[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