[PATCH RFC 04/11] drm/tilcdc: Add tilcdc_crtc_mode_set_nofb()
Daniel Vetter
daniel at ffwll.ch
Tue Apr 12 16:13:23 UTC 2016
On Mon, Apr 11, 2016 at 07:46:31PM +0300, Jyri Sarha wrote:
> 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 <jsarha at ti.com>
Yeah, if your hw always requires a primary plane then 2 bits needed: a)
make sure in the crtc's atomic_check it's there and set b) just use the
hooks whoever you want to. Atomic allows planes to be entirely independent
of the display pipeline, but doesn't require it really.
-Daniel
> ---
> drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 172 +++++++++++++++++++++++++++++++++++
> 1 file changed, 172 insertions(+)
>
> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> index 919c901..35f5682 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
> @@ -310,6 +310,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,
> @@ -526,6 +697,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)
> --
> 1.9.1
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list