diff options
| author | Rob Clark <robdclark@gmail.com> | 2013-10-08 12:57:48 -0400 |
|---|---|---|
| committer | Rob Clark <robdclark@gmail.com> | 2013-11-01 12:39:44 -0400 |
| commit | a862391871004bf8dea2299bb712aa93a512334a (patch) | |
| tree | 89f8d1d779f133bd4d271378d4d7df1a0eceeeab | |
| parent | 22ba8b6b230aa584171fb06c656157e752943ed0 (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.c | 136 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_format.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_kms.c | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_kms.h | 46 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_plane.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 3 |
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 | ||
| 634 | static 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); | ||
| < | |||
