Loading drivers/gpu/drm/msm/sde/sde_crtc.c +203 −107 Original line number Original line Diff line number Diff line Loading @@ -1691,6 +1691,181 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state) return max_t(u64, cstate->sbuf_clk_rate[1], tmp); return max_t(u64, cstate->sbuf_clk_rate[1], tmp); } } struct plane_state { struct sde_plane_state *sde_pstate; const struct drm_plane_state *drm_pstate; int stage; u32 pipe_id; }; static int pstate_cmp(const void *a, const void *b) { struct plane_state *pa = (struct plane_state *)a; struct plane_state *pb = (struct plane_state *)b; int rc = 0; int pa_zpos, pb_zpos; pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS); pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS); if (pa_zpos != pb_zpos) rc = pa_zpos - pb_zpos; else rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x; return rc; } /* * validate and set source split: * use pstates sorted by stage to check planes on same stage * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc, struct plane_state *pstates, int cnt) { struct plane_state *prv_pstate, *cur_pstate; struct sde_rect left_rect, right_rect; struct sde_kms *sde_kms; int32_t left_pid, right_pid; int32_t stage; int i, rc = 0; sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms || !sde_kms->catalog) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } for (i = 1; i < cnt; i++) { prv_pstate = &pstates[i - 1]; cur_pstate = &pstates[i]; if (prv_pstate->stage != cur_pstate->stage) continue; stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } /* * - planes are enumerated in pipe-priority order such that * planes with lower drm_id must be left-most in a shared * blend-stage when using source split. * - planes in source split must be contiguous in width * - planes in source split must have same dest yoff and height */ if ((right_pid < left_pid) && !sde_kms->catalog->pipe_order_type) { SDE_ERROR( "invalid src split cfg, stage:%d left:%d right:%d\n", stage, left_pid, right_pid); return -EINVAL; } else if (right_rect.x != (left_rect.x + left_rect.w)) { SDE_ERROR( "invalid coordinates, stage:%d l:%d-%d r:%d-%d\n", stage, left_rect.x, left_rect.w, right_rect.x, right_rect.w); return -EINVAL; } else if ((left_rect.y != right_rect.y) || (left_rect.h != right_rect.h)) { SDE_ERROR( "stage:%d invalid yoff/ht: l_yxh:%dx%d r_yxh:%dx%d\n", stage, left_rect.y, left_rect.h, right_rect.y, right_rect.h); return -EINVAL; } } return rc; } static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc, struct plane_state *pstates, int cnt) { struct plane_state *prv_pstate, *cur_pstate, *nxt_pstate; struct sde_kms *sde_kms; struct sde_rect left_rect, right_rect; int32_t left_pid, right_pid; int32_t stage; int i; sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms || !sde_kms->catalog) { SDE_ERROR("invalid parameters\n"); return; } if (!sde_kms->catalog->pipe_order_type) return; for (i = 0; i < cnt; i++) { prv_pstate = (i > 0) ? &pstates[i - 1] : NULL; cur_pstate = &pstates[i]; nxt_pstate = ((i + 1) < cnt) ? &pstates[i + 1] : NULL; if ((!prv_pstate) || (prv_pstate->stage != cur_pstate->stage)) { /* * reset if prv or nxt pipes are not in the same stage * as the cur pipe */ if ((!nxt_pstate) || (nxt_pstate->stage != cur_pstate->stage)) cur_pstate->sde_pstate->pipe_order_flags = 0; continue; } stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } cur_pstate->sde_pstate->pipe_order_flags = SDE_SSPP_RIGHT; prv_pstate->sde_pstate->pipe_order_flags = 0; } for (i = 0; i < cnt; i++) { cur_pstate = &pstates[i]; sde_plane_setup_src_split_order( cur_pstate->drm_pstate->plane, cur_pstate->sde_pstate->multirect_index, cur_pstate->sde_pstate->pipe_order_flags); } } static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_crtc_state *old_state, struct sde_crtc *sde_crtc, struct drm_crtc_state *old_state, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer) struct sde_crtc_mixer *mixer) Loading @@ -1700,6 +1875,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct drm_plane_state *state; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; struct sde_plane_state *pstate = NULL; struct sde_plane_state *pstate = NULL; struct plane_state *pstates = NULL; struct sde_format *format; struct sde_format *format; struct sde_hw_ctl *ctl; struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; struct sde_hw_mixer *lm; Loading @@ -1708,7 +1884,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, uint32_t prefill; uint32_t prefill; uint32_t stage_idx, lm_idx; uint32_t stage_idx, lm_idx; int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 }; int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 }; int i, rot_id = 0; int i, rot_id = 0, cnt = 0; bool bg_alpha_enable = false; bool bg_alpha_enable = false; if (!sde_crtc || !crtc->state || !mixer) { if (!sde_crtc || !crtc->state || !mixer) { Loading @@ -1726,6 +1902,11 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, sde_crtc->sbuf_rot_id = 0x0; sde_crtc->sbuf_rot_id = 0x0; sde_crtc->sbuf_rot_id_delta = 0x0; sde_crtc->sbuf_rot_id_delta = 0x0; pstates = kcalloc(SDE_PSTATES_MAX, sizeof(struct plane_state), GFP_KERNEL); if (!pstates) return; drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; state = plane->state; if (!state) if (!state) Loading Loading @@ -1765,7 +1946,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); if (!format) { if (!format) { SDE_ERROR("invalid format\n"); SDE_ERROR("invalid format\n"); return; goto end; } } if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) Loading Loading @@ -1801,8 +1982,22 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, mixer[lm_idx].mixer_op_mode |= mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; 1 << pstate->stage; } } if (cnt >= SDE_PSTATES_MAX) continue; pstates[cnt].sde_pstate = pstate; pstates[cnt].drm_pstate = state; pstates[cnt].stage = sde_plane_get_property( pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[cnt].pipe_id = sde_plane_pipe(plane); cnt++; } } sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); _sde_crtc_set_src_split_order(crtc, pstates, cnt); if (lm && lm->ops.setup_dim_layer) { if (lm && lm->ops.setup_dim_layer) { cstate = to_sde_crtc_state(crtc->state); cstate = to_sde_crtc_state(crtc->state); for (i = 0; i < cstate->num_dim_layers; i++) for (i = 0; i < cstate->num_dim_layers; i++) Loading @@ -1811,6 +2006,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, } } _sde_crtc_program_lm_output_roi(crtc); _sde_crtc_program_lm_output_roi(crtc); end: kfree(pstates); } } static void _sde_crtc_swap_mixers_for_right_partial_update( static void _sde_crtc_swap_mixers_for_right_partial_update( Loading Loading @@ -4651,31 +4849,6 @@ static void sde_crtc_enable(struct drm_crtc *crtc, sde_connector_schedule_status_work(cstate->connectors[i], true); sde_connector_schedule_status_work(cstate->connectors[i], true); } } struct plane_state { struct sde_plane_state *sde_pstate; const struct drm_plane_state *drm_pstate; int stage; u32 pipe_id; }; static int pstate_cmp(const void *a, const void *b) { struct plane_state *pa = (struct plane_state *)a; struct plane_state *pb = (struct plane_state *)b; int rc = 0; int pa_zpos, pb_zpos; pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS); pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS); if (pa_zpos != pb_zpos) rc = pa_zpos - pb_zpos; else rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x; return rc; } /* no input validation - caller API has all the checks */ /* no input validation - caller API has all the checks */ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, struct plane_state pstates[], int cnt) struct plane_state pstates[], int cnt) Loading Loading @@ -4901,7 +5074,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, struct sde_crtc *sde_crtc; struct sde_crtc *sde_crtc; struct plane_state *pstates = NULL; struct plane_state *pstates = NULL; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; struct sde_kms *kms; const struct drm_plane_state *pstate; const struct drm_plane_state *pstate; struct drm_plane *plane; struct drm_plane *plane; Loading @@ -4924,13 +5096,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, dev = crtc->dev; dev = crtc->dev; kms = _sde_crtc_get_kms(crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); cstate = to_sde_crtc_state(state); Loading Loading @@ -5013,7 +5178,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, continue; continue; pstates[cnt].sde_pstate = to_sde_plane_state(pstate); pstates[cnt].sde_pstate = to_sde_plane_state(pstate); pstates[cnt].sde_pstate->pipe_order_flags = 0x0; pstates[cnt].drm_pstate = pstate; pstates[cnt].drm_pstate = pstate; pstates[cnt].stage = sde_plane_get_property( pstates[cnt].stage = sde_plane_get_property( pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); Loading Loading @@ -5150,77 +5314,9 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; goto end; } } /* validate source split: rc = _sde_crtc_validate_src_split_order(crtc, pstates, cnt); * use pstates sorted by stage to check planes on same stage if (rc) * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ for (i = 1; i < cnt; i++) { struct plane_state *prv_pstate, *cur_pstate; struct sde_rect left_rect, right_rect; int32_t left_pid, right_pid; int32_t stage; prv_pstate = &pstates[i - 1]; cur_pstate = &pstates[i]; if (prv_pstate->stage != cur_pstate->stage) continue; stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } /** * - planes are enumerated in pipe-priority order such that * planes with lower drm_id must be left-most in a shared * blend-stage when using source split. * - planes in source split must be contiguous in width * - planes in source split must have same dest yoff and height */ if ((right_pid < left_pid) && !kms->catalog->pipe_order_type) { SDE_ERROR( "invalid src split cfg. priority mismatch. stage: %d left: %d right: %d\n", stage, left_pid, right_pid); rc = -EINVAL; goto end; } else if (right_rect.x != (left_rect.x + left_rect.w)) { SDE_ERROR( "non-contiguous coordinates for src split. stage: %d left: %d - %d right: %d - %d\n", stage, left_rect.x, left_rect.w, right_rect.x, right_rect.w); rc = -EINVAL; goto end; } else if ((left_rect.y != right_rect.y) || (left_rect.h != right_rect.h)) { SDE_ERROR( "source split at stage: %d. invalid yoff/height: l_y: %d r_y: %d l_h: %d r_h: %d\n", stage, left_rect.y, right_rect.y, left_rect.h, right_rect.h); rc = -EINVAL; goto end; goto end; } if (kms->catalog->pipe_order_type) cur_pstate->sde_pstate->pipe_order_flags = SDE_SSPP_RIGHT; } rc = _sde_crtc_check_rois(crtc, state); rc = _sde_crtc_check_rois(crtc, state); if (rc) { if (rc) { Loading drivers/gpu/drm/msm/sde/sde_hw_sspp.c +27 −4 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,31 @@ static void _sspp_setup_csc10_opmode(struct sde_hw_pipe *ctx, SDE_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode); SDE_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode); } } static void sde_hw_sspp_set_src_split_order(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index rect_mode, bool enable) { struct sde_hw_blk_reg_map *c; u32 opmode, idx, op_mode_off; if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) return; if (rect_mode == SDE_SSPP_RECT_SOLO || rect_mode == SDE_SSPP_RECT_0) op_mode_off = SSPP_SRC_OP_MODE; else op_mode_off = SSPP_SRC_OP_MODE_REC1; c = &ctx->hw; opmode = SDE_REG_READ(c, op_mode_off + idx); if (enable) opmode |= MDSS_MDP_OP_SPLIT_ORDER; else opmode &= ~MDSS_MDP_OP_SPLIT_ORDER; SDE_REG_WRITE(c, op_mode_off + idx, opmode); } /** /** * Setup source pixel format, flip, * Setup source pixel format, flip, */ */ Loading Loading @@ -294,15 +319,12 @@ static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx, c = &ctx->hw; c = &ctx->hw; opmode = SDE_REG_READ(c, op_mode_off + idx); opmode = SDE_REG_READ(c, op_mode_off + idx); opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD | opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD | MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE | MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE); MDSS_MDP_OP_SPLIT_ORDER); if (flags & SDE_SSPP_FLIP_LR) if (flags & SDE_SSPP_FLIP_LR) opmode |= MDSS_MDP_OP_FLIP_LR; opmode |= MDSS_MDP_OP_FLIP_LR; if (flags & SDE_SSPP_FLIP_UD) if (flags & SDE_SSPP_FLIP_UD) opmode |= MDSS_MDP_OP_FLIP_UD; opmode |= MDSS_MDP_OP_FLIP_UD; if ((flags & SDE_SSPP_RIGHT) && ctx->catalog->pipe_order_type) opmode |= MDSS_MDP_OP_SPLIT_ORDER; chroma_samp = fmt->chroma_sample; chroma_samp = fmt->chroma_sample; if (flags & SDE_SSPP_SOURCE_ROTATED_90) { if (flags & SDE_SSPP_SOURCE_ROTATED_90) { Loading Loading @@ -1111,6 +1133,7 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_solidfill = sde_hw_sspp_setup_solidfill; c->ops.setup_solidfill = sde_hw_sspp_setup_solidfill; c->ops.setup_pe = sde_hw_sspp_setup_pe_config; c->ops.setup_pe = sde_hw_sspp_setup_pe_config; c->ops.setup_secure_address = sde_hw_sspp_setup_secure; c->ops.setup_secure_address = sde_hw_sspp_setup_secure; c->ops.set_src_split_order = sde_hw_sspp_set_src_split_order; } } if (test_bit(SDE_SSPP_EXCL_RECT, &features)) if (test_bit(SDE_SSPP_EXCL_RECT, &features)) Loading drivers/gpu/drm/msm/sde/sde_hw_sspp.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -567,6 +567,15 @@ struct sde_hw_sspp_ops { enum sde_sspp_multirect_index index, enum sde_sspp_multirect_index index, bool enable); bool enable); /** * set_src_split_order - setup source split order priority * @ctx: Pointer to pipe context * @index: rectangle index in multirect * @enable: enable src split order */ void (*set_src_split_order)(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index index, bool enable); /** /** * setup_inverse_pma - enable/disable alpha unmultiply unit (PMA) * setup_inverse_pma - enable/disable alpha unmultiply unit (PMA) * @ctx: Pointer to pipe context * @ctx: Pointer to pipe context Loading drivers/gpu/drm/msm/sde/sde_plane.c +16 −4 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,20 @@ bool sde_plane_is_sec_ui_allowed(struct drm_plane *plane) return !(psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI)); return !(psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI)); } } void sde_plane_setup_src_split_order(struct drm_plane *plane, enum sde_sspp_multirect_index rect_mode, bool enable) { struct sde_plane *psde; if (!plane) return; psde = to_sde_plane(plane); if (psde->pipe_hw->ops.set_src_split_order) psde->pipe_hw->ops.set_src_split_order(psde->pipe_hw, rect_mode, enable); } /** /** * _sde_plane_calc_fill_level - calculate fill level of the given source format * _sde_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane * @plane: Pointer to drm plane Loading Loading @@ -1664,8 +1678,7 @@ static int _sde_plane_color_fill(struct sde_plane *psde, if (psde->pipe_hw->ops.setup_format) if (psde->pipe_hw->ops.setup_format) psde->pipe_hw->ops.setup_format(psde->pipe_hw, psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, blend_enable, fmt, blend_enable, SDE_SSPP_SOLID_FILL | SDE_SSPP_SOLID_FILL, pstate->pipe_order_flags, pstate->multirect_index); pstate->multirect_index); if (psde->pipe_hw->ops.setup_rects) if (psde->pipe_hw->ops.setup_rects) Loading Loading @@ -3793,7 +3806,7 @@ void sde_plane_set_error(struct drm_plane *plane, bool error) static int sde_plane_sspp_atomic_update(struct drm_plane *plane, static int sde_plane_sspp_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) struct drm_plane_state *old_state) { { uint32_t nplanes, src_flags; uint32_t nplanes, src_flags = 0; struct sde_plane *psde; struct sde_plane *psde; struct drm_plane_state *state; struct drm_plane_state *state; struct sde_plane_state *pstate; struct sde_plane_state *pstate; Loading Loading @@ -4054,7 +4067,6 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane, if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT || if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT || pstate->dirty & SDE_PLANE_DIRTY_RECTS) && pstate->dirty & SDE_PLANE_DIRTY_RECTS) && psde->pipe_hw->ops.setup_format) { psde->pipe_hw->ops.setup_format) { src_flags = pstate->pipe_order_flags; SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation); SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation); if (rstate->out_rotation & DRM_MODE_REFLECT_X) if (rstate->out_rotation & DRM_MODE_REFLECT_X) src_flags |= SDE_SSPP_FLIP_LR; src_flags |= SDE_SSPP_FLIP_LR; Loading drivers/gpu/drm/msm/sde/sde_plane.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -387,4 +387,13 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane); */ */ void sde_plane_clear_ubwc_error(struct drm_plane *plane); void sde_plane_clear_ubwc_error(struct drm_plane *plane); /* * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order * @plane: Pointer to DRM plane object * @rect_mode: multirect mode * @enable: enable/disable flag */ void sde_plane_setup_src_split_order(struct drm_plane *plane, enum sde_sspp_multirect_index rect_mode, bool enable); #endif /* _SDE_PLANE_H_ */ #endif /* _SDE_PLANE_H_ */ Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +203 −107 Original line number Original line Diff line number Diff line Loading @@ -1691,6 +1691,181 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state) return max_t(u64, cstate->sbuf_clk_rate[1], tmp); return max_t(u64, cstate->sbuf_clk_rate[1], tmp); } } struct plane_state { struct sde_plane_state *sde_pstate; const struct drm_plane_state *drm_pstate; int stage; u32 pipe_id; }; static int pstate_cmp(const void *a, const void *b) { struct plane_state *pa = (struct plane_state *)a; struct plane_state *pb = (struct plane_state *)b; int rc = 0; int pa_zpos, pb_zpos; pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS); pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS); if (pa_zpos != pb_zpos) rc = pa_zpos - pb_zpos; else rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x; return rc; } /* * validate and set source split: * use pstates sorted by stage to check planes on same stage * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ static int _sde_crtc_validate_src_split_order(struct drm_crtc *crtc, struct plane_state *pstates, int cnt) { struct plane_state *prv_pstate, *cur_pstate; struct sde_rect left_rect, right_rect; struct sde_kms *sde_kms; int32_t left_pid, right_pid; int32_t stage; int i, rc = 0; sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms || !sde_kms->catalog) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } for (i = 1; i < cnt; i++) { prv_pstate = &pstates[i - 1]; cur_pstate = &pstates[i]; if (prv_pstate->stage != cur_pstate->stage) continue; stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } /* * - planes are enumerated in pipe-priority order such that * planes with lower drm_id must be left-most in a shared * blend-stage when using source split. * - planes in source split must be contiguous in width * - planes in source split must have same dest yoff and height */ if ((right_pid < left_pid) && !sde_kms->catalog->pipe_order_type) { SDE_ERROR( "invalid src split cfg, stage:%d left:%d right:%d\n", stage, left_pid, right_pid); return -EINVAL; } else if (right_rect.x != (left_rect.x + left_rect.w)) { SDE_ERROR( "invalid coordinates, stage:%d l:%d-%d r:%d-%d\n", stage, left_rect.x, left_rect.w, right_rect.x, right_rect.w); return -EINVAL; } else if ((left_rect.y != right_rect.y) || (left_rect.h != right_rect.h)) { SDE_ERROR( "stage:%d invalid yoff/ht: l_yxh:%dx%d r_yxh:%dx%d\n", stage, left_rect.y, left_rect.h, right_rect.y, right_rect.h); return -EINVAL; } } return rc; } static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc, struct plane_state *pstates, int cnt) { struct plane_state *prv_pstate, *cur_pstate, *nxt_pstate; struct sde_kms *sde_kms; struct sde_rect left_rect, right_rect; int32_t left_pid, right_pid; int32_t stage; int i; sde_kms = _sde_crtc_get_kms(crtc); if (!sde_kms || !sde_kms->catalog) { SDE_ERROR("invalid parameters\n"); return; } if (!sde_kms->catalog->pipe_order_type) return; for (i = 0; i < cnt; i++) { prv_pstate = (i > 0) ? &pstates[i - 1] : NULL; cur_pstate = &pstates[i]; nxt_pstate = ((i + 1) < cnt) ? &pstates[i + 1] : NULL; if ((!prv_pstate) || (prv_pstate->stage != cur_pstate->stage)) { /* * reset if prv or nxt pipes are not in the same stage * as the cur pipe */ if ((!nxt_pstate) || (nxt_pstate->stage != cur_pstate->stage)) cur_pstate->sde_pstate->pipe_order_flags = 0; continue; } stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } cur_pstate->sde_pstate->pipe_order_flags = SDE_SSPP_RIGHT; prv_pstate->sde_pstate->pipe_order_flags = 0; } for (i = 0; i < cnt; i++) { cur_pstate = &pstates[i]; sde_plane_setup_src_split_order( cur_pstate->drm_pstate->plane, cur_pstate->sde_pstate->multirect_index, cur_pstate->sde_pstate->pipe_order_flags); } } static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_crtc_state *old_state, struct sde_crtc *sde_crtc, struct drm_crtc_state *old_state, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer) struct sde_crtc_mixer *mixer) Loading @@ -1700,6 +1875,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct drm_plane_state *state; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; struct sde_plane_state *pstate = NULL; struct sde_plane_state *pstate = NULL; struct plane_state *pstates = NULL; struct sde_format *format; struct sde_format *format; struct sde_hw_ctl *ctl; struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; struct sde_hw_mixer *lm; Loading @@ -1708,7 +1884,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, uint32_t prefill; uint32_t prefill; uint32_t stage_idx, lm_idx; uint32_t stage_idx, lm_idx; int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 }; int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 }; int i, rot_id = 0; int i, rot_id = 0, cnt = 0; bool bg_alpha_enable = false; bool bg_alpha_enable = false; if (!sde_crtc || !crtc->state || !mixer) { if (!sde_crtc || !crtc->state || !mixer) { Loading @@ -1726,6 +1902,11 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, sde_crtc->sbuf_rot_id = 0x0; sde_crtc->sbuf_rot_id = 0x0; sde_crtc->sbuf_rot_id_delta = 0x0; sde_crtc->sbuf_rot_id_delta = 0x0; pstates = kcalloc(SDE_PSTATES_MAX, sizeof(struct plane_state), GFP_KERNEL); if (!pstates) return; drm_atomic_crtc_for_each_plane(plane, crtc) { drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; state = plane->state; if (!state) if (!state) Loading Loading @@ -1765,7 +1946,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); if (!format) { if (!format) { SDE_ERROR("invalid format\n"); SDE_ERROR("invalid format\n"); return; goto end; } } if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) Loading Loading @@ -1801,8 +1982,22 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, mixer[lm_idx].mixer_op_mode |= mixer[lm_idx].mixer_op_mode |= 1 << pstate->stage; 1 << pstate->stage; } } if (cnt >= SDE_PSTATES_MAX) continue; pstates[cnt].sde_pstate = pstate; pstates[cnt].drm_pstate = state; pstates[cnt].stage = sde_plane_get_property( pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[cnt].pipe_id = sde_plane_pipe(plane); cnt++; } } sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); _sde_crtc_set_src_split_order(crtc, pstates, cnt); if (lm && lm->ops.setup_dim_layer) { if (lm && lm->ops.setup_dim_layer) { cstate = to_sde_crtc_state(crtc->state); cstate = to_sde_crtc_state(crtc->state); for (i = 0; i < cstate->num_dim_layers; i++) for (i = 0; i < cstate->num_dim_layers; i++) Loading @@ -1811,6 +2006,9 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, } } _sde_crtc_program_lm_output_roi(crtc); _sde_crtc_program_lm_output_roi(crtc); end: kfree(pstates); } } static void _sde_crtc_swap_mixers_for_right_partial_update( static void _sde_crtc_swap_mixers_for_right_partial_update( Loading Loading @@ -4651,31 +4849,6 @@ static void sde_crtc_enable(struct drm_crtc *crtc, sde_connector_schedule_status_work(cstate->connectors[i], true); sde_connector_schedule_status_work(cstate->connectors[i], true); } } struct plane_state { struct sde_plane_state *sde_pstate; const struct drm_plane_state *drm_pstate; int stage; u32 pipe_id; }; static int pstate_cmp(const void *a, const void *b) { struct plane_state *pa = (struct plane_state *)a; struct plane_state *pb = (struct plane_state *)b; int rc = 0; int pa_zpos, pb_zpos; pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS); pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS); if (pa_zpos != pb_zpos) rc = pa_zpos - pb_zpos; else rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x; return rc; } /* no input validation - caller API has all the checks */ /* no input validation - caller API has all the checks */ static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state, struct plane_state pstates[], int cnt) struct plane_state pstates[], int cnt) Loading Loading @@ -4901,7 +5074,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, struct sde_crtc *sde_crtc; struct sde_crtc *sde_crtc; struct plane_state *pstates = NULL; struct plane_state *pstates = NULL; struct sde_crtc_state *cstate; struct sde_crtc_state *cstate; struct sde_kms *kms; const struct drm_plane_state *pstate; const struct drm_plane_state *pstate; struct drm_plane *plane; struct drm_plane *plane; Loading @@ -4924,13 +5096,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, dev = crtc->dev; dev = crtc->dev; kms = _sde_crtc_get_kms(crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid parameters\n"); return -EINVAL; } sde_crtc = to_sde_crtc(crtc); sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); cstate = to_sde_crtc_state(state); Loading Loading @@ -5013,7 +5178,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, continue; continue; pstates[cnt].sde_pstate = to_sde_plane_state(pstate); pstates[cnt].sde_pstate = to_sde_plane_state(pstate); pstates[cnt].sde_pstate->pipe_order_flags = 0x0; pstates[cnt].drm_pstate = pstate; pstates[cnt].drm_pstate = pstate; pstates[cnt].stage = sde_plane_get_property( pstates[cnt].stage = sde_plane_get_property( pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); Loading Loading @@ -5150,77 +5314,9 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; goto end; } } /* validate source split: rc = _sde_crtc_validate_src_split_order(crtc, pstates, cnt); * use pstates sorted by stage to check planes on same stage if (rc) * we assume that all pipes are in source split so its valid to compare * without taking into account left/right mixer placement */ for (i = 1; i < cnt; i++) { struct plane_state *prv_pstate, *cur_pstate; struct sde_rect left_rect, right_rect; int32_t left_pid, right_pid; int32_t stage; prv_pstate = &pstates[i - 1]; cur_pstate = &pstates[i]; if (prv_pstate->stage != cur_pstate->stage) continue; stage = cur_pstate->stage; left_pid = prv_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&left_rect, prv_pstate->drm_pstate->crtc_x, prv_pstate->drm_pstate->crtc_y, prv_pstate->drm_pstate->crtc_w, prv_pstate->drm_pstate->crtc_h, false); right_pid = cur_pstate->sde_pstate->base.plane->base.id; POPULATE_RECT(&right_rect, cur_pstate->drm_pstate->crtc_x, cur_pstate->drm_pstate->crtc_y, cur_pstate->drm_pstate->crtc_w, cur_pstate->drm_pstate->crtc_h, false); if (right_rect.x < left_rect.x) { swap(left_pid, right_pid); swap(left_rect, right_rect); swap(prv_pstate, cur_pstate); } /** * - planes are enumerated in pipe-priority order such that * planes with lower drm_id must be left-most in a shared * blend-stage when using source split. * - planes in source split must be contiguous in width * - planes in source split must have same dest yoff and height */ if ((right_pid < left_pid) && !kms->catalog->pipe_order_type) { SDE_ERROR( "invalid src split cfg. priority mismatch. stage: %d left: %d right: %d\n", stage, left_pid, right_pid); rc = -EINVAL; goto end; } else if (right_rect.x != (left_rect.x + left_rect.w)) { SDE_ERROR( "non-contiguous coordinates for src split. stage: %d left: %d - %d right: %d - %d\n", stage, left_rect.x, left_rect.w, right_rect.x, right_rect.w); rc = -EINVAL; goto end; } else if ((left_rect.y != right_rect.y) || (left_rect.h != right_rect.h)) { SDE_ERROR( "source split at stage: %d. invalid yoff/height: l_y: %d r_y: %d l_h: %d r_h: %d\n", stage, left_rect.y, right_rect.y, left_rect.h, right_rect.h); rc = -EINVAL; goto end; goto end; } if (kms->catalog->pipe_order_type) cur_pstate->sde_pstate->pipe_order_flags = SDE_SSPP_RIGHT; } rc = _sde_crtc_check_rois(crtc, state); rc = _sde_crtc_check_rois(crtc, state); if (rc) { if (rc) { Loading
drivers/gpu/drm/msm/sde/sde_hw_sspp.c +27 −4 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,31 @@ static void _sspp_setup_csc10_opmode(struct sde_hw_pipe *ctx, SDE_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode); SDE_REG_WRITE(&ctx->hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode); } } static void sde_hw_sspp_set_src_split_order(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index rect_mode, bool enable) { struct sde_hw_blk_reg_map *c; u32 opmode, idx, op_mode_off; if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx)) return; if (rect_mode == SDE_SSPP_RECT_SOLO || rect_mode == SDE_SSPP_RECT_0) op_mode_off = SSPP_SRC_OP_MODE; else op_mode_off = SSPP_SRC_OP_MODE_REC1; c = &ctx->hw; opmode = SDE_REG_READ(c, op_mode_off + idx); if (enable) opmode |= MDSS_MDP_OP_SPLIT_ORDER; else opmode &= ~MDSS_MDP_OP_SPLIT_ORDER; SDE_REG_WRITE(c, op_mode_off + idx, opmode); } /** /** * Setup source pixel format, flip, * Setup source pixel format, flip, */ */ Loading Loading @@ -294,15 +319,12 @@ static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx, c = &ctx->hw; c = &ctx->hw; opmode = SDE_REG_READ(c, op_mode_off + idx); opmode = SDE_REG_READ(c, op_mode_off + idx); opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD | opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD | MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE | MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE); MDSS_MDP_OP_SPLIT_ORDER); if (flags & SDE_SSPP_FLIP_LR) if (flags & SDE_SSPP_FLIP_LR) opmode |= MDSS_MDP_OP_FLIP_LR; opmode |= MDSS_MDP_OP_FLIP_LR; if (flags & SDE_SSPP_FLIP_UD) if (flags & SDE_SSPP_FLIP_UD) opmode |= MDSS_MDP_OP_FLIP_UD; opmode |= MDSS_MDP_OP_FLIP_UD; if ((flags & SDE_SSPP_RIGHT) && ctx->catalog->pipe_order_type) opmode |= MDSS_MDP_OP_SPLIT_ORDER; chroma_samp = fmt->chroma_sample; chroma_samp = fmt->chroma_sample; if (flags & SDE_SSPP_SOURCE_ROTATED_90) { if (flags & SDE_SSPP_SOURCE_ROTATED_90) { Loading Loading @@ -1111,6 +1133,7 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_solidfill = sde_hw_sspp_setup_solidfill; c->ops.setup_solidfill = sde_hw_sspp_setup_solidfill; c->ops.setup_pe = sde_hw_sspp_setup_pe_config; c->ops.setup_pe = sde_hw_sspp_setup_pe_config; c->ops.setup_secure_address = sde_hw_sspp_setup_secure; c->ops.setup_secure_address = sde_hw_sspp_setup_secure; c->ops.set_src_split_order = sde_hw_sspp_set_src_split_order; } } if (test_bit(SDE_SSPP_EXCL_RECT, &features)) if (test_bit(SDE_SSPP_EXCL_RECT, &features)) Loading
drivers/gpu/drm/msm/sde/sde_hw_sspp.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -567,6 +567,15 @@ struct sde_hw_sspp_ops { enum sde_sspp_multirect_index index, enum sde_sspp_multirect_index index, bool enable); bool enable); /** * set_src_split_order - setup source split order priority * @ctx: Pointer to pipe context * @index: rectangle index in multirect * @enable: enable src split order */ void (*set_src_split_order)(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index index, bool enable); /** /** * setup_inverse_pma - enable/disable alpha unmultiply unit (PMA) * setup_inverse_pma - enable/disable alpha unmultiply unit (PMA) * @ctx: Pointer to pipe context * @ctx: Pointer to pipe context Loading
drivers/gpu/drm/msm/sde/sde_plane.c +16 −4 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,20 @@ bool sde_plane_is_sec_ui_allowed(struct drm_plane *plane) return !(psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI)); return !(psde->features & BIT(SDE_SSPP_BLOCK_SEC_UI)); } } void sde_plane_setup_src_split_order(struct drm_plane *plane, enum sde_sspp_multirect_index rect_mode, bool enable) { struct sde_plane *psde; if (!plane) return; psde = to_sde_plane(plane); if (psde->pipe_hw->ops.set_src_split_order) psde->pipe_hw->ops.set_src_split_order(psde->pipe_hw, rect_mode, enable); } /** /** * _sde_plane_calc_fill_level - calculate fill level of the given source format * _sde_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane * @plane: Pointer to drm plane Loading Loading @@ -1664,8 +1678,7 @@ static int _sde_plane_color_fill(struct sde_plane *psde, if (psde->pipe_hw->ops.setup_format) if (psde->pipe_hw->ops.setup_format) psde->pipe_hw->ops.setup_format(psde->pipe_hw, psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, blend_enable, fmt, blend_enable, SDE_SSPP_SOLID_FILL | SDE_SSPP_SOLID_FILL, pstate->pipe_order_flags, pstate->multirect_index); pstate->multirect_index); if (psde->pipe_hw->ops.setup_rects) if (psde->pipe_hw->ops.setup_rects) Loading Loading @@ -3793,7 +3806,7 @@ void sde_plane_set_error(struct drm_plane *plane, bool error) static int sde_plane_sspp_atomic_update(struct drm_plane *plane, static int sde_plane_sspp_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) struct drm_plane_state *old_state) { { uint32_t nplanes, src_flags; uint32_t nplanes, src_flags = 0; struct sde_plane *psde; struct sde_plane *psde; struct drm_plane_state *state; struct drm_plane_state *state; struct sde_plane_state *pstate; struct sde_plane_state *pstate; Loading Loading @@ -4054,7 +4067,6 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane, if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT || if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT || pstate->dirty & SDE_PLANE_DIRTY_RECTS) && pstate->dirty & SDE_PLANE_DIRTY_RECTS) && psde->pipe_hw->ops.setup_format) { psde->pipe_hw->ops.setup_format) { src_flags = pstate->pipe_order_flags; SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation); SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation); if (rstate->out_rotation & DRM_MODE_REFLECT_X) if (rstate->out_rotation & DRM_MODE_REFLECT_X) src_flags |= SDE_SSPP_FLIP_LR; src_flags |= SDE_SSPP_FLIP_LR; Loading
drivers/gpu/drm/msm/sde/sde_plane.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -387,4 +387,13 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane); */ */ void sde_plane_clear_ubwc_error(struct drm_plane *plane); void sde_plane_clear_ubwc_error(struct drm_plane *plane); /* * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order * @plane: Pointer to DRM plane object * @rect_mode: multirect mode * @enable: enable/disable flag */ void sde_plane_setup_src_split_order(struct drm_plane *plane, enum sde_sspp_multirect_index rect_mode, bool enable); #endif /* _SDE_PLANE_H_ */ #endif /* _SDE_PLANE_H_ */