drm/msm/mdp5: Cursor plane stuff
cover drm/msm/mdp5: Cursor plane stuff
This series does some mdp5_plane related clean ups (use plane helpers for clipping etc), adds MDP5 bits needed for cursor plane blocks, and then add cursor planes.
On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and that's implemented in mdp5_crtc.c. With newer hardware, the cursor blocks look exactly like MDP5 pipes (SSPPs).
The "faster than vblank cursor position update stuff" has been copied from vc4 and the patches posted recently by Maarten for Intel:
https://patchwork.kernel.org/patch/9466417/
I've tried this with some X11 UI and modetest -C, and it seems to work okay. Are there any tests that mix up atomic commits and legacy cursor updates a lot to identify issues?
Archit Taneja (9):
drm/msm/mdp5: cfg: Add pipe_cursor block drm/msm/mdp5: Update generated headers
drm/msm/mdp5: Prepare CRTC/LM for empty stages drm/msm/mdp5: Use plane helpers to configure src/dst rectangles drm/msm/mdp5: Configure COLOR3_OUT propagation drm/msm/mdp5: Misc cursor plane bits
drm/msm/mdp5: Refactor mdp5_plane_atomic_check
HACK: drm/msm/mdp5: Add support for legacy cursor updates drm/msm/mdp5: Add cursor planes
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 30 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 73 +++++++++++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 14 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 38 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 8 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 ++++++++++++++++++++++++++---- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + drivers/gpu/drm/msm/msm_atomic.c | 26 +++-- 12 files changed, 334 insertions(+), 60 deletions(-)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/9 drm/msm/mdp5: cfg: Add pipe_cursor block
Define the block in advance so that the generated mdp5.xml.h doesn't break build.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +1 -0
@@ -85,6 +85,7 @@ struct mdp5_cfg_hw {struct mdp5_pipe_block pipe_vig;struct mdp5_pipe_block pipe_rgb;struct mdp5_pipe_block pipe_dma; +struct mdp5_pipe_block pipe_cursor;struct mdp5_lm_block lm;struct mdp5_sub_block dspp;struct mdp5_sub_block ad;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 2/9 drm/msm/mdp5: Update generated headers
In reply to Archit Taneja--- drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +20 -10
@@ -65,16 +65,19 @@ enum mdp5_intfnum { };enum mdp5_pipe { -SSPP_VIG0 =0 , -SSPP_VIG1 =1 , -SSPP_VIG2 =2 , -SSPP_RGB0 =3 , -SSPP_RGB1 =4 , -SSPP_RGB2 =5 , -SSPP_DMA0 =6 , -SSPP_DMA1 =7 , -SSPP_VIG3 =8 , -SSPP_RGB3 =9 , +SSPP_NONE =0 , +SSPP_VIG0 =1 , +SSPP_VIG1 =2 , +SSPP_VIG2 =3 , +SSPP_RGB0 =4 , +SSPP_RGB1 =5 , +SSPP_RGB2 =6 , +SSPP_DMA0 =7 , +SSPP_DMA1 =8 , +SSPP_VIG3 =9 , +SSPP_RGB3 =10 , +SSPP_CURSOR0 =11 , +SSPP_CURSOR1 =12 , };enum mdp5_ctl_mode {
@@ -532,6 +535,7 @@ static inline uint32_t MDP5_CTL_LAYER_EXT_REG_CURSOR1(enum mdp_mixer_stage_id vastatic inline uint32_t __offset_PIPE (enum mdp5_pipe idx) {switch (idx) { +case SSPP_NONE :return (INVALID_IDX (idx));case SSPP_VIG0 :return (mdp5_cfg->pipe_vig.base[0 ]);case SSPP_VIG1 :return (mdp5_cfg->pipe_vig.base[1 ]);case SSPP_VIG2 :return (mdp5_cfg->pipe_vig.base[2 ]);
@@ -542,6 +546,8 @@ static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)case SSPP_DMA1 :return (mdp5_cfg->pipe_dma.base[1 ]);case SSPP_VIG3 :return (mdp5_cfg->pipe_vig.base[3 ]);case SSPP_RGB3 :return (mdp5_cfg->pipe_rgb.base[3 ]); +case SSPP_CURSOR0 :return (mdp5_cfg->pipe_cursor.base[0 ]); +case SSPP_CURSOR1 :return (mdp5_cfg->pipe_cursor.base[1 ]);default :return INVALID_IDX (idx); } }
@@ -1073,6 +1079,10 @@ static inline uint32_t __offset_LM(uint32_t idx)#define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA 0x00000004#define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA 0x00000008#define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA 0x00000010 +#define MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA 0x00000020 +#define MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA 0x00000040 +#define MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA 0x00000080 +#define MDP5_LM_BLEND_COLOR_OUT_SPLIT_LEFT_RIGHT 0x80000000static inline uint32_t REG_MDP5_LM_OUT_SIZE (uint32_t i0) {return 0x00000004 +__offset_LM (i0); }#define MDP5_LM_OUT_SIZE_HEIGHT__MASK 0xffff0000
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 3/9 drm/msm/mdp5: Prepare CRTC/LM for empty stages
In reply to Archit TanejaUse SSPP_NONE in mdp5_plane_pipe() if there is now hwpipe allocated for the drm_plane. Returning '0' means we are returning VIG0 pipe.
Also, use the mdp5_pipe enum to pass around the stage array. Initialize the stage to SSPP_NONE by default.
We do the above because 1) Cursor plane has to be staged at the topmost blender of the LM, which can result in empty stages in between 2) In the future, when we support multiple LMs per CRTC. We could have stages which don't have any pipe assigned to them.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 4 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 4 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +1 -1
@@ -195,7 +195,7 @@ static void blend_setup(struct drm_crtc *crtc)uint32_t lm = mdp5_crtc->lm;uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags =0 ;unsigned long flags; -uint8_t stage[STAGE_MAX +1 ]; +enum mdp5_pipe stage[STAGE_MAX +1 ] = {SSPP_NONE };int i, plane_cnt =0 ;#define blender (stage) ((stage) - STAGE0)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +2 -2
@@ -351,8 +351,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe, } } -int mdp5_ctl_blend (struct mdp5_ctl *ctl,u8 *stage,u32 stage_cnt, -u32 ctl_blend_op_flags) +int mdp5_ctl_blend (struct mdp5_ctl *ctl,enum mdp5_pipe *stage,u32 stage_cnt, +u32 ctl_blend_op_flags) {unsigned long flags;u32 blend_cfg =0 , blend_ext_cfg =0 ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h +2 -2
@@ -56,8 +56,8 @@ int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,* (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask) */ #define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT BIT(0) -int mdp5_ctl_blend (struct mdp5_ctl *ctl,u8 *stage,u32 stage_cnt, -u32 ctl_blend_op_flags); +int mdp5_ctl_blend (struct mdp5_ctl *ctl,enum mdp5_pipe *stage,u32 stage_cnt, +u32 ctl_blend_op_flags);/** * mdp_ctl_flush_mask...() - Register FLUSH masks
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +1 -1
@@ -836,7 +836,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)struct mdp5_plane_state *pstate =to_mdp5_plane_state (plane->state);if (WARN_ON (!pstate->hwpipe)) -return 0 ; +return SSPP_NONE ;return pstate->hwpipe->pipe; }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 4/9 drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
In reply to Archit TanejaThe MDP5 plane's atomic_check ops doesn't perform clipping tests. This didn't hurt us much in the past, but clipping becomes important with cursor planes.
Use drm_plane_helper_check_state, the way rockchip/intel/mtk drivers already do. Clipping requires knowledge of the crtc width and height. This requires us to call drm_atomic_helper_check_modeset before drm_atomic_helper_check_planes in the driver's atomic_check op, because check_modetest will populate the mode for the crtc, needed to populate the clip rectangle.
We also replace the plane_enabled(state) local helper with state->visible, since they both represent the same thing (i.e, whether state->fb and state->crtc are non-NULL or not).
One issue with the existing code is that we don't have a way to disable the plane when it's completely clipped out. Until there isn't an update on the crtc (which would de-stage the plane), we would still see the plane in its last 'visible' configuration.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 59 +++++++++++++++++++++++-------- drivers/gpu/drm/msm/msm_atomic.c | 21 +++++++---- 2 files changed, 60 insertions(+), 20 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +45 -14
@@ -29,10 +29,7 @@ struct mdp5_plane {static int mdp5_plane_mode_set (struct drm_plane *plane,struct drm_crtc *crtc,struct drm_framebuffer *fb, -int crtc_x,int crtc_y, -unsigned int crtc_w,unsigned int crtc_h, -uint32_t src_x,uint32_t src_y, -uint32_t src_w,uint32_t src_h); +struct drm_rect *src,struct drm_rect *dest);static void set_scanout_locked (struct drm_plane *plane,struct drm_framebuffer *fb);
@@ -275,6 +272,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,msm_framebuffer_cleanup (fb, mdp5_kms->id); } +#define FRAC_16_16 (mult, div) (((mult) << 16) / (div))static int mdp5_plane_atomic_check (struct drm_plane *plane,struct drm_plane_state *state) {
@@ -283,11 +281,20 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,struct mdp5_cfg *config =mdp5_cfg_get_config (get_kms (plane)->cfg);bool new_hwpipe = false;uint32_t max_width, max_height; +struct drm_crtc *crtc; +struct drm_crtc_state *crtc_state; +struct drm_rect clip; +int min_scale, max_scale;uint32_t caps =0 ; +int ret;DBG ("%s: check (%d -> %d)" , plane->name,plane_enabled (old_state),plane_enabled (state)); + crtc = state->crtc ? state->crtc : plane->state->crtc; +if (!crtc) +return 0 ; +/* We don't allow faster-than-vblank updates.. if we did add this * some day, we would need to disallow in cases where hwpipe * changes
@@ -306,7 +313,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return -ERANGE ; } -if (plane_enabled (state)) { + crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); +if (WARN_ON (!crtc_state)) +return -EINVAL ; + + clip.x1 =0 ; + clip.y1 =0 ; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + min_scale =FRAC_16_16 (1 ,8 ); + max_scale =FRAC_16_16 (8 ,1 ); + + ret =drm_plane_helper_check_state (state, &clip, min_scale, + max_scale, true, true); +if (ret) +return ret; + +if (state->visible) {unsigned int rotation;const struct mdp_format *format;struct mdp5_kms *mdp5_kms =get_kms (plane);
@@ -376,15 +399,12 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, mdp5_state->pending = true; -if (plane_enabled (state)) { +if (state->visible) {int ret; ret =mdp5_plane_mode_set (plane, state->crtc, state->fb, - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - state->src_x, state->src_y, - state->src_w, state->src_h); + &state->src, &state->dst);/* atomic_check should have ensured that this doesn't fail */ WARN_ON (ret <0 ); }
@@ -677,10 +697,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,static int mdp5_plane_mode_set (struct drm_plane *plane,struct drm_crtc *crtc,struct drm_framebuffer *fb, -int crtc_x,int crtc_y, -unsigned int crtc_w,unsigned int crtc_h, -uint32_t src_x,uint32_t src_y, -uint32_t src_w,uint32_t src_h) +struct drm_rect *src,struct drm_rect *dest) {struct drm_plane_state *pstate = plane->state;struct mdp5_hw_pipe *hwpipe =to_mdp5_plane_state (pstate)->hwpipe;
@@ -696,6 +713,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,uint32_t pix_format;unsigned int rotation;bool vflip, hflip; +int crtc_x, crtc_y; +unsigned int crtc_w, crtc_h; +uint32_t src_x, src_y; +uint32_t src_w, src_h;unsigned long flags;int ret;
@@ -708,6 +729,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, format =to_mdp_format (msm_framebuffer_format (fb)); pix_format = format->base.pixel_format; + src_x = src->x1; + src_y = src->y1; + src_w =drm_rect_width (src); + src_h =drm_rect_height (src); + + crtc_x = dest->x1; + crtc_y = dest->y1; + crtc_w =drm_rect_width (dest); + crtc_h =drm_rect_height (dest); +/* src values are in Q16 fixed point, convert to integer: */ src_x = src_x >>16 ; src_y = src_y >>16 ;
drivers/gpu/drm/msm/msm_atomic.c +15 -6
@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work) complete_commit(container_of(work, struct msm_commit, work), true); } +/* +* this func is identical to the drm_atomic_helper_check, but we keep this +* because we might eventually need to have a more finegrained check +* sequence without using the atomic helpers. +* +* In the past, we first called drm_atomic_helper_check_planes, and then +* drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's +* ->atomic_check could update ->mode_changed for pixel format changes. +* This, however isn't needed now because if there is a pixel format change, +* we just assign a new hwpipe for it with a new SMP allocation. We might +* eventually hit a condition where we would need to do a full modeset if +* we run out of planes. There, we'd probably need to set mode_changed. +*/ int msm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state) {int ret; -/* -* msm ->atomic_check can update ->mode_changed for pixel format -* changes, hence must be run before we check the modeset changes. -*/ - ret =drm_atomic_helper_check_planes (dev, state); + ret =drm_atomic_helper_check_modeset (dev, state);if (ret)return ret; - ret =drm_atomic_helper_check_modeset (dev, state); + ret =drm_atomic_helper_check_planes (dev, state);if (ret)return ret;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 5/9 drm/msm/mdp5: Configure COLOR3_OUT propagation
In reply to Archit TanejaIn MDP5 Layer Mixer HW, the blender output is only the blended color components (i.e R, G and B, or COLOR0/1/2 in MDP5 HW terminology). This is fed to the BG input of the next blender. We also need to provide an alpha (COLOR3) value for the BG input at the next stage.
This is configured via using the REG_MDP5_LM_BLEND_COLOR_OUT register. For each stage, we can propagate either the BG or FG alpha to the next stage.
The approach taken by the driver is to propagate FG alpha, if the plane staged on that blender has an alpha. If it doesn't, we try to propagate the base layer's alpha.
This is borrowed from downstream MDP5 kernel driver. Without this, we don't see any cursor plane content.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +30 -0
@@ -177,6 +177,21 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc)kfree (mdp5_crtc); } +static inline u32 mdp5_lm_use_fg_alpha_mask (enum mdp_mixer_stage_id stage) +{ +switch (stage) { +case STAGE0 :return MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA ; +case STAGE1 :return MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA ; +case STAGE2 :return MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA ; +case STAGE3 :return MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA ; +case STAGE4 :return MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA ; +case STAGE5 :return MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA ; +case STAGE6 :return MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA ; +default : +return 0 ; + } +} +/* * blend_setup() - blend all the planes of a CRTC *
@@ -197,6 +212,8 @@ static void blend_setup(struct drm_crtc *crtc)unsigned long flags;enum mdp5_pipe stage[STAGE_MAX +1 ] = {SSPP_NONE };int i, plane_cnt =0 ; +bool bg_alpha_enabled = false; +u32 mixer_op_mode =0 ;#define blender (stage) ((stage) - STAGE0) hw_cfg =mdp5_cfg_get_hw_config (mdp5_kms->cfg);
@@ -218,6 +235,11 @@ static void blend_setup(struct drm_crtc *crtc)if (!pstates[STAGE_BASE ]) { ctl_blend_flags |=MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT ;DBG ("Border Color is enabled" ); + }else if (plane_cnt) { + format =to_mdp_format (msm_framebuffer_format (pstates[STAGE_BASE ]->base.fb)); + +if (format->alpha_enable) + bg_alpha_enabled = true; }/* The reset for blending */
@@ -232,6 +254,12 @@ static void blend_setup(struct drm_crtc *crtc)MDP5_LM_BLEND_OP_MODE_BG_ALPHA (BG_CONST ); fg_alpha = pstates[i]->alpha; bg_alpha =0xFF - pstates[i]->alpha; + +if (!format->alpha_enable && bg_alpha_enabled) + mixer_op_mode =0 ; +else + mixer_op_mode |=mdp5_lm_use_fg_alpha_mask (i); +DBG ("Stage %d fg_alpha %x bg_alpha %x" , i, fg_alpha, bg_alpha);if (format->alpha_enable && pstates[i]->premultiplied) {
@@ -268,6 +296,8 @@ static void blend_setup(struct drm_crtc *crtc) blender(i)), bg_alpha); } +mdp5_write (mdp5_kms,REG_MDP5_LM_BLEND_COLOR_OUT (lm), mixer_op_mode); +mdp5_ctl_blend (mdp5_crtc->ctl, stage, plane_cnt, ctl_blend_flags); out:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 6/9 drm/msm/mdp5: Misc cursor plane bits
In reply to Archit TanejaThese are various changes in preparation for cursor planes:
- Add a pipe_cursor block for 8x96 in mdp5_cfg.
- Add a new pipe CAP called MDP_PIPE_CAP_CURSOR. Use this to ensure we assign a cursor SSPP for a drm_plane with type DRM_PLANE_TYPE_CURSOR.
- Update mdp5_ctl_blend/ext_blend masks to incorporate cursor SSPPs.
- In mdp5_crtc_atomic_check, make sure that the cursor plane has the highest zorder, and stage the cursor plane to the maximum stage # present on the HW.
- Create drm_crtc_funcs that doesn't try to implement cursors using the older LM cursor HW.
- Pass drm_plane_type in mdp5_plane_init instead of a bool telling whether plane is primary or not.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 +++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 34 +++++++++++++++++++++++++++---- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 10 +++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 10 +++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 7 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 7 ++++--- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + 8 files changed, 74 insertions(+), 13 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +10 -0
@@ -421,6 +421,16 @@ struct mdp5_cfg_handler {MDP_PIPE_CAP_SW_PIX_EXT | 0, }, + .pipe_cursor = { + .count = 2, + .base = { 0x34000, 0x36000 }, + .caps = MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_SW_PIX_EXT | +MDP_PIPE_CAP_CURSOR | + 0, + }, + .lm = { .count =6 , .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +30 -4
@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,struct plane_state pstates[STAGE_MAX +1 ];const struct mdp5_cfg_hw *hw_cfg;const struct drm_plane_state *pstate; +bool cursor_plane = false;int cnt =0 , base =0 , i;DBG ("%s: check" , crtc->name);
@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, pstates[cnt].state =to_mdp5_plane_state (pstate); cnt++; + +if (plane->type ==DRM_PLANE_TYPE_CURSOR ) + cursor_plane = true; }/* assign a stage based on sorted zpos property */
@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,if ((cnt >0 ) && !is_fullscreen (state, &pstates[0 ].state->base)) base++; +/* trigger a warning if cursor isn't the highest zorder */ +WARN_ON (cursor_plane && + (pstates[cnt -1 ].plane->type !=DRM_PLANE_TYPE_CURSOR )); +/* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: */
@@ -431,7 +439,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, }for (i =0 ; i < cnt; i++) { - pstates[i].state->stage =STAGE_BASE + i + base; +if (cursor_plane && (i == (cnt -1 ))) + pstates[i].state->stage = hw_cfg->lm.nb_stages; +else + pstates[i].state->stage =STAGE_BASE + i + base;DBG ("%s: assign pipe %s on stage=%d" , crtc->name, pstates[i].plane->name, pstates[i].state->stage);
@@ -642,6 +653,16 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) .cursor_move = mdp5_crtc_cursor_move, }; +static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { + .set_config = drm_atomic_helper_set_config, + .destroy = mdp5_crtc_destroy, + .page_flip = drm_atomic_helper_page_flip, + .set_property = drm_atomic_helper_crtc_set_property, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; +static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_nofb = mdp5_crtc_mode_set_nofb, .disable = mdp5_crtc_disable,
@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)/* initialize crtc */ struct drm_crtc *mdp5_crtc_init (struct drm_device *dev, -struct drm_plane *plane,int id) +struct drm_plane *plane, +struct drm_plane *cursor_plane,int id) {struct drm_crtc *crtc =NULL ;struct mdp5_crtc *mdp5_crtc;
@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq; mdp5_crtc->err.irq = mdp5_crtc_err_irq; -drm_crtc_init_with_planes (dev, crtc, plane,NULL , &mdp5_crtc_funcs, -NULL ); +if (cursor_plane) +drm_crtc_init_with_planes (dev, crtc, plane, cursor_plane, + &mdp5_crtc_no_lm_cursor_funcs,NULL ); +else +drm_crtc_init_with_planes (dev, crtc, plane,NULL , + &mdp5_crtc_funcs,NULL );drm_flip_work_init (&mdp5_crtc->unref_cursor_work,"unref cursor" , unref_cursor_worker);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +8 -2
@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,case SSPP_DMA1 :return MDP5_CTL_LAYER_REG_DMA1 (stage);case SSPP_VIG3 :return MDP5_CTL_LAYER_REG_VIG3 (stage);case SSPP_RGB3 :return MDP5_CTL_LAYER_REG_RGB3 (stage); +case SSPP_CURSOR0 : +case SSPP_CURSOR1 :default :return 0 ; } }
@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,static u32 mdp_ctl_blend_ext_mask (enum mdp5_pipe pipe,enum mdp_mixer_stage_id stage) { -if (stage <STAGE6 ) +if (stage <STAGE6 && (pipe !=SSPP_CURSOR0 && pipe !=SSPP_CURSOR1 ))return 0 ;switch (pipe) {
@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,case SSPP_DMA1 :return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3 ;case SSPP_VIG3 :return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3 ;case SSPP_RGB3 :return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3 ; +case SSPP_CURSOR0 :return MDP5_CTL_LAYER_EXT_REG_CURSOR0 (stage); +case SSPP_CURSOR1 :return MDP5_CTL_LAYER_EXT_REG_CURSOR1 (stage);default :return 0 ; } }
@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt, start_stage =STAGE_BASE ; } -for (i = start_stage; i < start_stage + stage_cnt; i++) { +for (i = start_stage; stage_cnt && i <=STAGE_MAX ; i++) { blend_cfg |=mdp_ctl_blend_mask (stage[i], i); blend_ext_cfg |=mdp_ctl_blend_ext_mask (stage[i], i); }
@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)case SSPP_DMA1 :return MDP5_CTL_FLUSH_DMA1 ;case SSPP_VIG3 :return MDP5_CTL_FLUSH_VIG3 ;case SSPP_RGB3 :return MDP5_CTL_FLUSH_RGB3 ; +case SSPP_CURSOR0 :return MDP5_CTL_FLUSH_CURSOR_0 ; +case SSPP_CURSOR1 :return MDP5_CTL_FLUSH_CURSOR_1 ;default :return 0 ; } }
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +8 -2
@@ -447,8 +447,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)bool primary = i < num_crtcs;struct drm_plane *plane;struct drm_crtc *crtc; +enum drm_plane_type type; - plane =mdp5_plane_init (dev, primary); +if (primary) + type =DRM_PLANE_TYPE_PRIMARY ; +else + type =DRM_PLANE_TYPE_OVERLAY ; + + plane =mdp5_plane_init (dev, type);if (IS_ERR (plane)) { ret =PTR_ERR (plane);dev_err (dev->dev,"failed to construct plane %d (%d)\n" , i, ret);
@@ -459,7 +465,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)if (!primary)continue ; - crtc =mdp5_crtc_init (dev, plane, i); + crtc =mdp5_crtc_init (dev, plane,NULL , i);if (IS_ERR (crtc)) { ret =PTR_ERR (crtc);dev_err (dev->dev,"failed to construct crtc %d (%d)\n" , i, ret);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +5 -2
@@ -169,6 +169,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)NAME (RGB0 ),NAME (RGB1 ),NAME (RGB2 ),NAME (DMA0 ),NAME (DMA1 ),NAME (VIG3 ),NAME (RGB3 ), +NAME (CURSOR0 ),NAME (CURSOR1 ), #undef NAME };return names[pipe];
@@ -246,7 +247,8 @@ void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,void mdp5_plane_complete_commit (struct drm_plane *plane,struct drm_plane_state *state);enum mdp5_pipe mdp5_plane_pipe (struct drm_plane *plane); -struct drm_plane *mdp5_plane_init (struct drm_device *dev,bool primary); +struct drm_plane *mdp5_plane_init (struct drm_device *dev, +enum drm_plane_type type);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc);
@@ -255,7 +257,8 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc, struct mdp5_interface *intf, struct mdp5_ctl *ctl);void mdp5_crtc_wait_for_commit_done (struct drm_crtc *crtc);struct drm_crtc *mdp5_crtc_init (struct drm_device *dev, -struct drm_plane *plane,int id); +struct drm_plane *plane, +struct drm_plane *cursor_plane,int id);struct drm_encoder *mdp5_encoder_init (struct drm_device *dev,struct mdp5_interface *intf,struct mdp5_ctl *ctl);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c +8 -0
@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,if (caps & ~cur->caps)continue ; +/* +* don't assign a cursor pipe to a plane that isn't going to +* be used as a cursor +*/ +if (cur->caps &MDP_PIPE_CAP_CURSOR && + plane->type !=DRM_PLANE_TYPE_CURSOR ) +continue ; +/* possible candidate, take the one with the * fewest unneeded caps bits set: */
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4 -3
@@ -354,6 +354,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,if (rotation &DRM_REFLECT_Y ) caps |=MDP_PIPE_CAP_VFLIP ; +if (plane->type ==DRM_PLANE_TYPE_CURSOR ) + caps |=MDP_PIPE_CAP_CURSOR ; +/* (re)allocate hw pipe if we don't have one or caps-mismatch: */ if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps)) new_hwpipe = true;
@@ -892,12 +895,11 @@ void mdp5_plane_complete_commit(struct drm_plane *plane, }/* initialize plane */ -struct drm_plane *mdp5_plane_init (struct drm_device *dev,bool primary) +struct drm_plane *mdp5_plane_init (struct drm_device *dev,enum drm_plane_type type) {struct drm_plane *plane =NULL ;struct mdp5_plane *mdp5_plane;int ret; -enum drm_plane_type type; mdp5_plane =kzalloc (sizeof (*mdp5_plane),GFP_KERNEL );if (!mdp5_plane) {
@@ -910,7 +912,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary) mdp5_plane->nformats =mdp_get_formats (mdp5_plane->formats,ARRAY_SIZE (mdp5_plane->formats), false); - type = primary ?DRM_PLANE_TYPE_PRIMARY :DRM_PLANE_TYPE_OVERLAY ; ret =drm_universal_plane_init (dev, plane,0xff , &mdp5_plane_funcs, mdp5_plane->formats, mdp5_plane->nformats, type,NULL );
drivers/gpu/drm/msm/mdp/mdp_kms.h +1 -0
@@ -112,6 +112,7 @@ struct mdp_format {#define MDP_PIPE_CAP_CSC BIT(3)#define MDP_PIPE_CAP_DECIMATION BIT(4)#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5) +#define MDP_PIPE_CAP_CURSOR BIT(6)static inline bool pipe_supports_yuv (uint32_t pipe_caps) {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH 7/9 drm/msm/mdp5: Refactor mdp5_plane_atomic_check
In reply to Archit TanejaIn mdp5_plane_atomic_check, we get crtc_state from drm_plane_state.
Later, for cursor planes, we'll populate the update_plane() func that takes a fast asynchronous path to implement cursor movements. There, we would need to call a similar atomic_check func to validate the plane state, but crtc_state would need to be derived differently.
Refactor mdp5_plane_atomic_check to mdp5_plane_atomic_check_with_state such that the latter takes crtc_state as an argument.
This is similar to what the intel driver has done for async cursor updates.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +20 -12
@@ -273,16 +273,15 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane, }#define FRAC_16_16 (mult, div) (((mult) << 16) / (div)) -static int mdp5_plane_atomic_check (struct drm_plane *plane, -struct drm_plane_state *state) +static int mdp5_plane_atomic_check_with_state (struct drm_crtc_state *crtc_state, +struct drm_plane_state *state) {struct mdp5_plane_state *mdp5_state =to_mdp5_plane_state (state); +struct drm_plane *plane = state->plane;struct drm_plane_state *old_state = plane->state;struct mdp5_cfg *config =mdp5_cfg_get_config (get_kms (plane)->cfg);bool new_hwpipe = false;uint32_t max_width, max_height; -struct drm_crtc *crtc; -struct drm_crtc_state *crtc_state;struct drm_rect clip;int min_scale, max_scale;uint32_t caps =0 ;
@@ -291,10 +290,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,DBG ("%s: check (%d -> %d)" , plane->name,plane_enabled (old_state),plane_enabled (state)); - crtc = state->crtc ? state->crtc : plane->state->crtc; -if (!crtc) -return 0 ; -/* We don't allow faster-than-vblank updates.. if we did add this * some day, we would need to disallow in cases where hwpipe * changes
@@ -313,10 +308,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return -ERANGE ; } - crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); -if (WARN_ON (!crtc_state)) -return -EINVAL ; - clip.x1 =0 ; clip.y1 =0 ; clip.x2 = crtc_state->adjusted_mode.hdisplay;
@@ -392,6 +383,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return 0 ; } +static int mdp5_plane_atomic_check (struct drm_plane *plane, +struct drm_plane_state *state) +{ +struct drm_crtc *crtc; +struct drm_crtc_state *crtc_state; + + crtc = state->crtc ? state->crtc : plane->state->crtc; +if (!crtc) +return 0 ; + + crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); +if (WARN_ON (!crtc_state)) +return -EINVAL ; + +return mdp5_plane_atomic_check_with_state (crtc_state, state); +} +static void mdp5_plane_atomic_update (struct drm_plane *plane,struct drm_plane_state *old_state) {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
RFC 8/9 HACK: drm/msm/mdp5: Add support for legacy cursor updates
In reply to Archit TanejaThis code has been more or less picked up from the vc4 and intel implementations of update_plane() funcs for cursor planes.
The update_plane() func is usually the drm_atomic_helper_update_plane func that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.
The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.
We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Cc:
---
- Don't know what to do for locking here :/
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 7 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 109 +++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +7 -0
@@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,mdp5_ctl_set_pipeline (ctl, intf, lm); } +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc) +{ +struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc); + +return mdp5_crtc->ctl; +} +int mdp5_crtc_get_lm (struct drm_crtc *crtc) {struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +1 -0
@@ -250,6 +250,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,struct drm_plane *mdp5_plane_init (struct drm_device *dev,enum drm_plane_type type); +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc);int mdp5_crtc_get_lm (struct drm_crtc *crtc);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +106 -3
133 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
Op 19-12-16 om 13:08 schreef Archit Taneja:
Quoted 20 lines
This code has been more or less picked up from the vc4 and intel implementations of
update_plane()funcs for cursor planes.The
update_plane()func is usually thedrm_atomic_helper_update_planefunc that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in
update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Quoted 4 lines
Cc:
Signed-off-by Archit Taneja <[email protected]>---
- Don't know what to do for locking here :/
Shouldn't patch 9 be done first before 8?
~Maarten
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
Quoted 21 lines · Maarten Lankhorst
Op 19-12-16 om 13:08 schreef Archit Taneja:
Quoted 20 lines
This code has been more or less picked up from the vc4 and intel implementations of
update_plane()funcs for cursor planes.The
update_plane()func is usually thedrm_atomic_helper_update_planefunc that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in
update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Quoted 5 lines
Quoted 4 lines
Cc:
Signed-off-by Archit Taneja <[email protected]>---
- Don't know what to do for locking here :/Shouldn't patch 9 be done first before 8?
Patch 9 introduces cursor drm_planes for the first time, so anything done in 8 doesn't really take effect until we add the planes in patch 9. So it's safe to have this order.
Archit
Quoted 7 lines
~Maarten
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
Op 20-12-16 om 07:23 schreef Archit Taneja:
Quoted 28 lines · Maarten Lankhorst
Quoted 25 lines
Op 19-12-16 om 13:08 schreef Archit Taneja:
Quoted 24 lines
This code has been more or less picked up from the vc4 and intel implementations of
update_plane()funcs for cursor planes.The
update_plane()func is usually thedrm_atomic_helper_update_planefunc that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in
update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Cc:
Signed-off-by Archit Taneja <[email protected]>---
- Don't know what to do for locking here :/
Quoted 5 lines
Quoted 1 line
Shouldn't patch 9 be done first before 8?
Patch 9 introduces cursor
drm_planesfor the first time, so anything done in 8 doesn't really take effect until we add the planes in patch 9. So it's safe to have this order.
The other way around will allow you to test with the normal atomic helpers first, and then if the hack breaks you're able to bisect it correctly and revert it, that's why I think it should be the other way around. :)
~Maarten
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
Quoted 29 lines · Maarten Lankhorst
Op 20-12-16 om 07:23 schreef Archit Taneja:
Quoted 28 lines · Maarten Lankhorst
Quoted 25 lines
Op 19-12-16 om 13:08 schreef Archit Taneja:
Quoted 24 lines
This code has been more or less picked up from the vc4 and intel implementations of
update_plane()funcs for cursor planes.The
update_plane()func is usually thedrm_atomic_helper_update_planefunc that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in
update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Cc:
Signed-off-by Archit Taneja <[email protected]>---
- Don't know what to do for locking here :/
Quoted 6 lines
Quoted 5 lines
Quoted 1 line
Shouldn't patch 9 be done first before 8?
Patch 9 introduces cursor
drm_planesfor the first time, so anything done in 8 doesn't really take effect until we add the planes in patch 9. So it's safe to have this order.The other way around will allow you to test with the normal atomic helpers first, and then if the hack breaks you're able to bisect it correctly and revert it, that's why I think it should be the other way around. :)
Yeah, makes sense when you put it that way :). Will make sure the hack commit comes after the cursor planes are supported the regular atomic way.
Archit
Quoted 3 lines
~Maarten
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
In reply to Archit TanejaQuoted 15 lines · Archit Taneja
This code has been more or less picked up from the vc4 and intel implementations of
update_plane()funcs for cursor planes.The
update_plane()func is usually thedrm_atomic_helper_update_planefunc that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in
update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.
Quoted 7 lines
We take the slow path even whenever the fb changes, and even when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. The slow path will ensure that the fb is prepared/pinned etc.
Cc:
Signed-off-by Archit Taneja <[email protected]>
I wonder whether it's time to extract this pattern into some helpers. I think a combo of async_check and async_flip callbacks on planes should do the trick and integrate somewhat into atomic overall. amdgpu also needs this for async flips on the primary plane.
Both async_check and async_flip would take only (struct drm_plane *plane, struct drm_plane_state *state) as arguments. Maybe we should even wrap that up into an struct drm_async_flip so that we can add more stuff in the future.
But all still a bit unclear to me.
Quoted 84 lines
---
- Don't know what to do for locking here :/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 7 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 109 +++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 3 deletions(-)drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +7
-0@@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,mdp5_ctl_set_pipeline (ctl, intf, lm); } +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc) +{ +struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc); + +return mdp5_crtc->ctl; +} +int mdp5_crtc_get_lm (struct drm_crtc *crtc) {struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc);drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +1
-0@@ -250,6 +250,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,struct drm_plane *mdp5_plane_init (struct drm_device *dev,enum drm_plane_type type); +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc);int mdp5_crtc_get_lm (struct drm_crtc *crtc);drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +24
-0@@ -31,6 +31,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_rect *src, struct drm_rect *dest); +static int mdp5_update_cursor_plane_legacy (struct drm_plane *plane, +struct drm_crtc *crtc, +struct drm_framebuffer *fb, +int crtc_x,int crtc_y, +unsigned int crtc_w,unsigned int crtc_h, +uint32_t src_x,uint32_t src_y, +uint32_t src_w,uint32_t src_h); +static void set_scanout_locked (struct drm_plane *plane,struct drm_framebuffer *fb);@@ -246,6 +254,19 @@ static void mdp5_plane_destroy_state(struct drm_plane *plane, .atomic_print_state = mdp5_plane_atomic_print_state, }; +static const struct drm_plane_funcs mdp5_cursor_plane_funcs = { + .update_plane = mdp5_update_cursor_plane_legacy, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = mdp5_plane_destroy, + .set_property = drm_atomic_helper_plane_set_property, + .atomic_set_property = mdp5_plane_atomic_set_property, + .atomic_get_property = mdp5_plane_atomic_get_property, + .reset = mdp5_plane_reset, + .atomic_duplicate_state = mdp5_plane_duplicate_state, + .atomic_destroy_state = mdp5_plane_destroy_state, + .atomic_print_state = mdp5_plane_atomic_print_state, +}; +static int mdp5_plane_prepare_fb (struct drm_plane *plane,struct drm_plane_state *new_state) {@@ -873,6 +894,81 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,return ret; } +static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane, + struct drm_crtc *crtc, struct drm_framebuffer *fb, + int crtc_x, int crtc_y,
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c static int mdp5_plane_mode_set(struct drm_plane *plane, · line 909
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +10
-0+ unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct drm_plane_state *plane_state, *new_plane_state; +struct mdp5_plane_state *mdp5_pstate; +struct drm_crtc_state *crtc_state = crtc->state; +int ret; + +if (!crtc_state->active ||drm_atomic_crtc_needs_modeset (crtc_state))
Until you do some kind of normal flip on the primary after a modeset no one will ever change the needs_modeset(crtc_state) if you only ever do async flips. Sounds like a bug, and vc4 doesn't check for it. Why do you need this?
Quoted 42 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +42
-0+ goto slow; + + plane_state = plane->state; + mdp5_pstate =to_mdp5_plane_state (plane_state); + +/* don't use fast path if we don't have a hwpipe allocated yet */ +if (!mdp5_pstate->hwpipe) + goto slow; + +/* only allow changing of position(crtc x/y or src x/y) in fast path */ +if (plane_state->crtc != crtc || + plane_state->src_w != src_w || + plane_state->src_h != src_h || + plane_state->crtc_w != crtc_w || + plane_state->crtc_h != crtc_h || + !plane_state->fb || + plane_state->fb != fb) + goto slow; + + new_plane_state =mdp5_plane_duplicate_state (plane); +if (!new_plane_state) +return -ENOMEM ; + + new_plane_state->src_x = src_x; + new_plane_state->src_y = src_y; + new_plane_state->src_w = src_w; + new_plane_state->src_h = src_h; + new_plane_state->crtc_x = crtc_x; + new_plane_state->crtc_y = crtc_y; + new_plane_state->crtc_w = crtc_w; + new_plane_state->crtc_h = crtc_h; + + ret =mdp5_plane_atomic_check_with_state (crtc_state, new_plane_state); +if (ret) + goto slow_free; + +if (new_plane_state->visible) { +struct mdp5_ctl *ctl; + + ret =mdp5_plane_mode_set (plane, crtc, fb, + &new_plane_state->src, + &new_plane_state->dst);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c static int mdp5_plane_mode_set(struct drm_plane *plane, · line 961
Quoted 10 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +10
-0+WARN_ON (ret <0 ); + + ctl =mdp5_crtc_get_ctl (crtc); + +mdp5_ctl_commit (ctl,mdp5_plane_get_flush (plane)); + } + + *to_mdp5_plane_state (plane_state) = *to_mdp5_plane_state (new_plane_state); + +mdp5_plane_destroy_state (plane, new_plane_state);
Even if the don't go the full monty, at least a drm_legacy_cursor_helper_update_plane which encodes the above would be good. I think it should be possible to code it up using the ->atomic_check and ->atomic_update callbacks ...
But just ideas really, might be better to wait for yet another driver to explore this space before we consolidate ;-)
-Daniel
Quoted 37 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +20
-3+ +return 0 ; +slow_free: +mdp5_plane_destroy_state (plane, new_plane_state); +slow: +return drm_atomic_helper_update_plane (plane, crtc, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x, src_y, src_w, src_h); +} +enum mdp5_pipe mdp5_plane_pipe (struct drm_plane *plane) {struct mdp5_plane_state *pstate =to_mdp5_plane_state (plane->state);@@ -920,9 +1016,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum drm_plane_type ty mdp5_plane->nformats =mdp_get_formats (mdp5_plane->formats,ARRAY_SIZE (mdp5_plane->formats), false); - ret =drm_universal_plane_init (dev, plane,0xff , &mdp5_plane_funcs, - mdp5_plane->formats, mdp5_plane->nformats, - type,NULL ); +if (type ==DRM_PLANE_TYPE_CURSOR ) + ret =drm_universal_plane_init (dev, plane,0xff , + &mdp5_cursor_plane_funcs, + mdp5_plane->formats, mdp5_plane->nformats, + type,NULL ); +else + ret =drm_universal_plane_init (dev, plane,0xff , + &mdp5_plane_funcs, + mdp5_plane->formats, mdp5_plane->nformats, + type,NULL );if (ret) goto fail;Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
Quoted 15 lines · Daniel Vetter
Quoted 14 lines · Archit Taneja
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +10
-0@@ -873,6 +894,81 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,return ret; } +static int mdp5_update_cursor_plane_legacy (struct drm_plane *plane, +struct drm_crtc *crtc,struct drm_framebuffer *fb, +int crtc_x,int crtc_y, +unsigned int crtc_w,unsigned int crtc_h, +uint32_t src_x,uint32_t src_y, +uint32_t src_w,uint32_t src_h) +{ +struct drm_plane_state *plane_state, *new_plane_state; +struct mdp5_plane_state *mdp5_pstate; +struct drm_crtc_state *crtc_state = crtc->state;
Quoted 8 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c static int mdp5_plane_mode_set(struct drm_plane *plane, · line 909
Quoted 3 lines
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +3
-0+int ret; + +if (!crtc_state->active ||drm_atomic_crtc_needs_modeset (crtc_state))Until you do some kind of normal flip on the primary after a modeset no one will ever change the
needs_modeset(crtc_state)if you only ever do async flips. Sounds like a bug, and vc4 doesn't check for it. Why do you need this?
Self-correct: The slow-path will duplicate the crtc state also and clear needs_modeset, which means only the very first cursor move after a modeset will be slow. I think that's ok.
But this kind of trickery is a good reason to try to extract this logic a bit better I think.
-Daniel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/9 drm/msm/mdp5: Add cursor planes
In reply to Archit TanejaRegister cursor drm_planes. The loop in modeset_init that inits the planes and crtcs has to be refactored a bit. We first iterate all the hwpipes to find the cursor planes. Then, we loop again to create crtcs.
In msm_atomic_wait_for_commit_done, remove the check which bypasses waiting for vsyncs if state->legacy_cursor_updates is true. We've created a fast path for cursor position changes in the cursor plane's update_plane func that doesn't go via the regular atomic commit path. For rest of cursor related updates, we have to wait for the vsyncs, so ignore the legacy_cursor_updates flag.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 32 +++++++++++++++++++++++++------- drivers/gpu/drm/msm/msm_atomic.c | 5 ----- 2 files changed, 25 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +25 -7
@@ -417,7 +417,9 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)struct msm_drm_private *priv = dev->dev_private;const struct mdp5_cfg_hw *hw_cfg;unsigned int num_crtcs; -int i, ret; +int i, ret, pi =0 , ci =0 ; +struct drm_plane *primary[6 ] = {NULL }; +struct drm_plane *cursor[6 ] = {NULL }; hw_cfg =mdp5_cfg_get_hw_config (mdp5_kms->cfg);
@@ -444,13 +446,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)* planes for the CRTCs, with the remainder as overlay planes: */ for (i =0 ; i < mdp5_kms->num_hwpipes; i++) { -bool primary = i < num_crtcs; +struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];struct drm_plane *plane; -struct drm_crtc *crtc;enum drm_plane_type type; -if (primary) +if (i < num_crtcs) type =DRM_PLANE_TYPE_PRIMARY ; +else if (hwpipe->caps &MDP_PIPE_CAP_CURSOR ) + type =DRM_PLANE_TYPE_CURSOR ;else type =DRM_PLANE_TYPE_OVERLAY ;
@@ -462,10 +465,16 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) } priv->planes[priv->num_planes++] = plane; -if (!primary) -continue ; +if (type ==DRM_PLANE_TYPE_PRIMARY ) + primary[pi++] = plane; +if (type ==DRM_PLANE_TYPE_CURSOR ) + cursor[ci++] = plane; + } + +for (i =0 ; i < num_crtcs; i++) { +struct drm_crtc *crtc; - crtc =mdp5_crtc_init (dev, plane,NULL , i); + crtc =mdp5_crtc_init (dev, primary[i], cursor[i], i);if (IS_ERR (crtc)) { ret =PTR_ERR (crtc);dev_err (dev->dev,"failed to construct crtc %d (%d)\n" , i, ret);
@@ -797,6 +806,9 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)static const enum mdp5_pipe dma_planes[] = {SSPP_DMA0 ,SSPP_DMA1 , }; +static const enum mdp5_pipe cursor_planes[] = { +SSPP_CURSOR0 ,SSPP_CURSOR1 , + };const struct mdp5_cfg_hw *hw_cfg;int ret;
@@ -820,6 +832,12 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)if (ret)return ret; +/* Construct cursor pipes: */ + ret =construct_pipes (mdp5_kms, hw_cfg->pipe_cursor.count, cursor_planes, + hw_cfg->pipe_cursor.base, hw_cfg->pipe_cursor.caps); +if (ret) +return ret; +return 0 ; }
drivers/gpu/drm/msm/msm_atomic.c +0 -5
@@ -93,11 +93,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,if (!crtc->state->enable)continue ; -/* Legacy cursor ioctls are completely unsynced, and userspace -* relies on that (by doing tons of cursor updates). */ -if (old_state->legacy_cursor_update) -continue ; - kms->funcs->wait_for_crtc_commit_done (kms, crtc); } }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Quoted 8 lines · Archit Taneja
This series does some
mdp5_planerelated clean ups (use plane helpers for clipping etc), adds MDP5 bits needed for cursor plane blocks, and then add cursor planes.On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and that's implemented in
mdp5_crtc.c. With newer hardware, the cursor blocks look exactly like MDP5 pipes (SSPPs).
Quoted 8 lines
The "faster than vblank cursor position update stuff" has been copied from vc4 and the patches posted recently by Maarten for Intel:
https://patchwork.kernel.org/patch/9466417/
I've tried this with some X11 UI and modetest -C, and it seems to work okay. Are there any tests that mix up atomic commits and legacy cursor updates a lot to identify issues?
kms_legacy_cursor mixes cursor updates with page_flips (and if you use atomic for those, atomic flips ofcourse). But the test is a bit too oveager and even expects cursor updates vs. modesets to not block. Not sure Maarten fixed that already.
-Daniel
Quoted 30 lines
Archit Taneja (9):
drm/msm/mdp5: cfg: Addpipe_cursorblock drm/msm/mdp5: Update generated headers
drm/msm/mdp5: Prepare CRTC/LM for empty stages drm/msm/mdp5: Use plane helpers to configure src/dst rectangles drm/msm/mdp5: ConfigureCOLOR3_OUTpropagation drm/msm/mdp5: Misc cursor plane bits
drm/msm/mdp5: Refactormdp5_plane_atomic_check
HACK: drm/msm/mdp5: Add support for legacy cursor updates drm/msm/mdp5: Add cursor planesdrivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 30 +++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 73 +++++++++++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 14 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 38 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 8 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 ++++++++++++++++++++++++++---- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + drivers/gpu/drm/msm/msm_atomic.c | 26 +++-- 12 files changed, 334 insertions(+), 60 deletions(-)Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
v2 cover drm/msm/mdp5: Cursor plane stuff
In reply to Archit TanejaThis series does some mdp5_plane related clean ups (use plane helpers for clipping etc), adds MDP5 bits needed for cursor plane blocks, and then add cursor planes.
On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and that's implemented in mdp5_crtc.c. With newer hardware, the cursor blocks look exactly like MDP5 pipes (SSPPs).
The "faster than vblank cursor position update stuff" has been copied from vc4 and the patches posted recently by Maarten for Intel:
https://patchwork.kernel.org/patch/9466417/
Changes in v2:
- Dropped generated headers patch.
- Add the fast path patch in the end as suggested by Maarten.
- Minor cleanups.
Archit Taneja (8):
drm/msm/mdp5: cfg: Add pipe_cursor block drm/msm/mdp5: Prepare CRTC/LM for empty stages drm/msm/mdp5: Use plane helpers to configure src/dst rectangles drm/msm/mdp5: Configure COLOR3_OUT propagation drm/msm/mdp5: Misc cursor plane bits
drm/msm/mdp5: Add cursor planes
drm/msm/mdp5: Refactor mdp5_plane_atomic_check
HACK: drm/msm/mdp5: Add support for legacy cursor updates
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 73 +++++++++++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 14 ++- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 39 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 8 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 +++++++++++++++++++++++++++--- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + drivers/gpu/drm/msm/msm_atomic.c | 26 +++-- 11 files changed, 316 insertions(+), 49 deletions(-)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 1/8 drm/msm/mdp5: cfg: Add pipe_cursor block
Define the block in advance so that the generated mdp5.xml.h doesn't break build.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +1 -0
@@ -85,6 +85,7 @@ struct mdp5_cfg_hw {struct mdp5_pipe_block pipe_vig;struct mdp5_pipe_block pipe_rgb;struct mdp5_pipe_block pipe_dma; +struct mdp5_pipe_block pipe_cursor;struct mdp5_lm_block lm;struct mdp5_sub_block dspp;struct mdp5_sub_block ad;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 2/8 drm/msm/mdp5: Prepare CRTC/LM for empty stages
In reply to Archit TanejaUse SSPP_NONE in mdp5_plane_pipe() if there is now hwpipe allocated for the drm_plane. Returning '0' means we are returning VIG0 pipe.
Also, use the mdp5_pipe enum to pass around the stage array. Initialize the stage to SSPP_NONE by default.
We do the above because 1) Cursor plane has to be staged at the topmost blender of the LM, which can result in empty stages in between 2) In the future, when we support multiple LMs per CRTC. We could have stages which don't have any pipe assigned to them.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 4 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h | 4 ++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +1 -1
@@ -195,7 +195,7 @@ static void blend_setup(struct drm_crtc *crtc)uint32_t lm = mdp5_crtc->lm;uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags =0 ;unsigned long flags; -uint8_t stage[STAGE_MAX +1 ]; +enum mdp5_pipe stage[STAGE_MAX +1 ] = {SSPP_NONE };int i, plane_cnt =0 ;#define blender (stage) ((stage) - STAGE0)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +2 -2
@@ -351,8 +351,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe, } } -int mdp5_ctl_blend (struct mdp5_ctl *ctl,u8 *stage,u32 stage_cnt, -u32 ctl_blend_op_flags) +int mdp5_ctl_blend (struct mdp5_ctl *ctl,enum mdp5_pipe *stage,u32 stage_cnt, +u32 ctl_blend_op_flags) {unsigned long flags;u32 blend_cfg =0 , blend_ext_cfg =0 ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h +2 -2
@@ -56,8 +56,8 @@ int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable);* (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask) */ #define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT BIT(0) -int mdp5_ctl_blend (struct mdp5_ctl *ctl,u8 *stage,u32 stage_cnt, -u32 ctl_blend_op_flags); +int mdp5_ctl_blend (struct mdp5_ctl *ctl,enum mdp5_pipe *stage,u32 stage_cnt, +u32 ctl_blend_op_flags);/** * mdp_ctl_flush_mask...() - Register FLUSH masks
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +1 -1
@@ -823,7 +823,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)struct mdp5_plane_state *pstate =to_mdp5_plane_state (plane->state);if (WARN_ON (!pstate->hwpipe)) -return 0 ; +return SSPP_NONE ;return pstate->hwpipe->pipe; }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 3/8 drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
In reply to Archit TanejaThe MDP5 plane's atomic_check ops doesn't perform clipping tests. This didn't hurt us much in the past, but clipping becomes important with cursor planes.
Use drm_plane_helper_check_state, the way rockchip/intel/mtk drivers already do. Use these drivers as reference.
Clipping requires knowledge of the crtc width and height. This requires us to call drm_atomic_helper_check_modeset before drm_atomic_helper_check_planes in the driver's atomic_check op, because check_modetest will populate the mode for the crtc, needed to populate the clip rectangle.
We update the plane_enabled(state) local helper to use state->visible, since state->visible and 'state->fb && state->crtc' represent the same thing.
One issue with the existing code is that we don't have a way to disable the plane when it's completely clipped out. Until there isn't an update on the crtc (which would de-stage the plane), we would still see the plane in its last 'visible' configuration.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 57 ++++++++++++++++++++++++------- drivers/gpu/drm/msm/msm_atomic.c | 21 ++++++++---- 2 files changed, 59 insertions(+), 19 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +44 -13
@@ -29,10 +29,7 @@ struct mdp5_plane {static int mdp5_plane_mode_set (struct drm_plane *plane,struct drm_crtc *crtc,struct drm_framebuffer *fb, -int crtc_x,int crtc_y, -unsigned int crtc_w,unsigned int crtc_h, -uint32_t src_x,uint32_t src_y, -uint32_t src_w,uint32_t src_h); +struct drm_rect *src,struct drm_rect *dest);static void set_scanout_locked (struct drm_plane *plane,struct drm_framebuffer *fb);
@@ -45,7 +42,7 @@ static struct mdp5_kms *get_kms(struct drm_plane *plane)static bool plane_enabled (struct drm_plane_state *state) { -return state->fb && state->crtc; +return state->visible; }static void mdp5_plane_destroy (struct drm_plane *plane)
@@ -272,6 +269,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,msm_framebuffer_cleanup (fb, mdp5_kms->id); } +#define FRAC_16_16 (mult, div) (((mult) << 16) / (div))static int mdp5_plane_atomic_check (struct drm_plane *plane,struct drm_plane_state *state) {
@@ -281,10 +279,19 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,bool new_hwpipe = false;uint32_t max_width, max_height;uint32_t caps =0 ; +struct drm_crtc *crtc; +struct drm_crtc_state *crtc_state; +struct drm_rect clip; +int min_scale, max_scale; +int ret;DBG ("%s: check (%d -> %d)" , plane->name,plane_enabled (old_state),plane_enabled (state)); + crtc = state->crtc ? state->crtc : plane->state->crtc; +if (!crtc) +return 0 ; + max_width = config->hw->lm.max_width <<16 ; max_height = config->hw->lm.max_height <<16 ;
@@ -296,6 +303,22 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return -ERANGE ; } + crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); +if (WARN_ON (!crtc_state)) +return -EINVAL ; + + clip.x1 =0 ; + clip.y1 =0 ; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + min_scale =FRAC_16_16 (1 ,8 ); + max_scale =FRAC_16_16 (8 ,1 ); + + ret =drm_plane_helper_check_state (state, &clip, min_scale, + max_scale, true, true); +if (ret) +return ret; +if (plane_enabled (state)) {unsigned int rotation;const struct mdp_format *format;
@@ -368,10 +391,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, ret =mdp5_plane_mode_set (plane, state->crtc, state->fb, - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - state->src_x, state->src_y, - state->src_w, state->src_h); + &state->src, &state->dst);/* atomic_check should have ensured that this doesn't fail */ WARN_ON (ret <0 ); }
@@ -664,10 +684,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,static int mdp5_plane_mode_set (struct drm_plane *plane,struct drm_crtc *crtc,struct drm_framebuffer *fb, -int crtc_x,int crtc_y, -unsigned int crtc_w,unsigned int crtc_h, -uint32_t src_x,uint32_t src_y, -uint32_t src_w,uint32_t src_h) +struct drm_rect *src,struct drm_rect *dest) {struct drm_plane_state *pstate = plane->state;struct mdp5_hw_pipe *hwpipe =to_mdp5_plane_state (pstate)->hwpipe;
@@ -683,6 +700,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,uint32_t pix_format;unsigned int rotation;bool vflip, hflip; +int crtc_x, crtc_y; +unsigned int crtc_w, crtc_h; +uint32_t src_x, src_y; +uint32_t src_w, src_h;unsigned long flags;int ret;
@@ -695,6 +716,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, format =to_mdp_format (msm_framebuffer_format (fb)); pix_format = format->base.pixel_format; + src_x = src->x1; + src_y = src->y1; + src_w =drm_rect_width (src); + src_h =drm_rect_height (src); + + crtc_x = dest->x1; + crtc_y = dest->y1; + crtc_w =drm_rect_width (dest); + crtc_h =drm_rect_height (dest); +/* src values are in Q16 fixed point, convert to integer: */ src_x = src_x >>16 ; src_y = src_y >>16 ;
drivers/gpu/drm/msm/msm_atomic.c +15 -6
@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work) complete_commit(container_of(work, struct msm_commit, work), true); } +/* +* this func is identical to the drm_atomic_helper_check, but we keep this +* because we might eventually need to have a more finegrained check +* sequence without using the atomic helpers. +* +* In the past, we first called drm_atomic_helper_check_planes, and then +* drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's +* ->atomic_check could update ->mode_changed for pixel format changes. +* This, however isn't needed now because if there is a pixel format change, +* we just assign a new hwpipe for it with a new SMP allocation. We might +* eventually hit a condition where we would need to do a full modeset if +* we run out of planes. There, we'd probably need to set mode_changed. +*/ int msm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state) {int ret; -/* -* msm ->atomic_check can update ->mode_changed for pixel format -* changes, hence must be run before we check the modeset changes. -*/ - ret =drm_atomic_helper_check_planes (dev, state); + ret =drm_atomic_helper_check_modeset (dev, state);if (ret)return ret; - ret =drm_atomic_helper_check_modeset (dev, state); + ret =drm_atomic_helper_check_planes (dev, state);if (ret)return ret;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 4/8 drm/msm/mdp5: Configure COLOR3_OUT propagation
In reply to Archit TanejaIn MDP5 Layer Mixer HW, the blender output is only the blended color components (i.e R, G and B, or COLOR0/1/2 in MDP5 HW terminology). This is fed to the BG input of the next blender. We also need to provide an alpha (COLOR3) value for the BG input at the next stage.
This is configured via using the REG_MDP5_LM_BLEND_COLOR_OUT register. For each stage, we can propagate either the BG or FG alpha to the next stage.
The approach taken by the driver is to propagate FG alpha, if the plane staged on that blender has an alpha. If it doesn't, we try to propagate the base layer's alpha.
This is borrowed from downstream MDP5 kernel driver. Without this, we don't see any cursor plane content.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +30 -0
@@ -177,6 +177,21 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc)kfree (mdp5_crtc); } +static inline u32 mdp5_lm_use_fg_alpha_mask (enum mdp_mixer_stage_id stage) +{ +switch (stage) { +case STAGE0 :return MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA ; +case STAGE1 :return MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA ; +case STAGE2 :return MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA ; +case STAGE3 :return MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA ; +case STAGE4 :return MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA ; +case STAGE5 :return MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA ; +case STAGE6 :return MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA ; +default : +return 0 ; + } +} +/* * blend_setup() - blend all the planes of a CRTC *
@@ -197,6 +212,8 @@ static void blend_setup(struct drm_crtc *crtc)unsigned long flags;enum mdp5_pipe stage[STAGE_MAX +1 ] = {SSPP_NONE };int i, plane_cnt =0 ; +bool bg_alpha_enabled = false; +u32 mixer_op_mode =0 ;#define blender (stage) ((stage) - STAGE0) hw_cfg =mdp5_cfg_get_hw_config (mdp5_kms->cfg);
@@ -218,6 +235,11 @@ static void blend_setup(struct drm_crtc *crtc)if (!pstates[STAGE_BASE ]) { ctl_blend_flags |=MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT ;DBG ("Border Color is enabled" ); + }else if (plane_cnt) { + format =to_mdp_format (msm_framebuffer_format (pstates[STAGE_BASE ]->base.fb)); + +if (format->alpha_enable) + bg_alpha_enabled = true; }/* The reset for blending */
@@ -232,6 +254,12 @@ static void blend_setup(struct drm_crtc *crtc)MDP5_LM_BLEND_OP_MODE_BG_ALPHA (BG_CONST ); fg_alpha = pstates[i]->alpha; bg_alpha =0xFF - pstates[i]->alpha; + +if (!format->alpha_enable && bg_alpha_enabled) + mixer_op_mode =0 ; +else + mixer_op_mode |=mdp5_lm_use_fg_alpha_mask (i); +DBG ("Stage %d fg_alpha %x bg_alpha %x" , i, fg_alpha, bg_alpha);if (format->alpha_enable && pstates[i]->premultiplied) {
@@ -268,6 +296,8 @@ static void blend_setup(struct drm_crtc *crtc) blender(i)), bg_alpha); } +mdp5_write (mdp5_kms,REG_MDP5_LM_BLEND_COLOR_OUT (lm), mixer_op_mode); +mdp5_ctl_blend (mdp5_crtc->ctl, stage, plane_cnt, ctl_blend_flags); out:
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 5/8 drm/msm/mdp5: Misc cursor plane bits
In reply to Archit TanejaThese are various changes added in preparation for cursor planes:
- Add a pipe_cursor block for 8x96 in mdp5_cfg.
- Add a new pipe CAP called MDP_PIPE_CAP_CURSOR. Use this to ensure we assign a cursor SSPP for a drm_plane with type DRM_PLANE_TYPE_CURSOR.
- Update mdp5_ctl_blend_mask/ext_blend_mask funcs to incorporate cursor SSPPs.
- In mdp5_ctl_blend, iterate through MAX_STAGES instead of stage_cnt, we need to do this because we can now have empty stages in between.
- In mdp5_crtc_atomic_check, make sure that the cursor plane has the highest zorder, and stage the cursor plane to the maximum stage # present on the HW.
- Create drm_crtc_funcs that doesn't try to implement cursors using the older LM cursor HW.
- Pass drm_plane_type in mdp5_plane_init instead of a bool telling whether plane is primary or not.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 +++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 34 +++++++++++++++++++++++++++---- drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c | 10 +++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 10 +++++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 7 +++++-- drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c | 8 ++++++++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 8 +++++--- drivers/gpu/drm/msm/mdp/mdp_kms.h | 1 + 8 files changed, 75 insertions(+), 13 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +10 -0
@@ -421,6 +421,16 @@ const struct mdp5_cfg_hw msm8x96_config = {MDP_PIPE_CAP_SW_PIX_EXT | 0, }, + .pipe_cursor = { + .count = 2, + .base = { 0x34000, 0x36000 }, + .caps = MDP_PIPE_CAP_HFLIP | +MDP_PIPE_CAP_VFLIP | +MDP_PIPE_CAP_SW_PIX_EXT | +MDP_PIPE_CAP_CURSOR | + 0, + }, + .lm = { .count =6 , .base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +30 -4
@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,struct plane_state pstates[STAGE_MAX +1 ];const struct mdp5_cfg_hw *hw_cfg;const struct drm_plane_state *pstate; +bool cursor_plane = false;int cnt =0 , base =0 , i;DBG ("%s: check" , crtc->name);
@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, pstates[cnt].state =to_mdp5_plane_state (pstate); cnt++; + +if (plane->type ==DRM_PLANE_TYPE_CURSOR ) + cursor_plane = true; }/* assign a stage based on sorted zpos property */
@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,if ((cnt >0 ) && !is_fullscreen (state, &pstates[0 ].state->base)) base++; +/* trigger a warning if cursor isn't the highest zorder */ +WARN_ON (cursor_plane && + (pstates[cnt -1 ].plane->type !=DRM_PLANE_TYPE_CURSOR )); +/* verify that there are not too many planes attached to crtc * and that we don't have conflicting mixer stages: */
@@ -431,7 +439,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, }for (i =0 ; i < cnt; i++) { - pstates[i].state->stage =STAGE_BASE + i + base; +if (cursor_plane && (i == (cnt -1 ))) + pstates[i].state->stage = hw_cfg->lm.nb_stages; +else + pstates[i].state->stage =STAGE_BASE + i + base;DBG ("%s: assign pipe %s on stage=%d" , crtc->name, pstates[i].plane->name, pstates[i].state->stage);
@@ -642,6 +653,16 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { .cursor_move = mdp5_crtc_cursor_move, }; +static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { + .set_config = drm_atomic_helper_set_config, + .destroy = mdp5_crtc_destroy, + .page_flip = drm_atomic_helper_page_flip, + .set_property = drm_atomic_helper_crtc_set_property, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, +}; +static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_nofb = mdp5_crtc_mode_set_nofb, .disable = mdp5_crtc_disable,
@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)/* initialize crtc */ struct drm_crtc *mdp5_crtc_init (struct drm_device *dev, -struct drm_plane *plane,int id) +struct drm_plane *plane, +struct drm_plane *cursor_plane,int id) {struct drm_crtc *crtc =NULL ;struct mdp5_crtc *mdp5_crtc;
@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq; mdp5_crtc->err.irq = mdp5_crtc_err_irq; -drm_crtc_init_with_planes (dev, crtc, plane,NULL , &mdp5_crtc_funcs, -NULL ); +if (cursor_plane) +drm_crtc_init_with_planes (dev, crtc, plane, cursor_plane, + &mdp5_crtc_no_lm_cursor_funcs,NULL ); +else +drm_crtc_init_with_planes (dev, crtc, plane,NULL , + &mdp5_crtc_funcs,NULL );drm_flip_work_init (&mdp5_crtc->unref_cursor_work,"unref cursor" , unref_cursor_worker);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c +8 -2
@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,case SSPP_DMA1 :return MDP5_CTL_LAYER_REG_DMA1 (stage);case SSPP_VIG3 :return MDP5_CTL_LAYER_REG_VIG3 (stage);case SSPP_RGB3 :return MDP5_CTL_LAYER_REG_RGB3 (stage); +case SSPP_CURSOR0 : +case SSPP_CURSOR1 :default :return 0 ; } }
@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,static u32 mdp_ctl_blend_ext_mask (enum mdp5_pipe pipe,enum mdp_mixer_stage_id stage) { -if (stage <STAGE6 ) +if (stage <STAGE6 && (pipe !=SSPP_CURSOR0 && pipe !=SSPP_CURSOR1 ))return 0 ;switch (pipe) {
@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,case SSPP_DMA1 :return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3 ;case SSPP_VIG3 :return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3 ;case SSPP_RGB3 :return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3 ; +case SSPP_CURSOR0 :return MDP5_CTL_LAYER_EXT_REG_CURSOR0 (stage); +case SSPP_CURSOR1 :return MDP5_CTL_LAYER_EXT_REG_CURSOR1 (stage);default :return 0 ; } }
@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt, start_stage =STAGE_BASE ; } -for (i = start_stage; i < start_stage + stage_cnt; i++) { +for (i = start_stage; stage_cnt && i <=STAGE_MAX ; i++) { blend_cfg |=mdp_ctl_blend_mask (stage[i], i); blend_ext_cfg |=mdp_ctl_blend_ext_mask (stage[i], i); }
@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)case SSPP_DMA1 :return MDP5_CTL_FLUSH_DMA1 ;case SSPP_VIG3 :return MDP5_CTL_FLUSH_VIG3 ;case SSPP_RGB3 :return MDP5_CTL_FLUSH_RGB3 ; +case SSPP_CURSOR0 :return MDP5_CTL_FLUSH_CURSOR_0 ; +case SSPP_CURSOR1 :return MDP5_CTL_FLUSH_CURSOR_1 ;default :return 0 ; } }
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +8 -2
@@ -441,8 +441,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)bool primary = i < num_crtcs;struct drm_plane *plane;struct drm_crtc *crtc; +enum drm_plane_type type; - plane =mdp5_plane_init (dev, primary); +if (primary) + type =DRM_PLANE_TYPE_PRIMARY ; +else + type =DRM_PLANE_TYPE_OVERLAY ; + + plane =mdp5_plane_init (dev, type);if (IS_ERR (plane)) { ret =PTR_ERR (plane);dev_err (dev->dev,"failed to construct plane %d (%d)\n" , i, ret);
@@ -453,7 +459,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)if (!primary)continue ; - crtc =mdp5_crtc_init (dev, plane, i); + crtc =mdp5_crtc_init (dev, plane,NULL , i);if (IS_ERR (crtc)) { ret =PTR_ERR (crtc);dev_err (dev->dev,"failed to construct crtc %d (%d)\n" , i, ret);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +5 -2
@@ -167,6 +167,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)NAME (RGB0 ),NAME (RGB1 ),NAME (RGB2 ),NAME (DMA0 ),NAME (DMA1 ),NAME (VIG3 ),NAME (RGB3 ), +NAME (CURSOR0 ),NAME (CURSOR1 ), #undef NAME };return names[pipe];
@@ -242,7 +243,8 @@ void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);uint32_t mdp5_plane_get_flush (struct drm_plane *plane);enum mdp5_pipe mdp5_plane_pipe (struct drm_plane *plane); -struct drm_plane *mdp5_plane_init (struct drm_device *dev,bool primary); +struct drm_plane *mdp5_plane_init (struct drm_device *dev, +enum drm_plane_type type);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc);
@@ -251,7 +253,8 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc, struct mdp5_interface *intf, struct mdp5_ctl *ctl);void mdp5_crtc_wait_for_commit_done (struct drm_crtc *crtc);struct drm_crtc *mdp5_crtc_init (struct drm_device *dev, -struct drm_plane *plane,int id); +struct drm_plane *plane, +struct drm_plane *cursor_plane,int id);struct drm_encoder *mdp5_encoder_init (struct drm_device *dev,struct mdp5_interface *intf,struct mdp5_ctl *ctl);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c +8 -0
@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,if (caps & ~cur->caps)continue ; +/* +* don't assign a cursor pipe to a plane that isn't going to +* be used as a cursor +*/ +if (cur->caps &MDP_PIPE_CAP_CURSOR && + plane->type !=DRM_PLANE_TYPE_CURSOR ) +continue ; +/* possible candidate, take the one with the * fewest unneeded caps bits set: */
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +5 -3
@@ -344,6 +344,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,if (rotation &DRM_REFLECT_Y ) caps |=MDP_PIPE_CAP_VFLIP ; +if (plane->type ==DRM_PLANE_TYPE_CURSOR ) + caps |=MDP_PIPE_CAP_CURSOR ; +/* (re)allocate hw pipe if we don't have one or caps-mismatch: */ if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps)) new_hwpipe = true;
@@ -870,12 +873,12 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane) }/* initialize plane */ -struct drm_plane *mdp5_plane_init (struct drm_device *dev,bool primary) +struct drm_plane *mdp5_plane_init (struct drm_device *dev, +enum drm_plane_type type) {struct drm_plane *plane =NULL ;struct mdp5_plane *mdp5_plane;int ret; -enum drm_plane_type type; mdp5_plane =kzalloc (sizeof (*mdp5_plane),GFP_KERNEL );if (!mdp5_plane) {
@@ -888,7 +891,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary) mdp5_plane->nformats =mdp_get_formats (mdp5_plane->formats,ARRAY_SIZE (mdp5_plane->formats), false); - type = primary ?DRM_PLANE_TYPE_PRIMARY :DRM_PLANE_TYPE_OVERLAY ; ret =drm_universal_plane_init (dev, plane,0xff , &mdp5_plane_funcs, mdp5_plane->formats, mdp5_plane->nformats, type,NULL );
drivers/gpu/drm/msm/mdp/mdp_kms.h +1 -0
@@ -112,6 +112,7 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);#define MDP_PIPE_CAP_CSC BIT(3)#define MDP_PIPE_CAP_DECIMATION BIT(4)#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5) +#define MDP_PIPE_CAP_CURSOR BIT(6)static inline bool pipe_supports_yuv (uint32_t pipe_caps) {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 6/8 drm/msm/mdp5: Add cursor planes
In reply to Archit TanejaRegister cursor drm_planes. The loop in modeset_init that inits the planes and crtcs has to be refactored a bit. We first iterate all the hwpipes to find the cursor planes. Then, we loop again to create crtcs.
In msm_atomic_wait_for_commit_done, remove the check which bypasses waiting for vsyncs if state->legacy_cursor_updates is true.
We will later create a fast path for cursor position changes in the cursor plane's update_plane func that doesn't go via the regular atomic commit path. For rest of cursor related updates, we will have to wait for vsyncs, so ignore the legacy_cursor_updates flag.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 33 ++++++++++++++++++++++++++------- drivers/gpu/drm/msm/msm_atomic.c | 5 ----- 2 files changed, 26 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +26 -7
@@ -411,7 +411,9 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)struct msm_drm_private *priv = dev->dev_private;const struct mdp5_cfg_hw *hw_cfg;unsigned int num_crtcs; -int i, ret; +int i, ret, pi =0 , ci =0 ; +struct drm_plane *primary[MAX_BASES ] = {NULL }; +struct drm_plane *cursor[MAX_BASES ] = {NULL }; hw_cfg =mdp5_cfg_get_hw_config (mdp5_kms->cfg);
@@ -438,13 +440,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)* planes for the CRTCs, with the remainder as overlay planes: */ for (i =0 ; i < mdp5_kms->num_hwpipes; i++) { -bool primary = i < num_crtcs; +struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];struct drm_plane *plane; -struct drm_crtc *crtc;enum drm_plane_type type; -if (primary) +if (i < num_crtcs) type =DRM_PLANE_TYPE_PRIMARY ; +else if (hwpipe->caps &MDP_PIPE_CAP_CURSOR ) + type =DRM_PLANE_TYPE_CURSOR ;else type =DRM_PLANE_TYPE_OVERLAY ;
@@ -456,10 +459,16 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) } priv->planes[priv->num_planes++] = plane; -if (!primary) -continue ; +if (type ==DRM_PLANE_TYPE_PRIMARY ) + primary[pi++] = plane; +if (type ==DRM_PLANE_TYPE_CURSOR ) + cursor[ci++] = plane; + } + +for (i =0 ; i < num_crtcs; i++) { +struct drm_crtc *crtc; - crtc =mdp5_crtc_init (dev, plane,NULL , i); + crtc =mdp5_crtc_init (dev, primary[i], cursor[i], i);if (IS_ERR (crtc)) { ret =PTR_ERR (crtc);dev_err (dev->dev,"failed to construct crtc %d (%d)\n" , i, ret);
@@ -791,6 +800,9 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)static const enum mdp5_pipe dma_planes[] = {SSPP_DMA0 ,SSPP_DMA1 , }; +static const enum mdp5_pipe cursor_planes[] = { +SSPP_CURSOR0 ,SSPP_CURSOR1 , + };const struct mdp5_cfg_hw *hw_cfg;int ret;
@@ -814,6 +826,13 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)if (ret)return ret; +/* Construct cursor pipes: */ + ret =construct_pipes (mdp5_kms, hw_cfg->pipe_cursor.count, + cursor_planes, hw_cfg->pipe_cursor.base, + hw_cfg->pipe_cursor.caps); +if (ret) +return ret; +return 0 ; }
drivers/gpu/drm/msm/msm_atomic.c +0 -5
@@ -93,11 +93,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,if (!crtc->state->enable)continue ; -/* Legacy cursor ioctls are completely unsynced, and userspace -* relies on that (by doing tons of cursor updates). */ -if (old_state->legacy_cursor_update) -continue ; - kms->funcs->wait_for_crtc_commit_done (kms, crtc); } }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 7/8 drm/msm/mdp5: Refactor mdp5_plane_atomic_check
In reply to Archit TanejaIn mdp5_plane_atomic_check, we get crtc_state from drm_plane_state.
Later, for cursor planes, we'll populate the update_plane() func that takes a fast asynchronous path to implement cursor movements. There, we would need to call a similar atomic_check func to validate the plane state, but crtc_state would need to be derived differently.
Refactor mdp5_plane_atomic_check to mdp5_plane_atomic_check_with_state such that the latter takes crtc_state as an argument.
This is similar to what the intel driver has done for async cursor updates.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +20 -12
@@ -270,17 +270,16 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane, }#define FRAC_16_16 (mult, div) (((mult) << 16) / (div)) -static int mdp5_plane_atomic_check (struct drm_plane *plane, -struct drm_plane_state *state) +static int mdp5_plane_atomic_check_with_state (struct drm_crtc_state *crtc_state, +struct drm_plane_state *state) {struct mdp5_plane_state *mdp5_state =to_mdp5_plane_state (state); +struct drm_plane *plane = state->plane;struct drm_plane_state *old_state = plane->state;struct mdp5_cfg *config =mdp5_cfg_get_config (get_kms (plane)->cfg);bool new_hwpipe = false;uint32_t max_width, max_height;uint32_t caps =0 ; -struct drm_crtc *crtc; -struct drm_crtc_state *crtc_state;struct drm_rect clip;int min_scale, max_scale;int ret;
@@ -288,10 +287,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,DBG ("%s: check (%d -> %d)" , plane->name,plane_enabled (old_state),plane_enabled (state)); - crtc = state->crtc ? state->crtc : plane->state->crtc; -if (!crtc) -return 0 ; - max_width = config->hw->lm.max_width <<16 ; max_height = config->hw->lm.max_height <<16 ;
@@ -303,10 +298,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return -ERANGE ; } - crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); -if (WARN_ON (!crtc_state)) -return -EINVAL ; - clip.x1 =0 ; clip.y1 =0 ; clip.x2 = crtc_state->adjusted_mode.hdisplay;
@@ -382,6 +373,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,return 0 ; } +static int mdp5_plane_atomic_check (struct drm_plane *plane, +struct drm_plane_state *state) +{ +struct drm_crtc *crtc; +struct drm_crtc_state *crtc_state; + + crtc = state->crtc ? state->crtc : plane->state->crtc; +if (!crtc) +return 0 ; + + crtc_state =drm_atomic_get_existing_crtc_state (state->state, crtc); +if (WARN_ON (!crtc_state)) +return -EINVAL ; + +return mdp5_plane_atomic_check_with_state (crtc_state, state); +} +static void mdp5_plane_atomic_update (struct drm_plane *plane,struct drm_plane_state *old_state) {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH v2 8/8 HACK: drm/msm/mdp5: Add support for legacy cursor updates
In reply to Archit TanejaThis code has been more or less picked up from the vc4 and intel implementations of update_plane() funcs for cursor planes.
The update_plane() func is usually the drm_atomic_helper_update_plane func that will issue an atomic commit with the plane updates. Such commits are not intended to be done faster than the vsync rate.
The legacy cursor userspace API, on the other hand, expects the kernel to handle cursor updates immediately.
Create a fast path in update_plane, which updates the cursor registers and flushes the configuration. The fast path is taken when there is only a change in the cursor's position in the crtc, or a change in the cursor's crop co-ordinates. For anything else, we go via the slow path.
We take the slow path even when the fb changes, and when there is currently no fb tied to the plane. This should hopefully ensure that we always take a slow path for every new fb. This in turn should ensure that the fb is pinned/prepared.
--- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 7 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 110 +++++++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +7 -0
@@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,mdp5_ctl_set_pipeline (ctl, intf, lm); } +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc) +{ +struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc); + +return mdp5_crtc->ctl; +} +int mdp5_crtc_get_lm (struct drm_crtc *crtc) {struct mdp5_crtc *mdp5_crtc =to_mdp5_crtc (crtc);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +1 -0
@@ -246,6 +246,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);struct drm_plane *mdp5_plane_init (struct drm_device *dev,enum drm_plane_type type); +struct mdp5_ctl *mdp5_crtc_get_ctl (struct drm_crtc *crtc);uint32_t mdp5_crtc_vblank (struct drm_crtc *crtc);int mdp5_crtc_get_lm (struct drm_crtc *crtc);
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +107 -3
134 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel