diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 0748aca9ea..3694fd54f3 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -147,6 +147,7 @@ enum msm_mdp_crtc_property { CRTC_PROP_DEST_SCALER_LUT_ED, CRTC_PROP_DEST_SCALER_LUT_CIR, CRTC_PROP_DEST_SCALER_LUT_SEP, + CRTC_PROP_DSPP_INFO, /* # of blob properties */ CRTC_PROP_BLOBCOUNT, diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 8f9ebb993b..9c29ac5d99 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -211,6 +211,35 @@ static bool feature_handoff_mask[SDE_CP_CRTC_MAX_FEATURES] = { [SDE_CP_CRTC_DSPP_DITHER] = 1, }; +typedef void (*dspp_cap_update_func_t)(struct sde_crtc *crtc, + struct sde_kms_info *info); +enum sde_dspp_caps_features { + SDE_CP_DSPP_CAPS, + SDE_CP_RC_CAPS, + SDE_CP_DEMRUA_CAPS, + SDE_CP_SPR_CAPS, + SDE_CP_LTM_CAPS, + SDE_CP_CAPS_MAX, +}; + +static void dspp_idx_caps_update(struct sde_crtc *crtc, + struct sde_kms_info *info); +static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info); +static void demura_caps_update(struct sde_crtc *crtc, + struct sde_kms_info *info); +static void spr_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info); +static void ltm_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info); +static dspp_cap_update_func_t dspp_cap_update_func[SDE_CP_CAPS_MAX]; + +#define setup_dspp_caps_funcs(func) \ +do { \ + func[SDE_CP_DSPP_CAPS] = dspp_idx_caps_update; \ + func[SDE_CP_RC_CAPS] = rc_caps_update; \ + func[SDE_CP_DEMRUA_CAPS] = demura_caps_update; \ + func[SDE_CP_SPR_CAPS] = spr_caps_update; \ + func[SDE_CP_LTM_CAPS] = ltm_caps_update; \ +} while (0) + static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc); typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp, @@ -1204,6 +1233,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc) if (IS_ERR(sde_crtc->hist_blob)) sde_crtc->hist_blob = NULL; + msm_property_install_blob(&sde_crtc->property_info, + "dspp_caps", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_DSPP_INFO); + mutex_init(&sde_crtc->crtc_cp_lock); INIT_LIST_HEAD(&sde_crtc->active_list); INIT_LIST_HEAD(&sde_crtc->dirty_list); @@ -1214,6 +1246,7 @@ void sde_cp_crtc_init(struct drm_crtc *crtc) spin_lock_init(&sde_crtc->ltm_lock); INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); + sde_cp_crtc_disable(crtc); } static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc, @@ -2070,6 +2103,7 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc) set_crtc_pu_feature_wrappers); setup_check_crtc_pu_feature_wrappers( check_crtc_pu_feature_wrappers); + setup_dspp_caps_funcs(dspp_cap_update_func); } if (!priv->cp_property) goto exit; @@ -4242,3 +4276,154 @@ void sde_cp_crtc_vm_primary_handoff(struct drm_crtc *crtc) mutex_unlock(&sde_crtc->crtc_cp_lock); } + +static void dspp_idx_caps_update(struct sde_crtc *crtc, + struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->dspp_count || num_mixers > catalog->dspp_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp) + continue; + snprintf(blk_name, sizeof(blk_name), "dspp%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->rc_count || num_mixers > catalog->rc_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp || (dspp->idx - DSPP_0) >= catalog->rc_count) + continue; + snprintf(blk_name, sizeof(blk_name), "rc%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +static void demura_caps_update(struct sde_crtc *crtc, + struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->demura_count || num_mixers > catalog->demura_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp || (dspp->idx - DSPP_0) >= catalog->demura_count) + continue; + snprintf(blk_name, sizeof(blk_name), "demura%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +static void spr_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->spr_count || num_mixers > catalog->spr_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp || (dspp->idx - DSPP_0) >= catalog->spr_count) + continue; + snprintf(blk_name, sizeof(blk_name), "spr%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +static void ltm_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->ltm_count || num_mixers > catalog->ltm_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp || (dspp->idx - DSPP_0) >= catalog->ltm_count) + continue; + snprintf(blk_name, sizeof(blk_name), "ltm%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +void sde_cp_crtc_enable(struct drm_crtc *drm_crtc) +{ + struct sde_crtc *crtc; + struct sde_kms_info *info = NULL; + u32 i, num_mixers; + + if (!drm_crtc) { + DRM_ERROR("invalid crtc handle"); + return; + } + crtc = to_sde_crtc(drm_crtc); + num_mixers = crtc->num_mixers; + if (!num_mixers) + return; + mutex_lock(&crtc->crtc_cp_lock); + info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL); + if (info) { + for (i = 0; i < ARRAY_SIZE(dspp_cap_update_func); i++) + dspp_cap_update_func[i](crtc, info); + msm_property_set_blob(&crtc->property_info, + &crtc->dspp_blob_info, + info->data, SDE_KMS_INFO_DATALEN(info), + CRTC_PROP_DSPP_INFO); + } + kfree(info); + mutex_unlock(&crtc->crtc_cp_lock); +} + +void sde_cp_crtc_disable(struct drm_crtc *drm_crtc) +{ + struct sde_kms_info *info = NULL; + struct sde_crtc *crtc; + + if (!drm_crtc) { + DRM_ERROR("invalid crtc handle"); + return; + } + crtc = to_sde_crtc(drm_crtc); + mutex_lock(&crtc->crtc_cp_lock); + info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL); + if (info) + msm_property_set_blob(&crtc->property_info, + &crtc->dspp_blob_info, + info->data, SDE_KMS_INFO_DATALEN(info), + CRTC_PROP_DSPP_INFO); + mutex_unlock(&crtc->crtc_cp_lock); + kfree(info); +} diff --git a/msm/sde/sde_color_processing.h b/msm/sde/sde_color_processing.h index e8542bcb8b..3742ef69e1 100644 --- a/msm/sde/sde_color_processing.h +++ b/msm/sde/sde_color_processing.h @@ -213,4 +213,17 @@ void sde_cp_crtc_res_change(struct drm_crtc *crtc_drm); */ void sde_cp_crtc_vm_primary_handoff(struct drm_crtc *crtc); +/** + * sde_cp_crtc_enable(): enable color processing info in the crtc. + * Should be called during crtc enable. + * @crtc: Pointer to drm_crtc. + */ +void sde_cp_crtc_enable(struct drm_crtc *crtc); + +/** + * sde_cp_crtc_disable(): disable color processing info in the crtc. + * Should be called during crtc disable. + * @crtc: Pointer to drm_crtc. + */ +void sde_cp_crtc_disable(struct drm_crtc *crtc); #endif /*_SDE_COLOR_PROCESSING_H */ diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index d562e46c5f..d0c0e93f4b 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -4193,6 +4193,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc) } _sde_crtc_reset(crtc); + sde_cp_crtc_disable(crtc); mutex_unlock(&sde_crtc->crtc_lock); } @@ -4267,7 +4268,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc, } sde_crtc->enabled = true; - + sde_cp_crtc_enable(crtc); /* update color processing on resume */ event.type = DRM_EVENT_CRTC_POWER; event.length = sizeof(u32); diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 525490ad22..2b2cf24d51 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -288,6 +288,7 @@ struct sde_crtc_misr_info { * @target_bpp : target bpp used to calculate compression ratio * @static_cache_read_work: delayed worker to transition cache state to read * @cache_state : Current static image cache state + * @dspp_blob_info : blob containing dspp hw capability information */ struct sde_crtc { struct drm_crtc base; @@ -374,6 +375,8 @@ struct sde_crtc { struct kthread_delayed_work static_cache_read_work; enum sde_crtc_cache_state cache_state; + + struct drm_property_blob *dspp_blob_info; }; enum sde_crtc_dirty_flags {