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 /drivers/gpu/drm/msm/mdp4/mdp4_crtc.c | |
parent | 22ba8b6b230aa584171fb06c656157e752943ed0 (diff) | |
download | lwn-a862391871004bf8dea2299bb712aa93a512334a.tar.gz lwn-a862391871004bf8dea2299bb712aa93a512334a.zip |
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>
Diffstat (limited to 'drivers/gpu/drm/msm/mdp4/mdp4_crtc.c')
-rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_crtc.c | 136 |
1 files changed, 85 insertions, 51 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 { struct drm_crtc base; char name[8]; struct drm_plane *plane; + struct drm_plane *planes[8]; int id; int ovlp; enum mdp4_dma dma; @@ -115,9 +116,15 @@ static void crtc_flush(struct drm_crtc *crtc) { struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); struct mdp4_kms *mdp4_kms = get_kms(crtc); - uint32_t flush = 0; + uint32_t i, flush = 0; - flush |= pipe2flush(mdp4_plane_pipe(mdp4_crtc->plane)); + for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { + struct drm_plane *plane = mdp4_crtc->planes[i]; + if (plane) { + enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); + flush |= pipe2flush(pipe_id); + } + } flush |= ovlp2flush(mdp4_crtc->ovlp); DBG("%s: flush=%08x", mdp4_crtc->name, flush); @@ -205,67 +212,69 @@ static void blend_setup(struct drm_crtc *crtc) struct mdp4_kms *mdp4_kms = get_kms(crtc); int i, ovlp = mdp4_crtc->ovlp; uint32_t mixer_cfg = 0; - - /* - * This probably would also need to be triggered by any attached - * plane when it changes.. for now since we are only using a single - * private plane, the configuration is hard-coded: - */ + static const enum mdp4_mixer_stage_id stages[] = { + STAGE_BASE, STAGE0, STAGE1, STAGE2, STAGE3, + }; + /* statically (for now) map planes to mixer stage (z-order): */ + static const int idxs[] = { + [VG1] = 1, + [VG2] = 2, + [RGB1] = 0, + [RGB2] = 0, + [RGB3] = 0, + [VG3] = 3, + [VG4] = 4, + + }; + bool alpha[4]= { false, false, false, false }; mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW0(ovlp), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_LOW1(ovlp), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH0(ovlp), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_TRANSP_HIGH1(ovlp), 0); + /* TODO single register for all CRTCs, so this won't work properly + * when multiple CRTCs are active.. + */ + for (i = 0; i < ARRAY_SIZE(mdp4_crtc->planes); i++) { + struct drm_plane *plane = mdp4_crtc->planes[i]; + if (plane) { + enum mdp4_pipe pipe_id = mdp4_plane_pipe(plane); + int idx = idxs[pipe_id]; + if (idx > 0) { + const struct mdp4_format *format = + to_mdp4_format(msm_framebuffer_format(plane->fb)); + alpha[idx-1] = format->alpha_enable; + } + mixer_cfg |= mixercfg(mdp4_crtc->mixer, pipe_id, stages[idx]); + } + } + + /* this shouldn't happen.. and seems to cause underflow: */ + WARN_ON(!mixer_cfg); + for (i = 0; i < 4; i++) { - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0); - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0); - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), - MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | - MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST)); - mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 0); + uint32_t op; + + if (alpha[i]) { + op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_PIXEL) | + MDP4_OVLP_STAGE_OP_BG_ALPHA(FG_PIXEL) | + MDP4_OVLP_STAGE_OP_BG_INV_ALPHA; + } else { + op = MDP4_OVLP_STAGE_OP_FG_ALPHA(FG_CONST) | + MDP4_OVLP_STAGE_OP_BG_ALPHA(BG_CONST); + } + + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_FG_ALPHA(ovlp, i), 0xff); + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_BG_ALPHA(ovlp, i), 0x00); + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_OP(ovlp, i), op); + mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_CO3(ovlp, i), 1); mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW0(ovlp, i), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_LOW1(ovlp, i), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH0(ovlp, i), 0); mdp4_write(mdp4_kms, REG_MDP4_OVLP_STAGE_TRANSP_HIGH1(ovlp, i), 0); } - /* TODO single register for all CRTCs, so this won't work properly - * when multiple CRTCs are active.. - */ - switch (mdp4_plane_pipe(mdp4_crtc->plane)) { - case VG1: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE0(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1); - break; - case VG2: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE1(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1); - break; - case RGB1: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE2(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1); - break; - case RGB2: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE3(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1); - break; - case RGB3: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE4(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1); - break; - case VG3: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE5(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1); - break; - case VG4: - mixer_cfg = MDP4_LAYERMIXER_IN_CFG_PIPE6(STAGE_BASE) | - COND(mdp4_crtc->mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1); - break; - default: - WARN_ON("invalid pipe"); - break; - } mdp4_write(mdp4_kms, REG_MDP4_LAYERMIXER_IN_CFG, mixer_cfg); } @@ -622,6 +631,32 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf) mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel); } +static void set_attach(struct drm_crtc *crtc, enum mdp4_pipe pipe_id, + struct drm_plane *plane) +{ + struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); + + BUG_ON(pipe_id >= ARRAY_SIZE(mdp4_crtc->planes)); + + if (mdp4_crtc->planes[pipe_id] == plane) + return; + + mdp4_crtc->planes[pipe_id] = plane; + blend_setup(crtc); + if (mdp4_crtc->enabled && (plane != mdp4_crtc->plane)) + crtc_flush(crtc); +} + +void mdp4_crtc_attach(struct drm_crtc *crtc, struct drm_plane *plane) +{ + set_attach(crtc, mdp4_plane_pipe(plane), plane); +} + +void mdp4_crtc_detach(struct drm_crtc *crtc, struct drm_plane *plane) +{ + set_attach(crtc, mdp4_plane_pipe(plane), NULL); +} + static const char *dma_names[] = { "DMA_P", "DMA_S", "DMA_E", }; @@ -644,7 +679,6 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev, crtc = &mdp4_crtc->base; mdp4_crtc->plane = plane; - mdp4_crtc->plane->crtc = crtc; mdp4_crtc->ovlp = ovlp_id; mdp4_crtc->dma = dma_id; |