26.03.2021 17:51, Thierry Reding пишет:
> From: Thierry Reding <[email protected]>
> 
> 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 <[email protected]>
> ---
>  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 <[email protected]>
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to