Browse Source

disp: msm: sde: use pp dsc api only if hw supports

This change checks the capabilities of pingpong block to
check if it needs to call the pingpong api to enable or
disable the dsc. Certain hw versions do not have support
in pingpong block to enable/disable the dsc instead the
dsc block itself have the hooks to control the DSC.

Change-Id: I17dd45479cc33ff2e81f6a6e5a5a8704562dfd24
Signed-off-by: Abhijit Kulkarni <[email protected]>
Abhijit Kulkarni 6 years ago
parent
commit
d3d3f808d4

+ 10 - 3
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 */
 	/* Get PP for DSC configuration */
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
 	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])
 		if (!sde_enc->hw_dsc[i])
 			continue;
 			continue;
 
 
@@ -2169,8 +2171,13 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 		request_hw.type = SDE_HW_BLK_PINGPONG;
 		request_hw.type = SDE_HW_BLK_PINGPONG;
 		if (!sde_rm_request_hw_blk(&sde_kms->rm, &request_hw))
 		if (!sde_rm_request_hw_blk(&sde_kms->rm, &request_hw))
 			break;
 			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++) {
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {

+ 6 - 6
msm/sde/sde_encoder_dce.c

@@ -188,9 +188,9 @@ static void _dce_dsc_pipe_cfg(struct sde_hw_dsc *hw_dsc,
 		return;
 		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;
 		return;
 	}
 	}
 
 
@@ -200,13 +200,13 @@ static void _dce_dsc_pipe_cfg(struct sde_hw_dsc *hw_dsc,
 	if (hw_dsc->ops.dsc_config_thresh)
 	if (hw_dsc->ops.dsc_config_thresh)
 		hw_dsc->ops.dsc_config_thresh(hw_dsc, dsc);
 		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);
 		hw_dsc_pp->ops.setup_dsc(hw_dsc_pp);
 
 
 	if (hw_dsc->ops.bind_pingpong_blk)
 	if (hw_dsc->ops.bind_pingpong_blk)
 		hw_dsc->ops.bind_pingpong_blk(hw_dsc, true, hw_pp->idx);
 		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);
 		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[i] = sde_enc->hw_dsc[i];
 		hw_dsc_pp[i] = sde_enc->hw_dsc_pp[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_ERROR_DCE(sde_enc, "invalid params for DSC\n");
 			SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
 			SDE_EVT32(DRMID(&sde_enc->base), roi->w, roi->h,
 				dsc_common_mode, i, active);
 				dsc_common_mode, i, active);

+ 12 - 8
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)
 	if (rc)
 		goto end;
 		goto end;
 
 
+	major_version = SDE_HW_MAJOR(sde_cfg->hwversion);
 	for (i = 0; i < off_count; i++) {
 	for (i = 0; i < off_count; i++) {
 		pp = sde_cfg->pingpong + i;
 		pp = sde_cfg->pingpong + i;
 		sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
 		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",
 		snprintf(sblk->te.name, SDE_HW_BLK_NAME_LEN, "te_%u",
 				pp->id - PINGPONG_0);
 				pp->id - PINGPONG_0);
 
 
-		major_version = SDE_HW_MAJOR(sde_cfg->hwversion);
 		if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
 		if (major_version < SDE_HW_MAJOR(SDE_HW_VER_500))
 			set_bit(SDE_PINGPONG_TE, &pp->features);
 			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))
 		if (PROP_VALUE_ACCESS(prop_value, PP_SLAVE, i))
 			set_bit(SDE_PINGPONG_SLAVE, &pp->features);
 			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,
 		sblk->dither.base = PROP_VALUE_ACCESS(prop_value, DITHER_OFF,
-							i);
+				i);
 		if (sblk->dither.base) {
 		if (sblk->dither.base) {
 			sblk->dither.id = SDE_PINGPONG_DITHER;
 			sblk->dither.id = SDE_PINGPONG_DITHER;
 			snprintf(sblk->dither.name, SDE_HW_BLK_NAME_LEN,
 			snprintf(sblk->dither.name, SDE_HW_BLK_NAME_LEN,

+ 14 - 5
msm/sde/sde_hw_pingpong.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // 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 <linux/iopoll.h>
 #include <linux/iopoll.h>
@@ -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)
 	if (pp->merge_3d && pp->merge_3d->ops.reset_blend_mode)
 		pp->merge_3d->ops.reset_blend_mode(pp->merge_3d);
 		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,
 static void _setup_pingpong_ops(struct sde_hw_pingpong_ops *ops,
 	const struct sde_pingpong_cfg *hw_cap)
 	const struct sde_pingpong_cfg *hw_cap)
 {
 {
 	u32 version = 0;
 	u32 version = 0;
 
 
+	ops->get_hw_caps = sde_hw_pp_get_caps;
 	if (hw_cap->features & BIT(SDE_PINGPONG_TE)) {
 	if (hw_cap->features & BIT(SDE_PINGPONG_TE)) {
 		ops->setup_tearcheck = sde_hw_pp_setup_te_config;
 		ops->setup_tearcheck = sde_hw_pp_setup_te_config;
 		ops->enable_tearcheck = sde_hw_pp_enable_te;
 		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->poll_timeout_wr_ptr = sde_hw_pp_poll_timeout_wr_ptr;
 		ops->get_line_count = sde_hw_pp_get_line_count;
 		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);
 	version = SDE_COLOR_PROCESS_MAJOR(hw_cap->sblk->dither.version);
 	switch (version) {
 	switch (version) {

+ 6 - 0
msm/sde/sde_hw_pingpong.h

@@ -32,6 +32,7 @@ struct sde_hw_dsc_cfg {
  *  @disable_dsc : disables DSC encoder
  *  @disable_dsc : disables DSC encoder
  *  @setup_dither : function to program the dither hw block
  *  @setup_dither : function to program the dither hw block
  *  @get_line_count: obtain current vertical line counter
  *  @get_line_count: obtain current vertical line counter
+ *  @get_hw_caps: returns features supported by this pp block
  */
  */
 struct sde_hw_pingpong_ops {
 struct sde_hw_pingpong_ops {
 	/**
 	/**
@@ -126,6 +127,11 @@ struct sde_hw_pingpong_ops {
 	 * reset 3d blend configuration
 	 * reset 3d blend configuration
 	 */
 	 */
 	void (*reset_3d_mode)(struct sde_hw_pingpong *pp);
 	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 {
 struct sde_hw_merge_3d_ops {