Explorar o código

disp: msm: sde: add DE LPF blend support

This change adds Detail Enhancer LPF blend support from MDSS 9.0.
Support is added for qseed block in both SSPP and Destination Scaler.

Change-Id: Ic8e3732059498a156f51fb93c5fd6638bd731c57
Signed-off-by: Narendra Muppalla <[email protected]>
Narendra Muppalla %!s(int64=3) %!d(string=hai) anos
pai
achega
43d8d04e73

+ 13 - 0
include/uapi/display/drm/sde_drm.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -261,6 +262,9 @@ struct sde_drm_de_v1 {
 /* Disable dynamic expansion */
 #define SDE_DYN_EXP_DISABLE 0x1
 
+#define SDE_DE_LPF_BLEND_FILT
+#define SDE_DE_LPF_BLEND_FLAG_EN (1 << 0)
+
 #define SDE_DRM_QSEED3LITE
 #define SDE_DRM_QSEED4
 #define SDE_DRM_INLINE_PREDOWNSCALE
@@ -301,6 +305,10 @@ struct sde_drm_de_v1 {
  * @pre_downscale_x_1  Pre-downscale ratio, x-direction, plane 1(UV)
  * @pre_downscale_y_0  Pre-downscale ratio, y-direction, plane 0(Y/RGB)
  * @pre_downscale_y_1  Pre-downscale ratio, y-direction, plane 1(UV)
+ * @de_lpf_flags:      Detail enhancer lpf blned configuration flags
+ * @de_lpf_h:          Detail enhancer lpf blend high
+ * @de_lpf_l:          Detail enhancer lpf blend low
+ * @de_lpf_m:          Detail enhancer lpf blend medium
  */
 struct sde_drm_scaler_v2 {
 	/*
@@ -366,6 +374,11 @@ struct sde_drm_scaler_v2 {
 	__u32 pre_downscale_x_1;
 	__u32 pre_downscale_y_0;
 	__u32 pre_downscale_y_1;
+
+	__u32 de_lpf_flags;
+	__u32 de_lpf_h;
+	__u32 de_lpf_l;
+	__u32 de_lpf_m;
 };
 
 /* Number of dest scalers supported */

+ 1 - 1
msm/sde/sde_crtc.c

@@ -2442,7 +2442,7 @@ static void _sde_crtc_dest_scaler_setup(struct drm_crtc *crtc)
 			if (cfg->flags & SDE_DRM_DESTSCALER_ENABLE)
 				op_mode |= BIT(hw_ds->idx - DS_0);
 
-			if ((i == count-1) && hw_ds->ops.setup_opmode) {
+			if (hw_ds->ops.setup_opmode) {
 				op_mode |= (cstate->num_ds_enabled ==
 					CRTC_DUAL_MIXERS_ONLY) ?
 					SDE_DS_OP_MODE_DUAL : 0;

+ 7 - 0
msm/sde/sde_hw_catalog.c

@@ -1875,6 +1875,9 @@ static void sde_sspp_set_features(struct sde_mdss_cfg *sde_cfg,
 
 		if (test_bit(SDE_FEATURE_UBWC_STATS, sde_cfg->features))
 			set_bit(SDE_SSPP_UBWC_STATS, &sspp->features);
+
+		if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_900))
+			set_bit(SDE_SSPP_SCALER_DE_LPF_BLEND, &sspp->features);
 	}
 }
 
@@ -3087,6 +3090,10 @@ static int sde_ds_parse_dt(struct device_node *np,
 		else if (sde_cfg->qseed_sw_lib_rev ==
 				SDE_SSPP_SCALER_QSEED3LITE)
 			set_bit(SDE_SSPP_SCALER_QSEED3LITE, &ds->features);
+		if (SDE_HW_MAJOR(sde_cfg->hw_rev) >= SDE_HW_MAJOR(SDE_HW_VER_900)) {
+			set_bit(SDE_DS_DE_LPF_BLEND, &ds->features);
+			set_bit(SDE_DS_MERGE_CTRL, &ds->features);
+		}
 	}
 
 end:

+ 14 - 0
msm/sde/sde_hw_catalog.h

@@ -293,6 +293,7 @@ enum {
  * @SDE_SSPP_FP16_CSC        FP16 CSC color processing block support
  * @SDE_SSPP_FP16_UNMULT     FP16 alpha unmult color processing block support
  * @SDE_SSPP_UBWC_STATS:     Support for ubwc stats
+ * @SDE_SSPP_SCALER_DE_LPF_BLEND:     Support for detail enhancer
  * @SDE_SSPP_MAX             maximum value
  */
 enum {
@@ -328,6 +329,7 @@ enum {
 	SDE_SSPP_FP16_CSC,
 	SDE_SSPP_FP16_UNMULT,
 	SDE_SSPP_UBWC_STATS,
+	SDE_SSPP_SCALER_DE_LPF_BLEND,
 	SDE_SSPP_MAX
 };
 
@@ -381,6 +383,18 @@ enum {
 	SDE_MIXER_MAX
 };
 
+/**
+ * Destination scalar features
+ * @SDE_DS_DE_LPF_BLEND       DE_LPF blend supports for destination scalar block
+ * @SDE_DS_MERGE_CTRL  	      mode operation support for destination scalar block
+ * @SDE_DS_DE_LPF_MAX         maximum value
+ */
+enum {
+	SDE_DS_DE_LPF_BLEND = 0x1,
+	SDE_DS_MERGE_CTRL,
+	SDE_DS_DE_LPF_MAX
+};
+
 /**
  * DSPP sub-blocks
  * @SDE_DSPP_IGC             DSPP Inverse gamma correction block

+ 27 - 4
msm/sde/sde_hw_ds.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -11,21 +12,36 @@
 /* Destination scaler TOP registers */
 #define DEST_SCALER_OP_MODE     0x00
 #define DEST_SCALER_HW_VERSION  0x10
+#define DEST_SCALER_MERGE_CTRL  0x0C
 
-static void sde_hw_ds_setup_opmode(struct sde_hw_ds *hw_ds,
-				u32 op_mode)
+#define DEST_SCALER_DUAL_PIPE   1
+#define DEST_SCALER_QUAD_PIPE   3
+
+static void sde_hw_ds_setup_opmode(struct sde_hw_ds *hw_ds, u32 op_mode)
 {
 	struct sde_hw_blk_reg_map *hw = &hw_ds->hw;
 
 	SDE_REG_WRITE(hw, DEST_SCALER_OP_MODE, op_mode);
 }
 
+static void sde_hw_ds_setup_opmode_v1(struct sde_hw_ds *hw_ds, u32 op_mode)
+{
+	struct sde_hw_blk_reg_map *hw = &hw_ds->hw;
+
+	if (op_mode & SDE_DS_OP_MODE_DUAL) {
+		op_mode = DEST_SCALER_DUAL_PIPE;
+		SDE_REG_WRITE(hw, DEST_SCALER_MERGE_CTRL + hw_ds->scl->base, op_mode);
+	}
+}
+
 static void sde_hw_ds_setup_scaler3(struct sde_hw_ds *hw_ds,
 			void *scaler_cfg, void *scaler_lut_cfg)
 {
 	struct sde_hw_scaler3_cfg *scl3_cfg = scaler_cfg;
 	struct sde_hw_scaler3_lut_cfg *scl3_lut_cfg = scaler_lut_cfg;
 
+	bool de_lpf_en = false;
+
 	if (!hw_ds || !hw_ds->scl || !scl3_cfg || !scl3_lut_cfg)
 		return;
 
@@ -41,14 +57,21 @@ static void sde_hw_ds_setup_scaler3(struct sde_hw_ds *hw_ds,
 		scl3_cfg->sep_len = scl3_lut_cfg->sep_len;
 	}
 
+
+	if (test_bit(SDE_DS_DE_LPF_BLEND, &hw_ds->scl->features))
+		de_lpf_en = true;
 	sde_hw_setup_scaler3(&hw_ds->hw, scl3_cfg, hw_ds->scl->version,
 			 hw_ds->scl->base,
-			 sde_get_sde_format(DRM_FORMAT_XBGR2101010));
+			 sde_get_sde_format(DRM_FORMAT_XBGR2101010), de_lpf_en);
 }
 
 static void _setup_ds_ops(struct sde_hw_ds_ops *ops, unsigned long features)
 {
-	ops->setup_opmode = sde_hw_ds_setup_opmode;
+
+	if (test_bit(SDE_DS_MERGE_CTRL, &features))
+		ops->setup_opmode = sde_hw_ds_setup_opmode_v1;
+	else
+		ops->setup_opmode = sde_hw_ds_setup_opmode;
 
 	if (test_bit(SDE_SSPP_SCALER_QSEED3, &features) ||
 			test_bit(SDE_SSPP_SCALER_QSEED3LITE, &features))

+ 5 - 1
msm/sde/sde_hw_sspp.c

@@ -760,6 +760,7 @@ static void _sde_hw_sspp_setup_scaler3(struct sde_hw_pipe *ctx,
 		void *scaler_cfg)
 {
 	u32 idx;
+	bool de_lpf_en = false;
 	struct sde_hw_scaler3_cfg *scaler3_cfg = scaler_cfg;
 
 	(void)pe;
@@ -767,8 +768,11 @@ static void _sde_hw_sspp_setup_scaler3(struct sde_hw_pipe *ctx,
 		|| !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk)
 		return;
 
+	if (test_bit(SDE_SSPP_SCALER_DE_LPF_BLEND, &ctx->cap->features))
+		de_lpf_en = true;
+
 	sde_hw_setup_scaler3(&ctx->hw, scaler3_cfg,
-		ctx->cap->sblk->scaler_blk.version, idx, sspp->layout.format);
+		ctx->cap->sblk->scaler_blk.version, idx, sspp->layout.format, de_lpf_en);
 }
 
 static void sde_hw_sspp_setup_pre_downscale(struct sde_hw_pipe *ctx,

+ 14 - 1
msm/sde/sde_hw_util.c

@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -30,6 +31,7 @@ static u32 sde_hw_util_log_mask = SDE_DBG_MASK_NONE;
 #define QSEED3_DE_ADJUST_DATA_0            0x34
 #define QSEED3_DE_ADJUST_DATA_1            0x38
 #define QSEED3_DE_ADJUST_DATA_2            0x3C
+#define QSEED3_DE_LPF_BLEND                0x64
 #define QSEED3_SRC_SIZE_Y_RGB_A            0x40
 #define QSEED3_SRC_SIZE_UV                 0x44
 #define QSEED3_DST_SIZE                    0x48
@@ -152,6 +154,9 @@ void sde_set_scaler_v2(struct sde_hw_scaler3_cfg *cfg,
 	cfg->de.thr_low = scale_v2->de.thr_low;
 	cfg->de.thr_high = scale_v2->de.thr_high;
 	cfg->de.blend = scale_v2->de_blend;
+	cfg->de_lpf_h = scale_v2->de_lpf_h;
+	cfg->de_lpf_l = scale_v2->de_lpf_l;
+	cfg->de_lpf_m = scale_v2->de_lpf_m;
 
 	for (i = 0; i < SDE_MAX_DE_CURVES; i++) {
 		cfg->de.adjust_a[i] = scale_v2->de.adjust_a[i];
@@ -348,11 +353,12 @@ static inline scaler_lut_type get_scaler_lut(
 
 void sde_hw_setup_scaler3(struct sde_hw_blk_reg_map *c,
 		struct sde_hw_scaler3_cfg *scaler3_cfg, u32 scaler_version,
-		u32 scaler_offset, const struct sde_format *format)
+		u32 scaler_offset, const struct sde_format *format, bool de_lpf)
 {
 	u32 op_mode = 0;
 	u32 phase_init, preload, src_y_rgb, src_uv, dst;
 	scaler_lut_type setup_lut = NULL;
+	u32 de_lpf_blend = 0;
 
 	if (!scaler3_cfg->enable)
 		goto end;
@@ -431,6 +437,13 @@ void sde_hw_setup_scaler3(struct sde_hw_blk_reg_map *c,
 
 	SDE_REG_WRITE(c, QSEED3_DST_SIZE + scaler_offset, dst);
 
+	if (de_lpf && (scaler3_cfg->de_lpf_flags & SDE_DYN_EXP_DISABLE)) {
+		de_lpf_blend = (scaler3_cfg->de_lpf_h & 0x3FF) |
+			((scaler3_cfg->de_lpf_l & 0x3FF) << 10) |
+			((scaler3_cfg->de_lpf_m & 0x3FF) << 20);
+		SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND, de_lpf_blend);
+	}
+
 end:
 	if (format && !SDE_FORMAT_IS_DX(format))
 		op_mode |= BIT(14);

+ 11 - 1
msm/sde/sde_hw_util.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -109,6 +110,10 @@ struct sde_hw_scaler3_de_cfg {
  * @ de: detail enhancer configuration
  * @ dir_weight:   Directional Weight
  * @dyn_exp_disabled:     Dynamic expansion disabled
+ * @de_lpf_flags:      Detail enhancer lpf blned configuration flags
+ * @de_lpf_h:          Detail enhancer lpf blend high
+ * @de_lpf_l:          Detail enhancer lpf blend low
+ * @de_lpf_m:          Detail enhancer lpf blend medium
  */
 struct sde_hw_scaler3_cfg {
 	u32 enable;
@@ -151,6 +156,11 @@ struct sde_hw_scaler3_cfg {
 	struct sde_hw_scaler3_de_cfg de;
 	uint32_t dir_weight;
 	uint32_t dyn_exp_disabled;
+
+	__u32 de_lpf_flags;
+	__u32 de_lpf_h;
+	__u32 de_lpf_l;
+	__u32 de_lpf_m;
 };
 
 struct sde_hw_scaler3_lut_cfg {
@@ -197,7 +207,7 @@ void sde_set_scaler_v2(struct sde_hw_scaler3_cfg *cfg,
 
 void sde_hw_setup_scaler3(struct sde_hw_blk_reg_map *c,
 		struct sde_hw_scaler3_cfg *scaler3_cfg, u32 scaler_version,
-		u32 scaler_offset, const struct sde_format *format);
+		u32 scaler_offset, const struct sde_format *format, bool de_lpf);
 
 void sde_hw_csc_matrix_coeff_setup(struct sde_hw_blk_reg_map *c,
 		u32 csc_reg_off, struct sde_csc_cfg *data,