disp: msm: sde: add support for ppb size programming

MDSS 10.0 onwards, hw supports programming of pingpong
latency buffer size based on the resolution of display.
In prior targets full size of the latency buffer is used.
This change adds required support in sde driver to program
the pingpong buffer size based on systems recommended
latency lines requirement and the display resolution.

Change-Id: I172b19e5b397eb86190de57fed36f24cd67d2207
Signed-off-by: Prabhanjan Kandula <quic_pkandula@quicinc.com>
This commit is contained in:
Prabhanjan Kandula
2022-12-29 12:41:28 -08:00
parent f6284fb3fa
commit a2f3cba8ca
10 changed files with 223 additions and 6 deletions

View File

@@ -1431,6 +1431,85 @@ static int _sde_encoder_update_roi(struct drm_encoder *drm_enc)
return 0;
}
static void _sde_encoder_update_ppb_size(struct drm_encoder *drm_enc)
{
struct sde_kms *sde_kms;
struct sde_hw_mdp *hw_mdp;
struct drm_display_mode *mode;
struct sde_encoder_virt *sde_enc;
u32 maxw, pixels_per_pp, num_lm_or_pp, latency_lines;
int i;
if (!drm_enc) {
SDE_ERROR("invalid encoder parameter\n");
return;
}
sde_enc = to_sde_encoder_virt(drm_enc);
if (!sde_enc->cur_master || !sde_enc->cur_master->connector) {
SDE_ERROR_ENC(sde_enc, "invalid master or conn\n");
return;
}
/* program only for realtime displays */
if (sde_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_VIRTUAL)
return;
sde_kms = sde_encoder_get_kms(&sde_enc->base);
if (!sde_kms) {
SDE_ERROR_ENC(sde_enc, "invalid sde_kms\n");
return;
}
/* check if hw support is available, early return if not available */
if (sde_kms->catalog->ppb_sz_program == SDE_PPB_SIZE_THRU_NONE)
return;
hw_mdp = sde_kms->hw_mdp;
if (!hw_mdp) {
SDE_ERROR_ENC(sde_enc, "invalid mdp top\n");
return;
}
mode = &drm_enc->crtc->state->adjusted_mode;
num_lm_or_pp = sde_enc->cur_channel_cnt;
latency_lines = sde_kms->catalog->ppb_buf_max_lines;
for (i = 0; i < num_lm_or_pp; i++) {
struct sde_hw_pingpong *hw_pp = sde_enc->hw_pp[i];
if (!hw_pp) {
SDE_ERROR_ENC(sde_enc, "invalid hw_pp i:%d pp_cnt:%d\n", i, num_lm_or_pp);
return;
}
if (hw_pp->ops.set_ppb_fifo_size) {
pixels_per_pp = mult_frac(mode->hdisplay, latency_lines, num_lm_or_pp);
hw_pp->ops.set_ppb_fifo_size(hw_pp, pixels_per_pp);
SDE_EVT32(DRMID(drm_enc), i, hw_pp->idx, mode->hdisplay, pixels_per_pp,
sde_kms->catalog->ppb_sz_program, SDE_EVTLOG_FUNC_CASE1);
SDE_DEBUG_ENC(sde_enc, "hw-pp i:%d pp_cnt:%d pixels_per_pp:%d\n",
i, num_lm_or_pp, pixels_per_pp);
} else if (hw_mdp->ops.set_ppb_fifo_size) {
maxw = sde_conn_get_max_mode_width(sde_enc->cur_master->connector);
if (!maxw) {
SDE_ERROR_ENC(sde_enc, "failed to get max horizantal resolution\n");
return;
}
pixels_per_pp = mult_frac(maxw, latency_lines, num_lm_or_pp);
hw_mdp->ops.set_ppb_fifo_size(hw_mdp, hw_pp->idx, pixels_per_pp);
SDE_EVT32(DRMID(drm_enc), i, hw_pp->idx, maxw, pixels_per_pp,
sde_kms->catalog->ppb_sz_program, SDE_EVTLOG_FUNC_CASE2);
SDE_DEBUG_ENC(sde_enc, "hw-pp i:%d pp_cnt:%d pixels_per_pp:%d\n",
i, num_lm_or_pp, pixels_per_pp);
} else {
SDE_ERROR_ENC(sde_enc, "invalid - ppb fifo size support is partial\n");
}
}
}
void sde_encoder_helper_vsync_config(struct sde_encoder_phys *phys_enc, u32 vsync_source)
{
struct sde_vsync_source_cfg vsync_cfg = { 0 };
@@ -2549,12 +2628,14 @@ static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc)
struct sde_rm_hw_request request_hw;
int i, j;
sde_enc->cur_channel_cnt = 0;
sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
sde_enc->hw_pp[i] = NULL;
if (!sde_rm_get_hw(&sde_kms->rm, &pp_iter))
break;
sde_enc->hw_pp[i] = to_sde_hw_pingpong(pp_iter.hw);
sde_enc->cur_channel_cnt++;
}
for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -3000,6 +3081,9 @@ static void _sde_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
_sde_encoder_update_vsync_source(sde_enc, &sde_enc->disp_info);
if (!sde_encoder_in_cont_splash(drm_enc))
_sde_encoder_update_ppb_size(drm_enc);
memset(&sde_enc->prv_conn_roi, 0, sizeof(sde_enc->prv_conn_roi));
memset(&sde_enc->cur_conn_roi, 0, sizeof(sde_enc->cur_conn_roi));
_sde_encoder_control_fal10_veto(drm_enc, true);