[PATCH v2 05/10] drm/tegra: dc: Implement hardware cursor on Tegra186 and later

Dmitry Osipenko digetx at gmail.com
Fri Mar 26 15:58:02 UTC 2021


26.03.2021 17:51, Thierry Reding пишет:
> From: Thierry Reding <treding at nvidia.com>
> 
> The hardware cursor on Tegra186 differs slightly from the implementation
> on older SoC generations. In particular the new implementation relies on
> software for clipping the cursor against the screen. Fortunately, atomic
> KMS already computes clipped coordinates for (cursor) planes, so this is
> trivial to implement.
> 
> The format supported by the hardware cursor is also slightly different.
> 
> v2: use more drm_rect helpers (Dmitry)
> 
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
>  drivers/gpu/drm/tegra/dc.c | 59 ++++++++++++++++++++++++++++++++------
>  drivers/gpu/drm/tegra/dc.h |  5 ++++
>  2 files changed, 56 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
> index 0541d7b5c841..7758d64822ae 100644
> --- a/drivers/gpu/drm/tegra/dc.c
> +++ b/drivers/gpu/drm/tegra/dc.c
> @@ -832,10 +832,14 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
>  	return &plane->base;
>  }
>  
> -static const u32 tegra_cursor_plane_formats[] = {
> +static const u32 tegra_legacy_cursor_plane_formats[] = {
>  	DRM_FORMAT_RGBA8888,
>  };
>  
> +static const u32 tegra_cursor_plane_formats[] = {
> +	DRM_FORMAT_ARGB8888,
> +};
> +
>  static int tegra_cursor_atomic_check(struct drm_plane *plane,
>  				     struct drm_atomic_state *state)
>  {
> @@ -875,12 +879,22 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
>  									   plane);
>  	struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);
>  	struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
> -	u32 value = CURSOR_CLIP_DISPLAY;
> +	struct tegra_drm *tegra = plane->dev->dev_private;
> +	u64 dma_mask = *dc->dev->dma_mask;
> +	unsigned int x, y;
> +	u32 value = 0;
>  
>  	/* rien ne va plus */
>  	if (!new_state->crtc || !new_state->fb)
>  		return;
>  
> +	/*
> +	 * Legacy display supports hardware clipping of the cursor, but
> +	 * nvdisplay relies on software to clip the cursor to the screen.
> +	 */
> +	if (!dc->soc->has_nvdisplay)
> +		value |= CURSOR_CLIP_DISPLAY;
> +
>  	switch (new_state->crtc_w) {
>  	case 32:
>  		value |= CURSOR_SIZE_32x32;
> @@ -908,7 +922,7 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
>  	tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
>  
>  #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> -	value = (tegra_plane_state->iova[0] >> 32) & 0x3;
> +	value = (tegra_plane_state->iova[0] >> 32) & (dma_mask >> 32);
>  	tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
>  #endif
>  
> @@ -920,15 +934,39 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
>  	value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
>  	value &= ~CURSOR_DST_BLEND_MASK;
>  	value &= ~CURSOR_SRC_BLEND_MASK;
> -	value |= CURSOR_MODE_NORMAL;
> +
> +	if (dc->soc->has_nvdisplay)
> +		value &= ~CURSOR_COMPOSITION_MODE_XOR;
> +	else
> +		value |= CURSOR_MODE_NORMAL;
> +
>  	value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
>  	value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
>  	value |= CURSOR_ALPHA;
>  	tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
>  
> +	/* nvdisplay relies on software for clipping */
> +	if (dc->soc->has_nvdisplay) {
> +		struct drm_rect src;
> +
> +		x = new_state->dst.x1;
> +		y = new_state->dst.y1;
> +
> +		drm_rect_fp_to_int(&src, &new_state->src);
> +
> +		value = (src.y1 & tegra->vmask) << 16 | (src.x1 & tegra->hmask);
> +		tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR);
> +
> +		value = (drm_rect_height(&src) & tegra->vmask) << 16 |
> +			(drm_rect_width(&src) & tegra->hmask);
> +		tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR);
> +	} else {
> +		x = new_state->crtc_x;
> +		y = new_state->crtc_y;
> +	}
> +
>  	/* position the cursor */
> -	value = (new_state->crtc_y & 0x3fff) << 16 |
> -		(new_state->crtc_x & 0x3fff);
> +	value = ((y & tegra->vmask) << 16) | (x & tegra->hmask);
>  	tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
>  }
>  
> @@ -982,8 +1020,13 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
>  	plane->index = 6;
>  	plane->dc = dc;
>  
> -	num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
> -	formats = tegra_cursor_plane_formats;
> +	if (!dc->soc->has_nvdisplay) {
> +		num_formats = ARRAY_SIZE(tegra_legacy_cursor_plane_formats);
> +		formats = tegra_legacy_cursor_plane_formats;
> +	} else {
> +		num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
> +		formats = tegra_cursor_plane_formats;
> +	}

Will be nice to have all tegra_legacy_ renamed to the corresponding h/w
versions, like tegra124_; and not to use the inverted checks, like
!dc->soc->has_nvdisplay. I think this will ease following of the code.
But this should be done separately.

Reviewed-by: Dmitry Osipenko <digetx at gmail.com>


More information about the dri-devel mailing list