Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Rob Clark a8623918 22ba8b6b

+181 -55
+84 -50
drivers/gpu/drm/msm/mdp4/mdp4_crtc.c
··· 26 26 struct drm_crtc base; 27 27 char name[8]; 28 28 struct drm_plane *plane; 29 + struct drm_plane *planes[8]; 29 30 int id; 30 31 int ovlp; 31 32 enum mdp4_dma dma; ··· 116 115 { 117 116 struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 118 117 struct mdp4_kms *mdp4_kms = get_kms(crtc); 119 - uint32_t flush = 0; 118 + uint32_t i, flush = 0; 120 119 121 - flush |= pipe2flush(mdp4_plane_pipe(mdp4_crtc->plane)); 120 + for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { 121 + struct drm_plane *plane = mdp4_crtc->planes[i]; 122 + if (plane) { 123 + enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); 124 + flush |= pipe2flush(pipe_id); 125 + } 126 + } 122 127 flush |= ovlp2flush(mdp4_crtc->ovlp); 123 128 124 129 DBG("%s: flush=%08x", mdp4_crtc->name, flush); ··· 212 205 struct mdp4_kms *mdp4_kms = get_kms(crtc); 213 206 int i, ovlp = mdp4_crtc->ovlp; 214 207 uint32_t mixer_cfg = 0; 208 + static const enum mdp4_mixer_stage_id stages[] = { 209 + STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3, 210 + }; 211 + /* statically (for now) map planes to mixer stage (z-order): */ 212 + static const int idxs[] = { 213 + [VG1] = 1, 214 + [VG2] = 2, 215 + [RGB1] = 0, 216 + [RGB2] = 0, 217 + [RGB3] = 0, 218 + [VG3] = 3, 219 + [VG4] = 4, 215 220 216 - /* 217 - * This probably would also need to be triggered by any attached 218 - * plane when it changes.. for now since we are only using a single 219 - * private plane, the configuration is hard-coded: 220 - */ 221 + }; 222 + bool alpha[4]= { false, false, false, false }; 221 223 222 224 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0); 223 225 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0); 224 226 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); 225 227 mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); 226 228 229 + /* TODO single register for all CRTCs, so this won't work properly 230 + * when multiple CRTCs are active.. 231 + */ 232 + for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { 233 + struct drm_plane *plane = mdp4_crtc->planes[i]; 234 + if (plane) { 235 + enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); 236 + int idx = idxs[pipe_id]; 237 + if (idx > 0) { 238 + const struct mdp4_format *format = 239 + to_mdp4_format(msm_framebuffer_format(plane->fb)); 240 + alpha[idx-1] = format->alpha_enable; 241 + } 242 + mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]); 243 + } 244 + } 245 + 246 + /* this shouldn't happen.. and seems to cause underflow: */ 247 + WARN_ON(!mixer_cfg); 248 + 227 249 for (i = 0; i < 4; i++) { 228 - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0); 229 - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0); 230 - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), 231 - MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | 232 - MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST)); 233 - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 0); 250 + uint32_t op; 251 + 252 + if (alpha[i]) { 253 + op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) | 254 + MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) | 255 + MDP4_OVLP_STAGE_OP_BG_INV_ALPHA; 256 + } else { 257 + op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | 258 + MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST); 259 + } 260 + 261 + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff); 262 + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00); 263 + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op); 264 + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1); 234 265 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0); 235 266 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0); 236 267 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0); 237 268 mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0); 238 269 } 239 270 240 - /* TODO single register for all CRTCs, so this won't work properly 241 - * when multiple CRTCs are active.. 242 - */ 243 - switch (mdp4_plane_pipe(mdp4_crtc->plane)) { 244 - case VG1: 245 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(STAGE_BASE) | 246 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 247 - break; 248 - case VG2: 249 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(STAGE_BASE) | 250 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 251 - break; 252 - case RGB1: 253 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(STAGE_BASE) | 254 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 255 - break; 256 - case RGB2: 257 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(STAGE_BASE) | 258 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 259 - break; 260 - case RGB3: 261 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(STAGE_BASE) | 262 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 263 - break; 264 - case VG3: 265 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(STAGE_BASE) | 266 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 267 - break; 268 - case VG4: 269 - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(STAGE_BASE) | 270 - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 271 - break; 272 - default: 273 - WARN_ON("invalid pipe"); 274 - break; 275 - } 276 271 mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg); 277 272 } 278 273 ··· 631 622 mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel); 632 623 } 633 624 625 + static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id, 626 + struct drm_plane *plane) 627 + { 628 + struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); 629 + 630 + BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes)); 631 + 632 + if (mdp4_crtc->planes[pipe_id] == plane) 633 + return; 634 + 635 + mdp4_crtc->planes[pipe_id] = plane; 636 + blend_setup(crtc); 637 + if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane)) 638 + crtc_flush(crtc); 639 + } 640 + 641 + void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane) 642 + { 643 + set_attach(crtc, mdp4_plane_pipe(plane), plane); 644 + } 645 + 646 + void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane) 647 + { 648 + set_attach(crtc, mdp4_plane_pipe(plane), NULL); 649 + } 650 + 634 651 static const char *dma_names[] = { 635 652 "DMA_P", "DMA_S", "DMA_E", 636 653 }; ··· 679 644 crtc = &mdp4_crtc->base; 680 645 681 646 mdp4_crtc->plane = plane; 682 - mdp4_crtc->plane->crtc = crtc; 683 647 684 648 mdp4_crtc->ovlp = ovlp_id; 685 649 mdp4_crtc->dma = dma_id;
+16
drivers/gpu/drm/msm/mdp4/mdp4_format.c
··· 44 44 FMT(BGR565, 0, 5, 6, 5, 2, 0, 1, 0, false, true, 2, 3), 45 45 }; 46 46 47 + uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats, 48 + uint32_t max_formats) 49 + { 50 + uint32_t i; 51 + for (i = 0; i < ARRAY_SIZE(formats); i++) { 52 + const struct mdp4_format *f = &formats[i]; 53 + 54 + if (i == max_formats) 55 + break; 56 + 57 + pixel_formats[i] = f->base.pixel_format; 58 + } 59 + 60 + return i; 61 + } 62 + 47 63 const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format) 48 64 { 49 65 int i;
+17
drivers/gpu/drm/msm/mdp4/mdp4_kms.c
··· 196 196 * for more than just RGB1->DMA_E->DTV->HDMI 197 197 */ 198 198 199 + /* construct non-private planes: */ 200 + plane = mdp4_plane_init(dev, VG1, false); 201 + if (IS_ERR(plane)) { 202 + dev_err(dev->dev, "failed to construct plane for VG1\n"); 203 + ret = PTR_ERR(plane); 204 + goto fail; 205 + } 206 + priv->planes[priv->num_planes++] = plane; 207 + 208 + plane = mdp4_plane_init(dev, VG2, false); 209 + if (IS_ERR(plane)) { 210 + dev_err(dev->dev, "failed to construct plane for VG2\n"); 211 + ret = PTR_ERR(plane); 212 + goto fail; 213 + } 214 + priv->planes[priv->num_planes++] = plane; 215 + 199 216 /* the CRTCs get constructed with a private plane: */ 200 217 plane = mdp4_plane_init(dev, RGB1, true); 201 218 if (IS_ERR(plane)) {
+46
drivers/gpu/drm/msm/mdp4/mdp4_kms.h
··· 133 133 } 134 134 } 135 135 136 + static inline uint32_t mixercfg(int mixer, enum mdp4_pipe pipe, 137 + enum mdp4_mixer_stage_id stage) 138 + { 139 + uint32_t mixer_cfg = 0; 140 + 141 + switch (pipe) { 142 + case VG1: 143 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) | 144 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); 145 + break; 146 + case VG2: 147 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) | 148 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); 149 + break; 150 + case RGB1: 151 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) | 152 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); 153 + break; 154 + case RGB2: 155 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) | 156 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); 157 + break; 158 + case RGB3: 159 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) | 160 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); 161 + break; 162 + case VG3: 163 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) | 164 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); 165 + break; 166 + case VG4: 167 + mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) | 168 + COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); 169 + break; 170 + default: 171 + WARN_ON("invalid pipe"); 172 + break; 173 + } 174 + 175 + return mixer_cfg; 176 + } 177 + 136 178 int mdp4_disable(struct mdp4_kms *mdp4_kms); 137 179 int mdp4_enable(struct mdp4_kms *mdp4_kms); 138 180 ··· 188 146 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 189 147 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc); 190 148 149 + uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *formats, 150 + uint32_t max_formats); 191 151 const struct msm_format *mdp4_get_format(struct msm_kms *kms, uint32_t format); 192 152 193 153 void mdp4_plane_install_properties(struct drm_plane *plane, ··· 210 166 void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc); 211 167 void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config); 212 168 void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf); 169 + void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane); 170 + void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane); 213 171 struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, 214 172 struct drm_plane *plane, int id, int ovlp_id, 215 173 enum mdp4_dma dma_id);
+15 -5
drivers/gpu/drm/msm/mdp4/mdp4_plane.c
··· 61 61 static int mdp4_plane_disable(struct drm_plane *plane) 62 62 { 63 63 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); 64 - DBG("%s: TODO", mdp4_plane->name); // XXX 64 + DBG("%s: disable", mdp4_plane->name); 65 + if (plane->crtc) 66 + mdp4_crtc_detach(plane->crtc, plane); 65 67 return 0; 66 68 } 67 69 ··· 143 141 src_w = src_w >> 16; 144 142 src_h = src_h >> 16; 145 143 144 + DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp4_plane->name, 145 + fb->base.id, src_x, src_y, src_w, src_h, 146 + crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h); 147 + 146 148 if (src_w != crtc_w) { 147 149 op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN; 148 150 /* TODO calc phasex_step */ ··· 197 191 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step); 198 192 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step); 199 193 200 - plane->crtc = crtc; 194 + /* TODO detach from old crtc (if we had more than one) */ 195 + mdp4_crtc_attach(crtc, plane); 201 196 202 197 return 0; 203 198 } ··· 219 212 struct drm_plane *mdp4_plane_init(struct drm_device *dev, 220 213 enum mdp4_pipe pipe_id, bool private_plane) 221 214 { 222 - struct msm_drm_private *priv = dev->dev_private; 223 215 struct drm_plane *plane = NULL; 224 216 struct mdp4_plane *mdp4_plane; 225 217 int ret; ··· 234 228 mdp4_plane->pipe = pipe_id; 235 229 mdp4_plane->name = pipe_names[pipe_id]; 236 230 237 - drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &mdp4_plane_funcs, 238 - mdp4_plane->formats, mdp4_plane->nformats, private_plane); 231 + mdp4_plane->nformats = mdp4_get_formats(pipe_id, mdp4_plane->formats, 232 + ARRAY_SIZE(mdp4_plane->formats)); 233 + 234 + drm_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, 235 + mdp4_plane->formats, mdp4_plane->nformats, 236 + private_plane); 239 237 240 238 mdp4_plane_install_properties(plane, &plane->base); 241 239
+3
drivers/gpu/drm/msm/msm_drv.h
··· 77 77 unsigned int num_iommus; 78 78 struct iommu_domain *iommus[NUM_DOMAINS]; 79 79 80 + unsigned int num_planes; 81 + struct drm_plane *planes[8]; 82 + 80 83 unsigned int num_crtcs; 81 84 struct drm_crtc *crtcs[8]; 82 85