mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
UPSTREAM: drm/tegra: dc: Implement hardware cursor on Tegra186 and later
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) Change-Id: I677aca7680f27b99f29c747f28e43fe4b0bd7c09 Signed-off-by: Thierry Reding <treding@nvidia.com> Reviewed-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2545942 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
98a160c54a
commit
7983dd9e4c
@@ -854,10 +854,14 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
|
|||||||
return &plane->base;
|
return &plane->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u32 tegra_cursor_plane_formats[] = {
|
static const u32 tegra_legacy_cursor_plane_formats[] = {
|
||||||
DRM_FORMAT_RGBA8888,
|
DRM_FORMAT_RGBA8888,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const u32 tegra_cursor_plane_formats[] = {
|
||||||
|
DRM_FORMAT_ARGB8888,
|
||||||
|
};
|
||||||
|
|
||||||
static int tegra_cursor_atomic_check(struct drm_plane *plane,
|
static int tegra_cursor_atomic_check(struct drm_plane *plane,
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
|
||||||
struct drm_atomic_state *state)
|
struct drm_atomic_state *state)
|
||||||
@@ -907,13 +911,25 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
|
|||||||
struct drm_plane_state *new_state = plane->state;
|
struct drm_plane_state *new_state = plane->state;
|
||||||
#endif
|
#endif
|
||||||
struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);
|
struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);
|
||||||
struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
|
struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
|
||||||
u32 value = CURSOR_CLIP_DISPLAY;
|
struct tegra_drm *tegra = plane->dev->dev_private;
|
||||||
|
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||||
|
u64 dma_mask = *dc->dev->dma_mask;
|
||||||
|
#endif
|
||||||
|
unsigned int x, y;
|
||||||
|
u32 value = 0;
|
||||||
|
|
||||||
/* rien ne va plus */
|
/* rien ne va plus */
|
||||||
if (!new_state->crtc || !new_state->fb)
|
if (!new_state->crtc || !new_state->fb)
|
||||||
return;
|
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) {
|
switch (new_state->crtc_w) {
|
||||||
case 32:
|
case 32:
|
||||||
value |= CURSOR_SIZE_32x32;
|
value |= CURSOR_SIZE_32x32;
|
||||||
@@ -941,7 +957,7 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
|
|||||||
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
|
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
#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);
|
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -953,15 +969,39 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
|
|||||||
value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
|
value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
|
||||||
value &= ~CURSOR_DST_BLEND_MASK;
|
value &= ~CURSOR_DST_BLEND_MASK;
|
||||||
value &= ~CURSOR_SRC_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_DST_BLEND_NEG_K1_TIMES_SRC;
|
||||||
value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
|
value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
|
||||||
value |= CURSOR_ALPHA;
|
value |= CURSOR_ALPHA;
|
||||||
tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
|
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 */
|
/* position the cursor */
|
||||||
value = (plane->state->crtc_y & 0x3fff) << 16 |
|
value = ((y & tegra->vmask) << 16) | (x & tegra->hmask);
|
||||||
(plane->state->crtc_x & 0x3fff);
|
|
||||||
tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
|
tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1020,8 +1060,13 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
|
|||||||
plane->index = 6;
|
plane->index = 6;
|
||||||
plane->dc = dc;
|
plane->dc = dc;
|
||||||
|
|
||||||
num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
|
if (!dc->soc->has_nvdisplay) {
|
||||||
formats = tegra_cursor_plane_formats;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
|
err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
|
||||||
&tegra_plane_funcs, formats,
|
&tegra_plane_funcs, formats,
|
||||||
|
|||||||
@@ -508,6 +508,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
|||||||
|
|
||||||
#define DC_DISP_CURSOR_START_ADDR_HI 0x4ec
|
#define DC_DISP_CURSOR_START_ADDR_HI 0x4ec
|
||||||
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1
|
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1
|
||||||
|
#define CURSOR_COMPOSITION_MODE_BLEND (0 << 25)
|
||||||
|
#define CURSOR_COMPOSITION_MODE_XOR (1 << 25)
|
||||||
#define CURSOR_MODE_LEGACY (0 << 24)
|
#define CURSOR_MODE_LEGACY (0 << 24)
|
||||||
#define CURSOR_MODE_NORMAL (1 << 24)
|
#define CURSOR_MODE_NORMAL (1 << 24)
|
||||||
#define CURSOR_DST_BLEND_ZERO (0 << 16)
|
#define CURSOR_DST_BLEND_ZERO (0 << 16)
|
||||||
@@ -702,6 +704,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
|
|||||||
#define PROTOCOL_MASK (0xf << 8)
|
#define PROTOCOL_MASK (0xf << 8)
|
||||||
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
|
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
|
||||||
|
|
||||||
|
#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442
|
||||||
|
#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446
|
||||||
|
|
||||||
#define DC_WIN_CORE_WINDOWGROUP_SET_CONTROL 0x702
|
#define DC_WIN_CORE_WINDOWGROUP_SET_CONTROL 0x702
|
||||||
#define OWNER_MASK (0xf << 0)
|
#define OWNER_MASK (0xf << 0)
|
||||||
#define OWNER(x) (((x) & 0xf) << 0)
|
#define OWNER(x) (((x) & 0xf) << 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user