Loading drivers/gpu/drm/msm/msm_drv.h +2 −0 Original line number Diff line number Diff line Loading @@ -445,6 +445,7 @@ struct msm_display_topology { * @wide_bus_en: wide-bus mode cfg for interface module * @mdp_transfer_time_us Specifies the mdp transfer time for command mode * panels in microseconds. * @vpadding: panel stacking height */ struct msm_mode_info { uint32_t frame_rate; Loading @@ -458,6 +459,7 @@ struct msm_mode_info { struct msm_roi_caps roi_caps; bool wide_bus_en; u32 mdp_transfer_time_us; u32 vpadding; }; /** Loading drivers/gpu/drm/msm/sde/sde_crtc.c +143 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,9 @@ static struct sde_crtc_custom_events custom_events[] = { #define MAX_FRAME_COUNT 1000 #define MILI_TO_MICRO 1000 /* Line padding ratio limit */ #define MAX_VPADDING_RATIO 3 static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; Loading Loading @@ -1058,6 +1061,18 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, cstate->lm_roi[i].y; } /* update dim layer rect for panel stacking crtc */ if (cstate->padding_height) { uint32_t padding_y, padding_start, padding_height; sde_crtc_calc_vpadding_param(crtc->state, split_dim_layer.rect.y, split_dim_layer.rect.h, &padding_y, &padding_start, &padding_height); split_dim_layer.rect.y = padding_y; split_dim_layer.rect.h = padding_height; } SDE_EVT32_VERBOSE(DRMID(crtc), cstate->lm_roi[i].x, cstate->lm_roi[i].y, Loading Loading @@ -1601,6 +1616,84 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, return 0; } static u32 _sde_crtc_calc_gcd(u32 a, u32 b) { if (b == 0) return a; return _sde_crtc_calc_gcd(b, a % b); } static int _sde_crtc_check_panel_stacking(struct drm_crtc *crtc, struct drm_crtc_state *state) { struct sde_kms *kms; struct sde_crtc *sde_crtc; struct sde_crtc_state *sde_crtc_state; struct drm_connector *conn; struct msm_mode_info mode_info; u32 gcd, m, n; int rc; kms = _sde_crtc_get_kms(crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid kms\n"); return -EINVAL; } if (!kms->catalog->has_line_insertion) return 0; sde_crtc = to_sde_crtc(crtc); sde_crtc_state = to_sde_crtc_state(state); /* panel stacking only support single connector */ if (sde_crtc_state->num_connectors != 1) return 0; conn = sde_crtc_state->connectors[0]; rc = sde_connector_get_mode_info(conn->state, &mode_info); if (rc) { SDE_ERROR("failed to get mode info\n"); return -EINVAL; } if (!mode_info.vpadding) goto done; if (mode_info.vpadding < state->mode.vdisplay) { SDE_ERROR("padding height %d is less than vdisplay %d\n", mode_info.vpadding, state->mode.vdisplay); return -EINVAL; } /* skip calculation if already cached */ if (mode_info.vpadding == sde_crtc_state->padding_height) return 0; gcd = _sde_crtc_calc_gcd(mode_info.vpadding, state->mode.vdisplay); if (!gcd) { SDE_ERROR("zero gcd found for padding height %d %d\n", mode_info.vpadding, state->mode.vdisplay); return -EINVAL; } m = state->mode.vdisplay / gcd; n = mode_info.vpadding / gcd - m; if (m > MAX_VPADDING_RATIO || n > MAX_VPADDING_RATIO) { SDE_ERROR("unsupported panel stacking pattern %d:%d", m, n); return -EINVAL; } sde_crtc_state->padding_active = m; sde_crtc_state->padding_dummy = n; done: sde_crtc_state->padding_height = mode_info.vpadding; return 0; } static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; Loading Loading @@ -5340,6 +5433,13 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } rc = _sde_crtc_check_panel_stacking(crtc, state); if (rc) { SDE_ERROR("crtc%d failed panel stacking check %d\n", crtc->base.id, rc); goto end; } end: kfree(pstates); kfree(multirect_plane); Loading Loading @@ -6872,3 +6972,46 @@ void sde_crtc_update_cont_splash_settings(struct drm_crtc *crtc) sde_crtc = to_sde_crtc(crtc); sde_crtc->cur_perf.core_clk_rate = kms->perf.max_core_clk_rate; } int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y, uint32_t *padding_start, uint32_t *padding_height) { struct sde_kms *kms; struct sde_crtc_state *cstate = to_sde_crtc_state(state); u32 y_blocks, y_remain, y_start; u32 h_start, h_blocks, h_end, h_total; u32 m, n; kms = _sde_crtc_get_kms(state->crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid kms\n"); return -EINVAL; } if (!kms->catalog->has_line_insertion) return 0; if (!cstate->padding_active) { SDE_ERROR("zero padding active value\n"); return -EINVAL; } m = cstate->padding_active; n = m + cstate->padding_dummy; y_blocks = crtc_y / m; y_remain = crtc_y - y_blocks * m; y_start = y_remain + y_blocks * n; h_start = m - y_remain; h_blocks = (crtc_h - h_start) / m; h_end = (crtc_h - h_start) - h_blocks * m; if (h_end) h_end += cstate->padding_dummy; h_total = h_start + h_end + h_blocks * n; *padding_y = y_start; *padding_start = h_start; *padding_height = h_total; return 0; } drivers/gpu/drm/msm/sde/sde_crtc.h +20 −0 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ struct sde_crtc_respool { * @sbuf_clk_rate : previous and current user specified inline rotator clock * @sbuf_clk_shifted : whether or not sbuf_clk_rate has been shifted as part * of crtc atomic check * @padding_height: panel height after line padding * @padding_active: active lines in panel stacking pattern * @padding_dummy: dummy lines in panel stacking pattern */ struct sde_crtc_state { struct drm_crtc_state base; Loading Loading @@ -429,6 +432,10 @@ struct sde_crtc_state { u64 sbuf_clk_rate[2]; bool sbuf_clk_shifted; u32 padding_height; u32 padding_active; u32 padding_dummy; struct sde_crtc_respool rp; }; Loading Loading @@ -830,4 +837,17 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state); */ void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count); /** * sde_crtc_calc_vpadding_param - calculate vpadding parameters * @state: Pointer to DRM crtc state object * @crtc_y: Plane's CRTC_Y offset * @crtc_h: Plane's CRTC_H size * @padding_y: Padding Y offset * @padding_start: Padding start offset * @padding_height: Padding height in total */ int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y, uint32_t *padding_start, uint32_t *padding_height); #endif /* _SDE_CRTC_H_ */ drivers/gpu/drm/msm/sde/sde_hw_catalog.c +7 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ enum sde_prop { UBWC_BW_CALC_VERSION, PIPE_ORDER_VERSION, SEC_SID_MASK, LINE_INSERTION, SDE_PROP_MAX, }; Loading Loading @@ -447,6 +448,7 @@ static struct sde_prop_type sde_prop[] = { {PIPE_ORDER_VERSION, "qcom,sde-pipe-order-version", false, PROP_TYPE_U32}, {SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY}, {LINE_INSERTION, "qcom,sde-has-line-insertion", false, PROP_TYPE_BOOL}, }; static struct sde_prop_type sde_perf_prop[] = { Loading Loading @@ -1397,6 +1399,9 @@ static int sde_sspp_parse_dt(struct device_node *np, set_bit(SDE_SSPP_TS_PREFILL_REC1, &sspp->features); } if (sde_cfg->has_line_insertion) set_bit(SDE_SSPP_LINE_INSERTION, &sspp->features); sblk->smart_dma_priority = PROP_VALUE_ACCESS(prop_value, SSPP_SMART_DMA, i); Loading Loading @@ -3054,6 +3059,8 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0); cfg->pipe_order_type = PROP_VALUE_ACCESS(prop_value, PIPE_ORDER_VERSION, 0); cfg->has_line_insertion = PROP_VALUE_ACCESS(prop_value, LINE_INSERTION, 0); end: kfree(prop_value); return rc; Loading drivers/gpu/drm/msm/sde/sde_hw_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ enum { * @SDE_SSPP_BLOCK_SEC_UI Blocks secure-ui layers * @SDE_SSPP_QOS_FL_NOCALC Avoid fill level calculation for QoS/danger/safe * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support * @SDE_SSPP_LINE_INSERTION Line insertion support * @SDE_SSPP_MAX maximum value */ enum { Loading Loading @@ -199,6 +200,7 @@ enum { SDE_SSPP_BLOCK_SEC_UI, SDE_SSPP_QOS_FL_NOCALC, SDE_SSPP_SCALER_QSEED3LITE, SDE_SSPP_LINE_INSERTION, SDE_SSPP_MAX }; Loading Loading @@ -1109,6 +1111,7 @@ struct sde_mdss_cfg { bool delay_prg_fetch_start; bool has_qsync; bool has_3d_merge_reset; bool has_line_insertion; bool sui_misr_supported; u32 sui_block_xin_mask; Loading Loading
drivers/gpu/drm/msm/msm_drv.h +2 −0 Original line number Diff line number Diff line Loading @@ -445,6 +445,7 @@ struct msm_display_topology { * @wide_bus_en: wide-bus mode cfg for interface module * @mdp_transfer_time_us Specifies the mdp transfer time for command mode * panels in microseconds. * @vpadding: panel stacking height */ struct msm_mode_info { uint32_t frame_rate; Loading @@ -458,6 +459,7 @@ struct msm_mode_info { struct msm_roi_caps roi_caps; bool wide_bus_en; u32 mdp_transfer_time_us; u32 vpadding; }; /** Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +143 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,9 @@ static struct sde_crtc_custom_events custom_events[] = { #define MAX_FRAME_COUNT 1000 #define MILI_TO_MICRO 1000 /* Line padding ratio limit */ #define MAX_VPADDING_RATIO 3 static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; Loading Loading @@ -1058,6 +1061,18 @@ static void _sde_crtc_setup_dim_layer_cfg(struct drm_crtc *crtc, cstate->lm_roi[i].y; } /* update dim layer rect for panel stacking crtc */ if (cstate->padding_height) { uint32_t padding_y, padding_start, padding_height; sde_crtc_calc_vpadding_param(crtc->state, split_dim_layer.rect.y, split_dim_layer.rect.h, &padding_y, &padding_start, &padding_height); split_dim_layer.rect.y = padding_y; split_dim_layer.rect.h = padding_height; } SDE_EVT32_VERBOSE(DRMID(crtc), cstate->lm_roi[i].x, cstate->lm_roi[i].y, Loading Loading @@ -1601,6 +1616,84 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, return 0; } static u32 _sde_crtc_calc_gcd(u32 a, u32 b) { if (b == 0) return a; return _sde_crtc_calc_gcd(b, a % b); } static int _sde_crtc_check_panel_stacking(struct drm_crtc *crtc, struct drm_crtc_state *state) { struct sde_kms *kms; struct sde_crtc *sde_crtc; struct sde_crtc_state *sde_crtc_state; struct drm_connector *conn; struct msm_mode_info mode_info; u32 gcd, m, n; int rc; kms = _sde_crtc_get_kms(crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid kms\n"); return -EINVAL; } if (!kms->catalog->has_line_insertion) return 0; sde_crtc = to_sde_crtc(crtc); sde_crtc_state = to_sde_crtc_state(state); /* panel stacking only support single connector */ if (sde_crtc_state->num_connectors != 1) return 0; conn = sde_crtc_state->connectors[0]; rc = sde_connector_get_mode_info(conn->state, &mode_info); if (rc) { SDE_ERROR("failed to get mode info\n"); return -EINVAL; } if (!mode_info.vpadding) goto done; if (mode_info.vpadding < state->mode.vdisplay) { SDE_ERROR("padding height %d is less than vdisplay %d\n", mode_info.vpadding, state->mode.vdisplay); return -EINVAL; } /* skip calculation if already cached */ if (mode_info.vpadding == sde_crtc_state->padding_height) return 0; gcd = _sde_crtc_calc_gcd(mode_info.vpadding, state->mode.vdisplay); if (!gcd) { SDE_ERROR("zero gcd found for padding height %d %d\n", mode_info.vpadding, state->mode.vdisplay); return -EINVAL; } m = state->mode.vdisplay / gcd; n = mode_info.vpadding / gcd - m; if (m > MAX_VPADDING_RATIO || n > MAX_VPADDING_RATIO) { SDE_ERROR("unsupported panel stacking pattern %d:%d", m, n); return -EINVAL; } sde_crtc_state->padding_active = m; sde_crtc_state->padding_dummy = n; done: sde_crtc_state->padding_height = mode_info.vpadding; return 0; } static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc; Loading Loading @@ -5340,6 +5433,13 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } rc = _sde_crtc_check_panel_stacking(crtc, state); if (rc) { SDE_ERROR("crtc%d failed panel stacking check %d\n", crtc->base.id, rc); goto end; } end: kfree(pstates); kfree(multirect_plane); Loading Loading @@ -6872,3 +6972,46 @@ void sde_crtc_update_cont_splash_settings(struct drm_crtc *crtc) sde_crtc = to_sde_crtc(crtc); sde_crtc->cur_perf.core_clk_rate = kms->perf.max_core_clk_rate; } int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y, uint32_t *padding_start, uint32_t *padding_height) { struct sde_kms *kms; struct sde_crtc_state *cstate = to_sde_crtc_state(state); u32 y_blocks, y_remain, y_start; u32 h_start, h_blocks, h_end, h_total; u32 m, n; kms = _sde_crtc_get_kms(state->crtc); if (!kms || !kms->catalog) { SDE_ERROR("invalid kms\n"); return -EINVAL; } if (!kms->catalog->has_line_insertion) return 0; if (!cstate->padding_active) { SDE_ERROR("zero padding active value\n"); return -EINVAL; } m = cstate->padding_active; n = m + cstate->padding_dummy; y_blocks = crtc_y / m; y_remain = crtc_y - y_blocks * m; y_start = y_remain + y_blocks * n; h_start = m - y_remain; h_blocks = (crtc_h - h_start) / m; h_end = (crtc_h - h_start) - h_blocks * m; if (h_end) h_end += cstate->padding_dummy; h_total = h_start + h_end + h_blocks * n; *padding_y = y_start; *padding_start = h_start; *padding_height = h_total; return 0; }
drivers/gpu/drm/msm/sde/sde_crtc.h +20 −0 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ struct sde_crtc_respool { * @sbuf_clk_rate : previous and current user specified inline rotator clock * @sbuf_clk_shifted : whether or not sbuf_clk_rate has been shifted as part * of crtc atomic check * @padding_height: panel height after line padding * @padding_active: active lines in panel stacking pattern * @padding_dummy: dummy lines in panel stacking pattern */ struct sde_crtc_state { struct drm_crtc_state base; Loading Loading @@ -429,6 +432,10 @@ struct sde_crtc_state { u64 sbuf_clk_rate[2]; bool sbuf_clk_shifted; u32 padding_height; u32 padding_active; u32 padding_dummy; struct sde_crtc_respool rp; }; Loading Loading @@ -830,4 +837,17 @@ uint64_t sde_crtc_get_sbuf_clk(struct drm_crtc_state *state); */ void sde_crtc_misr_setup(struct drm_crtc *crtc, bool enable, u32 frame_count); /** * sde_crtc_calc_vpadding_param - calculate vpadding parameters * @state: Pointer to DRM crtc state object * @crtc_y: Plane's CRTC_Y offset * @crtc_h: Plane's CRTC_H size * @padding_y: Padding Y offset * @padding_start: Padding start offset * @padding_height: Padding height in total */ int sde_crtc_calc_vpadding_param(struct drm_crtc_state *state, uint32_t crtc_y, uint32_t crtc_h, uint32_t *padding_y, uint32_t *padding_start, uint32_t *padding_height); #endif /* _SDE_CRTC_H_ */
drivers/gpu/drm/msm/sde/sde_hw_catalog.c +7 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,7 @@ enum sde_prop { UBWC_BW_CALC_VERSION, PIPE_ORDER_VERSION, SEC_SID_MASK, LINE_INSERTION, SDE_PROP_MAX, }; Loading Loading @@ -447,6 +448,7 @@ static struct sde_prop_type sde_prop[] = { {PIPE_ORDER_VERSION, "qcom,sde-pipe-order-version", false, PROP_TYPE_U32}, {SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY}, {LINE_INSERTION, "qcom,sde-has-line-insertion", false, PROP_TYPE_BOOL}, }; static struct sde_prop_type sde_perf_prop[] = { Loading Loading @@ -1397,6 +1399,9 @@ static int sde_sspp_parse_dt(struct device_node *np, set_bit(SDE_SSPP_TS_PREFILL_REC1, &sspp->features); } if (sde_cfg->has_line_insertion) set_bit(SDE_SSPP_LINE_INSERTION, &sspp->features); sblk->smart_dma_priority = PROP_VALUE_ACCESS(prop_value, SSPP_SMART_DMA, i); Loading Loading @@ -3054,6 +3059,8 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg) cfg->has_idle_pc = PROP_VALUE_ACCESS(prop_value, IDLE_PC, 0); cfg->pipe_order_type = PROP_VALUE_ACCESS(prop_value, PIPE_ORDER_VERSION, 0); cfg->has_line_insertion = PROP_VALUE_ACCESS(prop_value, LINE_INSERTION, 0); end: kfree(prop_value); return rc; Loading
drivers/gpu/drm/msm/sde/sde_hw_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ enum { * @SDE_SSPP_BLOCK_SEC_UI Blocks secure-ui layers * @SDE_SSPP_QOS_FL_NOCALC Avoid fill level calculation for QoS/danger/safe * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support * @SDE_SSPP_LINE_INSERTION Line insertion support * @SDE_SSPP_MAX maximum value */ enum { Loading Loading @@ -199,6 +200,7 @@ enum { SDE_SSPP_BLOCK_SEC_UI, SDE_SSPP_QOS_FL_NOCALC, SDE_SSPP_SCALER_QSEED3LITE, SDE_SSPP_LINE_INSERTION, SDE_SSPP_MAX }; Loading Loading @@ -1109,6 +1111,7 @@ struct sde_mdss_cfg { bool delay_prg_fetch_start; bool has_qsync; bool has_3d_merge_reset; bool has_line_insertion; bool sui_misr_supported; u32 sui_block_xin_mask; Loading