aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
diff options
context:
space:
mode:
authorArchit Taneja <architt@codeaurora.org>2017-03-23 15:58:08 +0530
committerRob Clark <robdclark@gmail.com>2017-04-08 06:59:34 -0400
commitb7621b2a081c2ac2c1c54070f6e88f774fe4b6b1 (patch)
tree9ca03cdb13924df4cf35b48070fe1a05f0a81195 /drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
parentdrm/msm/mdp5: Add a CAP for Source Split (diff)
downloadlinux-dev-b7621b2a081c2ac2c1c54070f6e88f774fe4b6b1.tar.xz
linux-dev-b7621b2a081c2ac2c1c54070f6e88f774fe4b6b1.zip
drm/msm/mdp5: Add optional 'right' Layer Mixer in CRTC state
Add another mdp5_hw_mixer pointer (r_mixer) in mdp5_crtc_state. This mixer will be used to generate the right half of the scanout. With Source Split, a SSPP can now be connected to 2 Layer Mixers, but has to be at the same blend level (stage #) on both Layer Mixers. A drm_plane that has a lesser width than the max width supported, will comprise of a single SSPP/hwpipe, staged on both the Layer Mixers at the same blend level. A plane that is greater than max width will comprise of 2 SSPPs, with the 'left' SSPP staged on the left LM, and the 'right' SSPP staged on the right LM at the same blend level. For now, the drm_plane consists of only one SSPP, therefore, it needs to be staged on both the LMs in blend_setup() and mdp5_ctl_blend(). We'll extend this logic to support 2 hwpipes per plane later. The crtc cursor ops (using the LM cursors, not SSPP cursors) simply return an error if they're called when the right mixer is assigned to the CRTC state. With source split is enabled, we're expected to only SSPP cursors. This commit adds code that configures the right mixer, but the r_mixer itself isn't assigned at the moment. Signed-off-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c')
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 03a64bd39f22..82827f3e2a47 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -105,7 +105,7 @@ static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
static u32 crtc_flush_all(struct drm_crtc *crtc)
{
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
- struct mdp5_hw_mixer *mixer;
+ struct mdp5_hw_mixer *mixer, *r_mixer;
struct drm_plane *plane;
uint32_t flush_mask = 0;
@@ -120,6 +120,10 @@ static u32 crtc_flush_all(struct drm_crtc *crtc)
mixer = mdp5_cstate->pipeline.mixer;
flush_mask |= mdp_ctl_flush_mask_lm(mixer->lm);
+ r_mixer = mdp5_cstate->pipeline.r_mixer;
+ if (r_mixer)
+ flush_mask |= mdp_ctl_flush_mask_lm(r_mixer->lm);
+
return crtc_flush(crtc, flush_mask);
}
@@ -145,7 +149,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
if (ctl && !crtc->state->enable) {
/* set STAGE_UNUSED for all layers */
- mdp5_ctl_blend(ctl, pipeline, NULL, 0, 0);
+ mdp5_ctl_blend(ctl, pipeline, NULL, NULL, 0, 0);
/* XXX: What to do here? */
/* mdp5_crtc->ctl = NULL; */
}
@@ -187,6 +191,12 @@ static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage)
}
/*
+ * left/right pipe offsets for the stage array used in blend_setup()
+ */
+#define PIPE_LEFT 0
+#define PIPE_RIGHT 1
+
+/*
* blend_setup() - blend all the planes of a CRTC
*
* If no base layer is available, border will be enabled as the base layer.
@@ -205,10 +215,13 @@ static void blend_setup(struct drm_crtc *crtc)
const struct mdp_format *format;
struct mdp5_hw_mixer *mixer = pipeline->mixer;
uint32_t lm = mixer->lm;
+ struct mdp5_hw_mixer *r_mixer = pipeline->r_mixer;
+ uint32_t r_lm = r_mixer ? r_mixer->lm : 0;
struct mdp5_ctl *ctl = mdp5_cstate->ctl;
uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
unsigned long flags;
- enum mdp5_pipe stage[STAGE_MAX + 1] = { SSPP_NONE };
+ enum mdp5_pipe stage[STAGE_MAX + 1][MAX_PIPE_STAGE] = { SSPP_NONE };
+ enum mdp5_pipe r_stage[STAGE_MAX + 1][MAX_PIPE_STAGE] = { SSPP_NONE };
int i, plane_cnt = 0;
bool bg_alpha_enabled = false;
u32 mixer_op_mode = 0;
@@ -227,7 +240,15 @@ static void blend_setup(struct drm_crtc *crtc)
drm_atomic_crtc_for_each_plane(plane, crtc) {
pstate = to_mdp5_plane_state(plane->state);
pstates[pstate->stage] = pstate;
- stage[pstate->stage] = mdp5_plane_pipe(plane);
+ stage[pstate->stage][PIPE_LEFT] = mdp5_plane_pipe(plane);
+ /*
+ * if we have a right mixer, stage the same pipe as we
+ * have on the left mixer
+ */
+ if (r_mixer)
+ r_stage[pstate->stage][PIPE_LEFT] =
+ mdp5_plane_pipe(plane);
+
plane_cnt++;
}
@@ -293,12 +314,23 @@ static void blend_setup(struct drm_crtc *crtc)
blender(i)), fg_alpha);
mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(lm,
blender(i)), bg_alpha);
+ if (r_mixer) {
+ mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(r_lm,
+ blender(i)), blend_op);
+ mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(r_lm,
+ blender(i)), fg_alpha);
+ mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(r_lm,
+ blender(i)), bg_alpha);
+ }
}
mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm), mixer_op_mode);
+ if (r_mixer)
+ mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(r_lm),
+ mixer_op_mode);
- mdp5_ctl_blend(ctl, pipeline, stage, plane_cnt, ctl_blend_flags);
-
+ mdp5_ctl_blend(ctl, pipeline, stage, r_stage, plane_cnt,
+ ctl_blend_flags);
out:
spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
}
@@ -309,6 +341,7 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct mdp5_hw_mixer *mixer = mdp5_cstate->pipeline.mixer;
+ struct mdp5_hw_mixer *r_mixer = mdp5_cstate->pipeline.r_mixer;
uint32_t lm = mixer->lm;
unsigned long flags;
struct drm_display_mode *mode;
@@ -331,6 +364,10 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc)
mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(lm),
MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
+ if (r_mixer)
+ mdp5_write(mdp5_kms, REG_MDP5_LM_OUT_SIZE(r_mixer->lm),
+ MDP5_LM_OUT_SIZE_WIDTH(mode->hdisplay) |
+ MDP5_LM_OUT_SIZE_HEIGHT(mode->vdisplay));
spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
}
@@ -612,6 +649,10 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
if (!ctl)
return -EINVAL;
+ /* don't support LM cursors when we we have source split enabled */
+ if (mdp5_cstate->pipeline.r_mixer)
+ return -EINVAL;
+
if (!handle) {
DBG("Cursor off");
cursor_enable = false;
@@ -685,6 +726,10 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
uint32_t roi_h;
unsigned long flags;
+ /* don't support LM cursors when we we have source split enabled */
+ if (mdp5_cstate->pipeline.r_mixer)
+ return -EINVAL;
+
/* In case the CRTC is disabled, just drop the cursor update */
if (unlikely(!crtc->state->enable))
return 0;
@@ -714,12 +759,17 @@ mdp5_crtc_atomic_print_state(struct drm_printer *p,
{
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(state);
struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
+ struct mdp5_kms *mdp5_kms = get_kms(state->crtc);
if (WARN_ON(!pipeline))
return;
drm_printf(p, "\thwmixer=%s\n", pipeline->mixer ?
pipeline->mixer->name : "(null)");
+
+ if (mdp5_kms->caps & MDP_CAP_SRC_SPLIT)
+ drm_printf(p, "\tright hwmixer=%s\n", pipeline->r_mixer ?
+ pipeline->r_mixer->name : "(null)");
}
static void mdp5_crtc_reset(struct drm_crtc *crtc)