diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 1e1559dc..78b2d5ce 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -2161,7 +2161,9 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, /* Get PP for DSC configuration */ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { - sde_enc->hw_dsc_pp[i] = NULL; + struct sde_hw_pingpong *pp = NULL; + unsigned long features = 0; + if (!sde_enc->hw_dsc[i]) continue; @@ -2169,8 +2171,13 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, request_hw.type = SDE_HW_BLK_PINGPONG; if (!sde_rm_request_hw_blk(&sde_kms->rm, &request_hw)) break; - sde_enc->hw_dsc_pp[i] = - (struct sde_hw_pingpong *) request_hw.hw; + pp = (struct sde_hw_pingpong *) request_hw.hw; + features = pp->ops.get_hw_caps(pp); + + if (test_bit(SDE_PINGPONG_DSC, &features)) + sde_enc->hw_dsc_pp[i] = pp; + else + sde_enc->hw_dsc_pp[i] = NULL; } for (i = 0; i < sde_enc->num_phys_encs; i++) { diff --git a/msm/sde/sde_encoder_dce.c b/msm/sde/sde_encoder_dce.c index 7ce71e34..9e481877 100644 --- a/msm/sde/sde_encoder_dce.c +++ b/msm/sde/sde_encoder_dce.c @@ -188,9 +188,9 @@ static void _dce_dsc_pipe_cfg(struct sde_hw_dsc *hw_dsc, return; } - if (!dsc || !hw_dsc || !hw_pp || !hw_dsc_pp) { - SDE_ERROR("invalid params %d %d %d %d\n", !dsc, !hw_dsc, - !hw_pp, !hw_dsc_pp); + if (!dsc || !hw_dsc || !hw_pp) { + SDE_ERROR("invalid params %d %d %d\n", !dsc, !hw_dsc, + !hw_pp); return; } @@ -200,13 +200,13 @@ static void _dce_dsc_pipe_cfg(struct sde_hw_dsc *hw_dsc, if (hw_dsc->ops.dsc_config_thresh) hw_dsc->ops.dsc_config_thresh(hw_dsc, dsc); - if (hw_dsc_pp->ops.setup_dsc) + if (hw_dsc_pp && hw_dsc_pp->ops.setup_dsc) hw_dsc_pp->ops.setup_dsc(hw_dsc_pp); if (hw_dsc->ops.bind_pingpong_blk) hw_dsc->ops.bind_pingpong_blk(hw_dsc, true, hw_pp->idx); - if (hw_dsc_pp->ops.enable_dsc) + if (hw_dsc_pp && hw_dsc_pp->ops.enable_dsc) hw_dsc_pp->ops.enable_dsc(hw_dsc_pp); } @@ -335,7 +335,7 @@ static int _dce_dsc_setup(struct sde_encoder_virt *sde_enc, hw_dsc[i] = sde_enc->hw_dsc[i]; hw_dsc_pp[i] = sde_enc->hw_dsc_pp[i]; - if (!hw_pp[i] || !hw_dsc[i] || !hw_dsc_pp[i]) { + if (!hw_pp[i] || !hw_dsc[i]) { SDE_ERROR_DCE(sde_enc, "invalid params for DSC\n"); SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h, dsc_common_mode, i, active); diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 93426953..60ba1ba2 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -3181,6 +3181,7 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (rc) goto end; + major_version = SDE_HW_MAJOR(sde_cfg->hwversion); for (i = 0; i < off_count; i++) { pp = sde_cfg->pingpong + i; sblk = kzalloc(sizeof(*sblk), GFP_KERNEL); @@ -3202,7 +3203,6 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) snprintf(sblk->te.name, SDE_HW_BLK_NAME_LEN, "te_%u", pp->id - PINGPONG_0); - major_version = SDE_HW_MAJOR(sde_cfg->hwversion); if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500)) set_bit(SDE_PINGPONG_TE, &pp->features); @@ -3218,16 +3218,20 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) if (PROP_VALUE_ACCESS(prop_value, PP_SLAVE, i)) set_bit(SDE_PINGPONG_SLAVE, &pp->features); - sblk->dsc.base = PROP_VALUE_ACCESS(prop_value, DSC_OFF, i); - if (sblk->dsc.base) { - sblk->dsc.id = SDE_PINGPONG_DSC; - snprintf(sblk->dsc.name, SDE_HW_BLK_NAME_LEN, "dsc_%u", - pp->id - PINGPONG_0); - set_bit(SDE_PINGPONG_DSC, &pp->features); + if (major_version < SDE_HW_MAJOR(SDE_HW_VER_700)) { + sblk->dsc.base = PROP_VALUE_ACCESS(prop_value, + DSC_OFF, i); + if (sblk->dsc.base) { + sblk->dsc.id = SDE_PINGPONG_DSC; + snprintf(sblk->dsc.name, SDE_HW_BLK_NAME_LEN, + "dsc_%u", + pp->id - PINGPONG_0); + set_bit(SDE_PINGPONG_DSC, &pp->features); + } } sblk->dither.base = PROP_VALUE_ACCESS(prop_value, DITHER_OFF, - i); + i); if (sblk->dither.base) { sblk->dither.id = SDE_PINGPONG_DITHER; snprintf(sblk->dither.name, SDE_HW_BLK_NAME_LEN, diff --git a/msm/sde/sde_hw_pingpong.c b/msm/sde/sde_hw_pingpong.c index e7f92eaf..d49a7895 100644 --- a/msm/sde/sde_hw_pingpong.c +++ b/msm/sde/sde_hw_pingpong.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -459,11 +459,18 @@ static void sde_hw_pp_reset_3d_merge_mode(struct sde_hw_pingpong *pp) if (pp->merge_3d && pp->merge_3d->ops.reset_blend_mode) pp->merge_3d->ops.reset_blend_mode(pp->merge_3d); } + +static unsigned long sde_hw_pp_get_caps(struct sde_hw_pingpong *pp) +{ + return !pp ? 0 : pp->caps->features; +} + static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops, const struct sde_pingpong_cfg *hw_cap) { u32 version = 0; + ops->get_hw_caps = sde_hw_pp_get_caps; if (hw_cap->features & BIT(SDE_PINGPONG_TE)) { ops->setup_tearcheck = sde_hw_pp_setup_te_config; ops->enable_tearcheck = sde_hw_pp_enable_te; @@ -475,10 +482,12 @@ static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops, ops->poll_timeout_wr_ptr = sde_hw_pp_poll_timeout_wr_ptr; ops->get_line_count = sde_hw_pp_get_line_count; } - ops->setup_dsc = sde_hw_pp_setup_dsc; - ops->enable_dsc = sde_hw_pp_dsc_enable; - ops->disable_dsc = sde_hw_pp_dsc_disable; - ops->get_dsc_status = sde_hw_pp_get_dsc_status; + if (hw_cap->features & BIT(SDE_PINGPONG_DSC)) { + ops->setup_dsc = sde_hw_pp_setup_dsc; + ops->enable_dsc = sde_hw_pp_dsc_enable; + ops->disable_dsc = sde_hw_pp_dsc_disable; + ops->get_dsc_status = sde_hw_pp_get_dsc_status; + } version = SDE_COLOR_PROCESS_MAJOR(hw_cap->sblk->dither.version); switch (version) { diff --git a/msm/sde/sde_hw_pingpong.h b/msm/sde/sde_hw_pingpong.h index 32866708..91760432 100644 --- a/msm/sde/sde_hw_pingpong.h +++ b/msm/sde/sde_hw_pingpong.h @@ -32,6 +32,7 @@ struct sde_hw_dsc_cfg { * @disable_dsc : disables DSC encoder * @setup_dither : function to program the dither hw block * @get_line_count: obtain current vertical line counter + * @get_hw_caps: returns features supported by this pp block */ struct sde_hw_pingpong_ops { /** @@ -126,6 +127,11 @@ struct sde_hw_pingpong_ops { * reset 3d blend configuration */ void (*reset_3d_mode)(struct sde_hw_pingpong *pp); + + /** + * get PP features supported by this instance + */ + unsigned long (*get_hw_caps)(struct sde_hw_pingpong *pp); }; struct sde_hw_merge_3d_ops {