drm/msm/mdp4: fix mixer setup for multi-crtc + planes
authorRob Clark <robdclark@gmail.com>
Fri, 21 Nov 2014 16:18:01 +0000 (11:18 -0500)
committerRob Clark <robdclark@gmail.com>
Fri, 21 Nov 2014 20:32:37 +0000 (15:32 -0500)
On mdp4 there is a single global LAYERMIXER_IN_CFG register.  The
previous logic to share that between multiple crtcs didn't actually
handle plane-disable very well.  Easier just to look at all of the
crtcs each time.

Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h

index fef22e8..6781aa9 100644 (file)
@@ -167,34 +167,54 @@ static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
        return true;
 }
 
-static void blend_setup(struct drm_crtc *crtc)
+/* statically (for now) map planes to mixer stage (z-order): */
+static const int idxs[] = {
+               [VG1]  = 1,
+               [VG2]  = 2,
+               [RGB1] = 0,
+               [RGB2] = 0,
+               [RGB3] = 0,
+               [VG3]  = 3,
+               [VG4]  = 4,
+
+};
+
+/* setup mixer config, for which we need to consider all crtc's and
+ * the planes attached to them
+ *
+ * TODO may possibly need some extra locking here
+ */
+static void setup_mixer(struct mdp4_kms *mdp4_kms)
 {
-       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-       struct mdp4_kms *mdp4_kms = get_kms(crtc);
-       struct drm_plane *plane;
-       int i, ovlp = mdp4_crtc->ovlp;
+       struct drm_mode_config *config = &mdp4_kms->dev->mode_config;
+       struct drm_crtc *crtc;
        uint32_t mixer_cfg = 0;
        static const enum mdp_mixer_stage_id stages[] = {
                        STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
        };
-       /* statically (for now) map planes to mixer stage (z-order): */
-       static const int idxs[] = {
-                       [VG1]  = 1,
-                       [VG2]  = 2,
-                       [RGB1] = 0,
-                       [RGB2] = 0,
-                       [RGB3] = 0,
-                       [VG3]  = 3,
-                       [VG4]  = 4,
 
-       };
-       bool alpha[4]= { false, false, false, false };
+       list_for_each_entry(crtc, &config->crtc_list, head) {
+               struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+               struct drm_plane *plane;
 
-       /* Don't rely on value read back from hw, but instead use our
-        * own shadowed value.  Possibly disable/reenable looses the
-        * previous value and goes back to power-on default?
-        */
-       mixer_cfg = mdp4_kms->mixer_cfg;
+               for_each_plane_on_crtc(crtc, plane) {
+                       enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
+                       int idx = idxs[pipe_id];
+                       mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
+                                       pipe_id, stages[idx]);
+               }
+       }
+
+       mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
+}
+
+static void blend_setup(struct drm_crtc *crtc)
+{
+       struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+       struct mdp4_kms *mdp4_kms = get_kms(crtc);
+       struct drm_plane *plane;
+       int i, ovlp = mdp4_crtc->ovlp;
+       bool alpha[4]= { false, false, false, false };
 
        mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
        mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
@@ -209,13 +229,8 @@ static void blend_setup(struct drm_crtc *crtc)
                                        to_mdp_format(msm_framebuffer_format(plane->fb));
                        alpha[idx-1] = format->alpha_enable;
                }
-               mixer_cfg = mixercfg(mixer_cfg, mdp4_crtc->mixer,
-                               pipe_id, stages[idx]);
        }
 
-       /* this shouldn't happen.. and seems to cause underflow: */
-       WARN_ON(!mixer_cfg);
-
        for (i = 0; i < 4; i++) {
                uint32_t op;
 
@@ -238,8 +253,7 @@ static void blend_setup(struct drm_crtc *crtc)
                mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
        }
 
-       mdp4_kms->mixer_cfg = mixer_cfg;
-       mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
+       setup_mixer(mdp4_kms);
 }
 
 static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc)
index 7706452..cbd77bc 100644 (file)
@@ -32,13 +32,6 @@ struct mdp4_kms {
 
        int rev;
 
-       /* Shadow value for MDP4_LAYERMIXER_IN_CFG.. since setup for all
-        * crtcs/encoders is in one shared register, we need to update it
-        * via read/modify/write.  But to avoid getting confused by power-
-        * on-default values after resume, use this shadow value instead:
-        */
-       uint32_t mixer_cfg;
-
        /* mapper-id used to request GEM buffer mapped for scanout: */
        int id;