[PATCH] drm/tidss: dispc: Rewrite naive plane positioning code
Jyri Sarha
jsarha at ti.com
Fri Feb 7 18:26:17 UTC 2020
On 07/02/2020 20:18, Jyri Sarha wrote:
> 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 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. This is easy since we have
> access to the whole atomic state when updating the CRTC configuration.
>
While implementing this fix it caught me by surprise that
crtc->state->state (pointer up to full atomic state) is NULL when
crtc_enable() or -flush() is called. So I take the plane-state directly
from the plane->state and just assume that it is pointing to the same
atomic state with the crtc state I am having. I that alraight?
Why is the crtc->state->state NULL? Is it a bug or is there some reason
to it?
Best regards,
Jyri
> Signed-off-by: Jyri Sarha <jsarha at ti.com>
> ---
> drivers/gpu/drm/tidss/tidss_crtc.c | 2 +-
> drivers/gpu/drm/tidss/tidss_dispc.c | 66 ++++++++++++++++++++---------
> 2 files changed, 47 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
> index 032c31ee2820..367efdebe2f8 100644
> --- a/drivers/gpu/drm/tidss/tidss_crtc.c
> +++ b/drivers/gpu/drm/tidss/tidss_crtc.c
> @@ -143,7 +143,7 @@ static void tidss_crtc_atomic_flush(struct drm_crtc *crtc,
> if (WARN_ON(!crtc->state->event))
> return;
>
> - /* Write vp properties to HW if needed. */
> + /* Write vp properties and plane positions to HW if needed. */
> dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, false);
>
> WARN_ON(drm_crtc_vblank_get(crtc) != 0);
> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
> index eeb160dc047b..cfc230d2a88a 100644
> --- a/drivers/gpu/drm/tidss/tidss_dispc.c
> +++ b/drivers/gpu/drm/tidss/tidss_dispc.c
> @@ -20,6 +20,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/regmap.h>
>
> +#include <drm/drm_atomic.h>
> #include <drm/drm_fourcc.h>
> #include <drm/drm_fb_cma_helper.h>
> #include <drm/drm_gem_cma_helper.h>
> @@ -281,11 +282,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 +303,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;
>
> @@ -1301,13 +1295,54 @@ 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)
> +static 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);
> }
>
> +static void dispc_vp_position_planes(struct dispc_device *dispc,
> + u32 hw_videoport,
> + const struct drm_crtc_state *cstate,
> + bool newmodeset)
> +{
> + struct drm_device *ddev = &dispc->tidss->ddev;
> + int zpos;
> +
> + if (!cstate->zpos_changed && !cstate->planes_changed && !newmodeset)
> + return;
> +
> + for (zpos = 0; zpos < dispc->feat->num_planes; zpos++) {
> + struct drm_plane *plane;
> + bool zpos_taken = false;
> +
> + drm_for_each_plane_mask(plane, ddev, cstate->plane_mask) {
> + if (WARN_ON(!plane->state))
> + continue;
> +
> + if (plane->state->normalized_zpos == zpos) {
> + zpos_taken = true;
> + break;
> + }
> + }
> +
> + if (zpos_taken) {
> + struct tidss_plane *tplane = to_tidss_plane(plane);
> + const struct drm_plane_state *pstate = plane->state;
> +
> + dispc_ovr_set_plane(dispc, tplane->hw_plane_id,
> + hw_videoport,
> + pstate->crtc_x, pstate->crtc_y,
> + zpos);
> + }
> + dispc_ovr_enable_layer(dispc, hw_videoport, zpos, zpos_taken);
> + }
> +}
> +
> /* CSC */
> enum csc_ctm {
> CSC_RR, CSC_RG, CSC_RB,
> @@ -2070,21 +2105,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;
> @@ -2566,6 +2591,7 @@ void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
> {
> dispc_vp_set_default_color(dispc, hw_videoport, 0);
> dispc_vp_set_color_mgmt(dispc, hw_videoport, state, newmodeset);
> + dispc_vp_position_planes(dispc, hw_videoport, state, newmodeset);
> }
>
> int dispc_runtime_suspend(struct dispc_device *dispc)
>
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
More information about the dri-devel
mailing list