Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4dd14fe6 authored by Rob Clark's avatar Rob Clark
Browse files

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: default avatarRob Clark <robdclark@gmail.com>
parent d6ac4a84
Loading
Loading
Loading
Loading
+42 −28
Original line number Diff line number Diff line
@@ -167,16 +167,6 @@ static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
	return true;
}

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;
	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,
@@ -188,13 +178,43 @@ static void blend_setup(struct drm_crtc *crtc)
		[VG4]  = 4,

};
	bool alpha[4]= { false, false, false, false };

	/* 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?
/* 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
 */
	mixer_cfg = mdp4_kms->mixer_cfg;
static void setup_mixer(struct mdp4_kms *mdp4_kms)
{
	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,
	};

	list_for_each_entry(crtc, &config->crtc_list, head) {
		struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
		struct drm_plane *plane;

		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)
+0 −7
Original line number Diff line number Diff line
@@ -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;