summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tidss/tidss_dispc.c
diff options
context:
space:
mode:
authorJyri Sarha <jsarha@ti.com>2020-02-27 14:00:52 +0200
committerJyri Sarha <jsarha@ti.com>2020-02-28 14:48:58 +0200
commitb33b54748866f7bc29696837c472f49413169d4e (patch)
tree85563d8f0987887e553b6bd537a8f55eee128490 /drivers/gpu/drm/tidss/tidss_dispc.c
parentd6b8bbca6bc83b9c57e528b28df6177b9b57e19d (diff)
downloadlinux-b33b54748866f7bc29696837c472f49413169d4e.tar.bz2
drm/tidss: dispc: Fix broken plane positioning code
The old implementation of placing planes on the CRTC while configuring the planes was naive and relied on the order in which the planes were configured, enabled, and disabled. The situation where a plane's zpos was changed on the fly was completely broken. The usual symptoms of this problem was scrambled display and a flood of sync lost errors, when a plane was active in two layers at the same time, or a missing plane, in case when a layer was accidentally disabled. The rewrite takes a more straight forward approach when HW is concerned. The plane positioning registers are in the CRTC (or actually OVR) register space and it is more natural to configure them in a one go when configuring the CRTC. To do this we need make sure we have all the planes on the updated CRTCs in the new atomic state. The untouched planes on CRTCs that need plane position update are added to the atomic state in tidss_atomic_check(). Signed-off-by: Jyri Sarha <jsarha@ti.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200227120052.23168-1-jsarha@ti.com
Diffstat (limited to 'drivers/gpu/drm/tidss/tidss_dispc.c')
-rw-r--r--drivers/gpu/drm/tidss/tidss_dispc.c55
1 files changed, 20 insertions, 35 deletions
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
index eeb160dc047b..e79dad246b1e 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -281,11 +281,6 @@ struct dss_vp_data {
u32 *gamma_table;
};
-struct dss_plane_data {
- u32 zorder;
- u32 hw_videoport;
-};
-
struct dispc_device {
struct tidss_device *tidss;
struct device *dev;
@@ -307,8 +302,6 @@ struct dispc_device {
struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
- struct dss_plane_data plane_data[TIDSS_MAX_PLANES];
-
u32 *fourccs;
u32 num_fourccs;
@@ -1247,7 +1240,7 @@ int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
/* OVR */
static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
u32 hw_plane, u32 hw_videoport,
- u32 x, u32 y, u32 zpos)
+ u32 x, u32 y, u32 layer)
{
/* On k2g there is only one plane and no need for ovr */
dispc_vid_write(dispc, hw_plane, DISPC_VID_K2G_POSITION,
@@ -1256,44 +1249,43 @@ static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc,
u32 hw_plane, u32 hw_videoport,
- u32 x, u32 y, u32 zpos)
+ u32 x, u32 y, u32 layer)
{
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
hw_plane, 4, 1);
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
x, 17, 6);
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
y, 30, 19);
}
static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc,
u32 hw_plane, u32 hw_videoport,
- u32 x, u32 y, u32 zpos)
+ u32 x, u32 y, u32 layer)
{
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
hw_plane, 4, 1);
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
x, 13, 0);
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(zpos),
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
y, 29, 16);
}
-static void dispc_ovr_set_plane(struct dispc_device *dispc,
- u32 hw_plane, u32 hw_videoport,
- u32 x, u32 y, u32 zpos)
+void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
+ u32 hw_videoport, u32 x, u32 y, u32 layer)
{
switch (dispc->feat->subrev) {
case DISPC_K2G:
dispc_k2g_ovr_set_plane(dispc, hw_plane, hw_videoport,
- x, y, zpos);
+ x, y, layer);
break;
case DISPC_AM65X:
dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport,
- x, y, zpos);
+ x, y, layer);
break;
case DISPC_J721E:
dispc_j721e_ovr_set_plane(dispc, hw_plane, hw_videoport,
- x, y, zpos);
+ x, y, layer);
break;
default:
WARN_ON(1);
@@ -1301,10 +1293,13 @@ static void dispc_ovr_set_plane(struct dispc_device *dispc,
}
}
-static void dispc_ovr_enable_plane(struct dispc_device *dispc,
- u32 hw_videoport, u32 zpos, bool enable)
+void dispc_ovr_enable_layer(struct dispc_device *dispc,
+ u32 hw_videoport, u32 layer, bool enable)
{
- OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(zpos),
+ if (dispc->feat->subrev == DISPC_K2G)
+ return;
+
+ OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
!!enable, 0, 0);
}
@@ -2070,21 +2065,11 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, 0,
28, 28);
- dispc_ovr_set_plane(dispc, hw_plane, hw_videoport,
- state->crtc_x, state->crtc_y,
- state->normalized_zpos);
-
- dispc->plane_data[hw_plane].zorder = state->normalized_zpos;
- dispc->plane_data[hw_plane].hw_videoport = hw_videoport;
-
return 0;
}
int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable)
{
- dispc_ovr_enable_plane(dispc, dispc->plane_data[hw_plane].hw_videoport,
- dispc->plane_data[hw_plane].zorder, enable);
-
VID_REG_FLD_MOD(dispc, hw_plane, DISPC_VID_ATTRIBUTES, !!enable, 0, 0);
return 0;