Browse Source

drm: msm: add dspp caps blob to crtc

All sde crtc's are virtual when they are created. Resources for the crtc
is allocated when crtc is enabled. All crtc's will not have same
capabilities because some of the dspp blocks have additional hardware
blocks. Change exposes additional dspp capabilities dynamically when
crtc is allocated the dspp hardware block.

Change-Id: I93e76a1335574e4ca30d9419ef6cc6e8149e2c3c
Signed-off-by: Gopikrishnaiah Anandan <[email protected]>
Gopikrishnaiah Anandan 5 years ago
parent
commit
10e00393d8
5 changed files with 204 additions and 1 deletions
  1. 1 0
      msm/msm_drv.h
  2. 185 0
      msm/sde/sde_color_processing.c
  3. 13 0
      msm/sde/sde_color_processing.h
  4. 2 1
      msm/sde/sde_crtc.c
  5. 3 0
      msm/sde/sde_crtc.h

+ 1 - 0
msm/msm_drv.h

@@ -147,6 +147,7 @@ enum msm_mdp_crtc_property {
 	CRTC_PROP_DEST_SCALER_LUT_ED,
 	CRTC_PROP_DEST_SCALER_LUT_ED,
 	CRTC_PROP_DEST_SCALER_LUT_CIR,
 	CRTC_PROP_DEST_SCALER_LUT_CIR,
 	CRTC_PROP_DEST_SCALER_LUT_SEP,
 	CRTC_PROP_DEST_SCALER_LUT_SEP,
+	CRTC_PROP_DSPP_INFO,
 
 
 	/* # of blob properties */
 	/* # of blob properties */
 	CRTC_PROP_BLOBCOUNT,
 	CRTC_PROP_BLOBCOUNT,

+ 185 - 0
msm/sde/sde_color_processing.c

@@ -210,6 +210,35 @@ static bool feature_handoff_mask[SDE_CP_CRTC_MAX_FEATURES] = {
 	[SDE_CP_CRTC_DSPP_DITHER] = 1,
 	[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);
 static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc);
 
 
 typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp,
 typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp,
@@ -1203,6 +1232,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
 	if (IS_ERR(sde_crtc->hist_blob))
 	if (IS_ERR(sde_crtc->hist_blob))
 		sde_crtc->hist_blob = NULL;
 		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);
 	mutex_init(&sde_crtc->crtc_cp_lock);
 	INIT_LIST_HEAD(&sde_crtc->active_list);
 	INIT_LIST_HEAD(&sde_crtc->active_list);
 	INIT_LIST_HEAD(&sde_crtc->dirty_list);
 	INIT_LIST_HEAD(&sde_crtc->dirty_list);
@@ -1213,6 +1245,7 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
 	spin_lock_init(&sde_crtc->ltm_lock);
 	spin_lock_init(&sde_crtc->ltm_lock);
 	INIT_LIST_HEAD(&sde_crtc->ltm_buf_free);
 	INIT_LIST_HEAD(&sde_crtc->ltm_buf_free);
 	INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy);
 	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,
 static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc,
@@ -2068,6 +2101,7 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc)
 				set_crtc_pu_feature_wrappers);
 				set_crtc_pu_feature_wrappers);
 		setup_check_crtc_pu_feature_wrappers(
 		setup_check_crtc_pu_feature_wrappers(
 				check_crtc_pu_feature_wrappers);
 				check_crtc_pu_feature_wrappers);
+		setup_dspp_caps_funcs(dspp_cap_update_func);
 	}
 	}
 	if (!priv->cp_property)
 	if (!priv->cp_property)
 		goto exit;
 		goto exit;
@@ -4219,3 +4253,154 @@ void sde_cp_crtc_vm_primary_handoff(struct drm_crtc *crtc)
 
 
 	mutex_unlock(&sde_crtc->crtc_cp_lock);
 	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);
+}

+ 13 - 0
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);
 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 */
 #endif /*_SDE_COLOR_PROCESSING_H */

+ 2 - 1
msm/sde/sde_crtc.c

@@ -4201,6 +4201,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
 	}
 	}
 
 
 	_sde_crtc_reset(crtc);
 	_sde_crtc_reset(crtc);
+	sde_cp_crtc_disable(crtc);
 
 
 	mutex_unlock(&sde_crtc->crtc_lock);
 	mutex_unlock(&sde_crtc->crtc_lock);
 }
 }
@@ -4275,7 +4276,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
 	}
 	}
 
 
 	sde_crtc->enabled = true;
 	sde_crtc->enabled = true;
-
+	sde_cp_crtc_enable(crtc);
 	/* update color processing on resume */
 	/* update color processing on resume */
 	event.type = DRM_EVENT_CRTC_POWER;
 	event.type = DRM_EVENT_CRTC_POWER;
 	event.length = sizeof(u32);
 	event.length = sizeof(u32);

+ 3 - 0
msm/sde/sde_crtc.h

@@ -288,6 +288,7 @@ struct sde_crtc_misr_info {
  * @target_bpp      : target bpp used to calculate compression ratio
  * @target_bpp      : target bpp used to calculate compression ratio
  * @static_cache_read_work: delayed worker to transition cache state to read
  * @static_cache_read_work: delayed worker to transition cache state to read
  * @cache_state     : Current static image cache state
  * @cache_state     : Current static image cache state
+ * @dspp_blob_info  : blob containing dspp hw capability information
  */
  */
 struct sde_crtc {
 struct sde_crtc {
 	struct drm_crtc base;
 	struct drm_crtc base;
@@ -374,6 +375,8 @@ struct sde_crtc {
 
 
 	struct kthread_delayed_work static_cache_read_work;
 	struct kthread_delayed_work static_cache_read_work;
 	enum sde_crtc_cache_state cache_state;
 	enum sde_crtc_cache_state cache_state;
+
+	struct drm_property_blob *dspp_blob_info;
 };
 };
 
 
 enum sde_crtc_dirty_flags {
 enum sde_crtc_dirty_flags {