Skip to content

Commit

Permalink
drm/tilcdc: Add tilcdc_crtc_mode_set_nofb()
Browse files Browse the repository at this point in the history
commit f6382f1 upstream.

Add tilcdc_crtc_mode_set_nofb(). The mode_set_nofb() semantics do not
fit well to LCDC, because of the mandatory framebuffer. However, when
the primary plane is required in the check phase, it and the
framebuffer can be found from the atomic state struct.

Signed-off-by: Jyri Sarha <[email protected]>
  • Loading branch information
Jyri Sarha committed Aug 17, 2016
1 parent 8ff2aeb commit e6cbc04
Showing 1 changed file with 172 additions and 0 deletions.
172 changes: 172 additions & 0 deletions drivers/gpu/drm/tilcdc/tilcdc_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,177 @@ static void tilcdc_crtc_commit(struct drm_crtc *crtc)
tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}

static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct tilcdc_drm_private *priv = dev->dev_private;
const struct tilcdc_panel_info *info = tilcdc_crtc->info;
uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct drm_framebuffer *fb = crtc->primary->state->fb;

if (WARN_ON(!info))
return;

if (WARN_ON(!fb))
return;

pm_runtime_get_sync(dev->dev);

/* Configure the Burst Size and fifo threshold of DMA: */
reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
switch (info->dma_burst_sz) {
case 1:
reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
break;
case 2:
reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
break;
case 4:
reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
break;
case 8:
reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
break;
case 16:
reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
break;
default:
dev_err(dev->dev, "invalid burst size\n");
return;
}
reg |= (info->fifo_th << 8);
tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);

/* Configure timings: */
hbp = mode->htotal - mode->hsync_end;
hfp = mode->hsync_start - mode->hdisplay;
hsw = mode->hsync_end - mode->hsync_start;
vbp = mode->vtotal - mode->vsync_end;
vfp = mode->vsync_start - mode->vdisplay;
vsw = mode->vsync_end - mode->vsync_start;

DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);

/* Set AC Bias Period and Number of Transitions per Interrupt: */
reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);

/*
* subtract one from hfp, hbp, hsw because the hardware uses
* a value of 0 as 1
*/
if (priv->rev == 2) {
/* clear bits we're going to set */
reg &= ~0x78000033;
reg |= ((hfp-1) & 0x300) >> 8;
reg |= ((hbp-1) & 0x300) >> 4;
reg |= ((hsw-1) & 0x3c0) << 21;
}
tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);

reg = (((mode->hdisplay >> 4) - 1) << 4) |
(((hbp-1) & 0xff) << 24) |
(((hfp-1) & 0xff) << 16) |
(((hsw-1) & 0x3f) << 10);
if (priv->rev == 2)
reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);

reg = ((mode->vdisplay - 1) & 0x3ff) |
((vbp & 0xff) << 24) |
((vfp & 0xff) << 16) |
(((vsw-1) & 0x3f) << 10);
tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);

/*
* be sure to set Bit 10 for the V2 LCDC controller,
* otherwise limited to 1024 pixels width, stopping
* 1920x1080 being supported.
*/
if (priv->rev == 2) {
if ((mode->vdisplay - 1) & 0x400) {
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG,
LCDC_LPP_B10);
} else {
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG,
LCDC_LPP_B10);
}
}

/* Configure display type: */
reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK |
0x000ff000 /* Palette Loading Delay bits */);
reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
if (info->tft_alt_mode)
reg |= LCDC_TFT_ALT_ENABLE;
if (priv->rev == 2) {
unsigned int depth, bpp;

drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
switch (bpp) {
case 16:
break;
case 32:
reg |= LCDC_V2_TFT_24BPP_UNPACK;
/* fallthrough */
case 24:
reg |= LCDC_V2_TFT_24BPP_MODE;
break;
default:
dev_err(dev->dev, "invalid pixel format\n");
return;
}
}
reg |= info->fdd < 12;
tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);

if (info->invert_pxl_clk)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);

if (info->sync_ctrl)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);

if (info->sync_edge)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);

if (mode->flags & DRM_MODE_FLAG_NHSYNC)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);

if (mode->flags & DRM_MODE_FLAG_NVSYNC)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);

if (info->raster_order)
tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
else
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);

drm_framebuffer_reference(fb);

set_scanout(crtc, fb);

tilcdc_crtc_update_clk(crtc);

pm_runtime_put_sync(dev->dev);

crtc->hwmode = crtc->state->adjusted_mode;
}

static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
Expand Down Expand Up @@ -519,6 +690,7 @@ static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
.commit = tilcdc_crtc_commit,
.mode_set = tilcdc_crtc_mode_set,
.mode_set_base = tilcdc_crtc_mode_set_base,
.mode_set_nofb = tilcdc_crtc_mode_set_nofb,
};

int tilcdc_crtc_max_width(struct drm_crtc *crtc)
Expand Down

0 comments on commit e6cbc04

Please sign in to comment.