aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
diff options
context:
space:
mode:
authorjilai wang <jilaiw@codeaurora.org>2015-06-25 17:37:42 -0400
committerRob Clark <robdclark@gmail.com>2015-08-15 18:27:15 -0400
commit129877819c0a5f8d419fe67ae08a8a7c811afa5e (patch)
treedc093d220897efd68d1beecf5aed0078a45aff05 /drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
parent4ff696eafaa50d6d649d256d20528b475104a500 (diff)
drm/msm/mdp5: Add plane blending operation support for MDP5 (v2)
This change is to add properties alpha/zpos/blend_mode to mdp5 plane for alpha blending operation to generate the blended output. v1: Initial change v2: Change "premultilied" property to enum (Rob's comment) Signed-off-by: Jilai Wang <jilaiw@codeaurora.org> [Don't actually expose alpha/premultiplied props to userspace yet pending a chance for discussion and some userspace to exercise it] 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.c110
1 files changed, 76 insertions, 34 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 5a00f9fed8cb..572f57927595 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -160,7 +160,7 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
160 160
161 if (mdp5_crtc->ctl && !crtc->state->enable) { 161 if (mdp5_crtc->ctl && !crtc->state->enable) {
162 /* set STAGE_UNUSED for all layers */ 162 /* set STAGE_UNUSED for all layers */
163 mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000); 163 mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, NULL, 0, 0);
164 mdp5_ctl_release(mdp5_crtc->ctl); 164 mdp5_ctl_release(mdp5_crtc->ctl);
165 mdp5_crtc->ctl = NULL; 165 mdp5_crtc->ctl = NULL;
166 } 166 }
@@ -196,13 +196,9 @@ static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc,
196/* 196/*
197 * blend_setup() - blend all the planes of a CRTC 197 * blend_setup() - blend all the planes of a CRTC
198 * 198 *
199 * When border is enabled, the border color will ALWAYS be the base layer. 199 * If no base layer is available, border will be enabled as the base layer.
200 * Therefore, the first plane (private RGB pipe) will start at STAGE0. 200 * Otherwise all layers will be blended based on their stage calculated
201 * If disabled, the first plane starts at STAGE_BASE. 201 * in mdp5_crtc_atomic_check.
202 *
203 * Note:
204 * Border is not enabled here because the private plane is exactly
205 * the CRTC resolution.
206 */ 202 */
207static void blend_setup(struct drm_crtc *crtc) 203static void blend_setup(struct drm_crtc *crtc)
208{ 204{
@@ -210,9 +206,14 @@ static void blend_setup(struct drm_crtc *crtc)
210 struct mdp5_kms *mdp5_kms = get_kms(crtc); 206 struct mdp5_kms *mdp5_kms = get_kms(crtc);
211 struct drm_plane *plane; 207 struct drm_plane *plane;
212 const struct mdp5_cfg_hw *hw_cfg; 208 const struct mdp5_cfg_hw *hw_cfg;
213 uint32_t lm = mdp5_crtc->lm, blend_cfg = 0; 209 struct mdp5_plane_state *pstate, *pstates[STAGE_MAX + 1] = {NULL};
210 const struct mdp_format *format;
211 uint32_t lm = mdp5_crtc->lm;
212 uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
214 unsigned long flags; 213 unsigned long flags;
215#define blender(stage) ((stage) - STAGE_BASE) 214 uint8_t stage[STAGE_MAX + 1];
215 int i, plane_cnt = 0;
216#define blender(stage) ((stage) - STAGE0)
216 217
217 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); 218 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
218 219
@@ -222,33 +223,73 @@ static void blend_setup(struct drm_crtc *crtc)
222 if (!mdp5_crtc->ctl) 223 if (!mdp5_crtc->ctl)
223 goto out; 224 goto out;
224 225
226 /* Collect all plane information */
225 drm_atomic_crtc_for_each_plane(plane, crtc) { 227 drm_atomic_crtc_for_each_plane(plane, crtc) {
226 enum mdp_mixer_stage_id stage = 228 pstate = to_mdp5_plane_state(plane->state);
227 to_mdp5_plane_state(plane->state)->stage; 229 pstates[pstate->stage] = pstate;
230 stage[pstate->stage] = mdp5_plane_pipe(plane);
231 plane_cnt++;
232 }
228 233
229 /* 234 /*
230 * Note: This cannot happen with current implementation but 235 * If there is no base layer, enable border color.
231 * we need to check this condition once z property is added 236 * Although it's not possbile in current blend logic,
232 */ 237 * put it here as a reminder.
233 BUG_ON(stage > hw_cfg->lm.nb_stages); 238 */
239 if (!pstates[STAGE_BASE] && plane_cnt) {
240 ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT;
241 DBG("Border Color is enabled");
242 }
234 243
235 /* LM */ 244 /* The reset for blending */
236 mdp5_write(mdp5_kms, 245 for (i = STAGE0; i <= STAGE_MAX; i++) {
237 REG_MDP5_LM_BLEND_OP_MODE(lm, blender(stage)), 246 if (!pstates[i])
238 MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) | 247 continue;
239 MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST)); 248
249 format = to_mdp_format(
250 msm_framebuffer_format(pstates[i]->base.fb));
251 plane = pstates[i]->base.plane;
252 blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
253 MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST);
254 fg_alpha = pstates[i]->alpha;
255 bg_alpha = 0xFF - pstates[i]->alpha;
256 DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha);
257
258 if (format->alpha_enable && pstates[i]->premultiplied) {
259 blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_CONST) |
260 MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL);
261 if (fg_alpha != 0xff) {
262 bg_alpha = fg_alpha;
263 blend_op |=
264 MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA |
265 MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA;
266 } else {
267 blend_op |= MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA;
268 }
269 } else if (format->alpha_enable) {
270 blend_op = MDP5_LM_BLEND_OP_MODE_FG_ALPHA(FG_PIXEL) |
271 MDP5_LM_BLEND_OP_MODE_BG_ALPHA(FG_PIXEL);
272 if (fg_alpha != 0xff) {
273 bg_alpha = fg_alpha;
274 blend_op |=
275 MDP5_LM_BLEND_OP_MODE_FG_MOD_ALPHA |
276 MDP5_LM_BLEND_OP_MODE_FG_INV_MOD_ALPHA |
277 MDP5_LM_BLEND_OP_MODE_BG_MOD_ALPHA |
278 MDP5_LM_BLEND_OP_MODE_BG_INV_MOD_ALPHA;
279 } else {
280 blend_op |= MDP5_LM_BLEND_OP_MODE_BG_INV_ALPHA;
281 }
282 }
283
284 mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_OP_MODE(lm,
285 blender(i)), blend_op);
240 mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(lm, 286 mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_FG_ALPHA(lm,
241 blender(stage)), 0xff); 287 blender(i)), fg_alpha);
242 mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(lm, 288 mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_BG_ALPHA(lm,
243 blender(stage)), 0x00); 289 blender(i)), bg_alpha);
244 /* CTL */
245 blend_cfg |= mdp_ctl_blend_mask(mdp5_plane_pipe(plane), stage);
246 DBG("%s: blending pipe %s on stage=%d", mdp5_crtc->name,
247 pipe2name(mdp5_plane_pipe(plane)), stage);
248 } 290 }
249 291
250 DBG("%s: lm%d: blend config = 0x%08x", mdp5_crtc->name, lm, blend_cfg); 292 mdp5_ctl_blend(mdp5_crtc->ctl, lm, stage, plane_cnt, ctl_blend_flags);
251 mdp5_ctl_blend(mdp5_crtc->ctl, lm, blend_cfg);
252 293
253out: 294out:
254 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); 295 spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags);
@@ -339,7 +380,8 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
339 struct mdp5_kms *mdp5_kms = get_kms(crtc); 380 struct mdp5_kms *mdp5_kms = get_kms(crtc);
340 struct drm_plane *plane; 381 struct drm_plane *plane;
341 struct drm_device *dev = crtc->dev; 382 struct drm_device *dev = crtc->dev;
342 struct plane_state pstates[STAGE3 + 1]; 383 struct plane_state pstates[STAGE_MAX + 1];
384 const struct mdp5_cfg_hw *hw_cfg;
343 int cnt = 0, i; 385 int cnt = 0, i;
344 386
345 DBG("%s: check", mdp5_crtc->name); 387 DBG("%s: check", mdp5_crtc->name);
@@ -354,10 +396,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
354 /* verify that there are not too many planes attached to crtc 396 /* verify that there are not too many planes attached to crtc
355 * and that we don't have conflicting mixer stages: 397 * and that we don't have conflicting mixer stages:
356 */ 398 */
399 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
357 drm_atomic_crtc_state_for_each_plane(plane, state) { 400 drm_atomic_crtc_state_for_each_plane(plane, state) {
358 struct drm_plane_state *pstate; 401 struct drm_plane_state *pstate;
359 402 if (cnt >= (hw_cfg->lm.nb_stages)) {
360 if (cnt >= ARRAY_SIZE(pstates)) {
361 dev_err(dev->dev, "too many planes!\n"); 403 dev_err(dev->dev, "too many planes!\n");
362 return -EINVAL; 404 return -EINVAL;
363 } 405 }
@@ -369,13 +411,13 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
369 */ 411 */
370 if (!pstate) 412 if (!pstate)
371 pstate = plane->state; 413 pstate = plane->state;
372
373 pstates[cnt].plane = plane; 414 pstates[cnt].plane = plane;
374 pstates[cnt].state = to_mdp5_plane_state(pstate); 415 pstates[cnt].state = to_mdp5_plane_state(pstate);
375 416
376 cnt++; 417 cnt++;
377 } 418 }
378 419
420 /* assign a stage based on sorted zpos property */
379 sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); 421 sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
380 422
381 for (i = 0; i < cnt; i++) { 423 for (i = 0; i < cnt; i++) {