aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2013-10-08 12:57:48 -0400
committerRob Clark <robdclark@gmail.com>2013-11-01 12:39:44 -0400
commita862391871004bf8dea2299bb712aa93a512334a (patch)
tree89f8d1d779f133bd4d271378d4d7df1a0eceeeab
parent22ba8b6b230aa584171fb06c656157e752943ed0 (diff)
drm/msm: add plane support
Enable using VG1 and VG2 for planes. Currently YUV/CSC or scaling is not enabled, but ARGB and xRGB blending is. Signed-off-by: Rob Clark <robdclark@gmail.com> Acked-by: David Brown <davidb@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_crtc.c136
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_format.c16
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_kms.c17
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_kms.h46
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_plane.c20
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h3
6 files changed, 182 insertions, 56 deletions
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
index de6bea297cda..5a68aab66fa2 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
@@ -26,6 +26,7 @@ struct mdp4_crtc {
26 struct drm_crtc base; 26 struct drm_crtc base;
27 char name[8]; 27 char name[8];
28 struct drm_plane *plane; 28 struct drm_plane *plane;
29 struct drm_plane *planes[8];
29 int id; 30 int id;
30 int ovlp; 31 int ovlp;
31 enum mdp4_dma dma; 32 enum mdp4_dma dma;
@@ -115,9 +116,15 @@ static void crtc_flush(struct drm_crtc *crtc)
115{ 116{
116 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 117 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
117 struct mdp4_kms *mdp4_kms = get_kms(crtc); 118 struct mdp4_kms *mdp4_kms = get_kms(crtc);
118 uint32_t flush = 0; 119 uint32_t i, flush = 0;
119 120
120 flush |= pipe2flush(mdp4_plane_pipe(mdp4_crtc->plane)); 121 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
122 struct drm_plane *plane = mdp4_crtc->planes[i];
123 if (plane) {
124 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
125 flush |= pipe2flush(pipe_id);
126 }
127 }
121 flush |= ovlp2flush(mdp4_crtc->ovlp); 128 flush |= ovlp2flush(mdp4_crtc->ovlp);
122 129
123 DBG("%s: flush=%08x", mdp4_crtc->name, flush); 130 DBG("%s: flush=%08x", mdp4_crtc->name, flush);
@@ -205,67 +212,69 @@ static void blend_setup(struct drm_crtc *crtc)
205 struct mdp4_kms *mdp4_kms = get_kms(crtc); 212 struct mdp4_kms *mdp4_kms = get_kms(crtc);
206 int i, ovlp = mdp4_crtc->ovlp; 213 int i, ovlp = mdp4_crtc->ovlp;
207 uint32_t mixer_cfg = 0; 214 uint32_t mixer_cfg = 0;
208 215 static const enum mdp4_mixer_stage_id stages[] = {
209 /* 216 STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3,
210 * This probably would also need to be triggered by any attached 217 };
211 * plane when it changes.. for now since we are only using a single 218 /* statically (for now) map planes to mixer stage (z-order): */
212 * private plane, the configuration is hard-coded: 219 static const int idxs[] = {
213 */ 220 [VG1] = 1,
221 [VG2] = 2,
222 [RGB1] = 0,
223 [RGB2] = 0,
224 [RGB3] = 0,
225 [VG3] = 3,
226 [VG4] = 4,
227
228 };
229 bool alpha[4]= { false, false, false, false };
214 230
215 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0); 231 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0);
216 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0); 232 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0);
217 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); 233 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0);
218 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); 234 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0);
219 235
236 /* TODO single register for all CRTCs, so this won't work properly
237 * when multiple CRTCs are active..
238 */
239 for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) {
240 struct drm_plane *plane = mdp4_crtc->planes[i];
241 if (plane) {
242 enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane);
243 int idx = idxs[pipe_id];
244 if (idx > 0) {
245 const struct mdp4_format *format =
246 to_mdp4_format(msm_framebuffer_format(plane->fb));
247 alpha[idx-1] = format->alpha_enable;
248 }
249 mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]);
250 }
251 }
252
253 /* this shouldn't happen.. and seems to cause underflow: */
254 WARN_ON(!mixer_cfg);
255
220 for (i = 0; i < 4; i++) { 256 for (i = 0; i < 4; i++) {
221 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0); 257 uint32_t op;
222 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0); 258
223 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), 259 if (alpha[i]) {
224 MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | 260 op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) |
225 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST)); 261 MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) |
226 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 0); 262 MDP4_OVLP_STAGE_OP_BG_INV_ALPHA;
263 } else {
264 op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) |
265 MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST);
266 }
267
268 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff);
269 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00);
270 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op);
271 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1);
227 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0); 272 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0);
228 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0); 273 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0);
229 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0); 274 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0);
230 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0); 275 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0);
231 } 276 }
232 277
233 /* TODO single register for all CRTCs, so this won't work properly
234 * when multiple CRTCs are active..
235 */
236 switch (mdp4_plane_pipe(mdp4_crtc->plane)) {
237 case VG1:
238 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(STAGE_BASE) |
239 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
240 break;
241 case VG2:
242 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(STAGE_BASE) |
243 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
244 break;
245 case RGB1:
246 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(STAGE_BASE) |
247 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
248 break;
249 case RGB2:
250 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(STAGE_BASE) |
251 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
252 break;
253 case RGB3:
254 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(STAGE_BASE) |
255 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
256 break;
257 case VG3:
258 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(STAGE_BASE) |
259 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
260 break;
261 case VG4:
262 mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(STAGE_BASE) |
263 COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
264 break;
265 default:
266 WARN_ON("invalid pipe");
267 break;
268 }
269 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg); 278 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg);
270} 279}
271 280
@@ -622,6 +631,32 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf)
622 mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel); 631 mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
623} 632}
624 633
634static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id,
635 struct drm_plane *plane)
636{
637 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
638
639 BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes));
640
641 if (mdp4_crtc->planes[pipe_id] == plane)
642 return;
643
644 mdp4_crtc->planes[pipe_id] = plane;
645 blend_setup(crtc);
646 if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane))
647 crtc_flush(crtc);
<