summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-11-21 11:18:01 -0500
committerRob Clark <robdclark@gmail.com>2014-11-21 15:32:37 -0500
commit4dd14fe6fb8119d1d8c87127ebc74c63deb2ffc8 (patch)
tree4940f4f16fe5b56b6eb4effca02071887e46afed /drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
parentd6ac4a84e7a3713929ec473cb8c10acc1dec41a2 (diff)
drm/msm/mdp4: fix mixer setup for multi-crtc + planes
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>
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c')
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index fef22e8cabb6..6781aa994613 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -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)