Merge "drm/msm/sde: add support for PA VLUT version 1.8"
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
index 4191367..c8e732a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
@@ -12,6 +12,7 @@
 
 #include <drm/msm_drm_pp.h>
 #include "sde_hw_color_processing_v1_7.h"
+#include "sde_hw_ctl.h"
 
 #define PA_HUE_VIG_OFF		0x110
 #define PA_SAT_VIG_OFF		0x114
@@ -26,6 +27,9 @@
 #define PA_LUTV_DSPP_OFF	0x1400
 #define PA_LUT_SWAP_OFF		0x234
 
+#define PA_LUTV_DSPP_CTRL_OFF	0x4c
+#define PA_LUTV_DSPP_SWAP_OFF	0x18
+
 #define PA_HUE_MASK		0xFFF
 #define PA_SAT_MASK		0xFFFF
 #define PA_VAL_MASK		0xFF
@@ -458,6 +462,62 @@
 	SDE_REG_WRITE(&ctx->hw, base, op_mode);
 }
 
+void sde_setup_dspp_pa_vlut_v1_8(struct sde_hw_dspp *ctx, void *cfg)
+{
+	struct drm_msm_pa_vlut *payload = NULL;
+	struct sde_hw_cp_cfg *hw_cfg = cfg;
+	struct sde_hw_ctl *ctl = NULL;
+	u32 vlut_base, pa_hist_base;
+	u32 ctrl_off, swap_off;
+	u32 tmp = 0;
+	int i = 0, j = 0;
+	u32 flush_mask = 0;
+
+	if (!ctx) {
+		DRM_ERROR("invalid input parameter NULL ctx\n");
+		return;
+	}
+
+	if (!hw_cfg || (hw_cfg->payload && hw_cfg->len !=
+			sizeof(struct drm_msm_pa_vlut))) {
+		DRM_ERROR("hw %pK payload %pK payloadsize %d exp size %zd\n",
+			  hw_cfg, ((hw_cfg) ? hw_cfg->payload : NULL),
+			  ((hw_cfg) ? hw_cfg->len : 0),
+			  sizeof(struct drm_msm_pa_vlut));
+		return;
+	}
+
+	ctl = hw_cfg->ctl;
+	vlut_base = ctx->cap->sblk->vlut.base;
+	pa_hist_base = ctx->cap->sblk->hist.base;
+	ctrl_off = pa_hist_base + PA_LUTV_DSPP_CTRL_OFF;
+	swap_off = pa_hist_base + PA_LUTV_DSPP_SWAP_OFF;
+
+	if (!hw_cfg->payload) {
+		DRM_DEBUG_DRIVER("Disable vlut feature\n");
+		SDE_REG_WRITE(&ctx->hw, ctrl_off, 0);
+		goto exit;
+	}
+
+	payload = hw_cfg->payload;
+	DRM_DEBUG_DRIVER("Enable vlut feature flags %llx\n", payload->flags);
+	for (i = 0, j = 0; i < ARRAY_SIZE(payload->val); i += 2, j += 4) {
+		tmp = (payload->val[i] & REG_MASK(10)) |
+			((payload->val[i + 1] & REG_MASK(10)) << 16);
+		SDE_REG_WRITE(&ctx->hw, (vlut_base + j), tmp);
+	}
+	SDE_REG_WRITE(&ctx->hw, ctrl_off, 1);
+	SDE_REG_WRITE(&ctx->hw, swap_off, 1);
+
+exit:
+	/* update flush bit */
+	if (ctl && ctl->ops.get_bitmask_dspp_pavlut) {
+		ctl->ops.get_bitmask_dspp_pavlut(ctl, &flush_mask, ctx->idx);
+		if (ctl->ops.update_pending_flush)
+			ctl->ops.update_pending_flush(ctl, flush_mask);
+	}
+}
+
 void sde_setup_dspp_gc_v1_7(struct sde_hw_dspp *ctx, void *cfg)
 {
 	struct drm_msm_pgc_lut *payload = NULL;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.h b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.h
index 25e446b7..4cd2e5a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.h
@@ -76,6 +76,13 @@
 void sde_setup_dspp_pa_vlut_v1_7(struct sde_hw_dspp *ctx, void *cfg);
 
 /**
+ * sde_setup_dspp_pa_vlut_v1_8 - setup DSPP PA vLUT feature in v1.8 hardware
+ * @ctx: Pointer to DSPP context
+ * @cfg: Pointer to vLUT data
+ */
+void sde_setup_dspp_pa_vlut_v1_8(struct sde_hw_dspp *ctx, void *cfg);
+
+/**
  * sde_setup_dspp_gc_v1_7 - setup DSPP gc feature in v1.7 hardware
  * @ctx: Pointer to DSPP context
  * @cfg: Pointer to gc data
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
index 621a172..e027be7 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.c
@@ -235,6 +235,22 @@
 	return 0;
 }
 
+static inline int sde_hw_ctl_get_bitmask_dspp_pavlut(struct sde_hw_ctl *ctx,
+		u32 *flushbits, enum sde_dspp dspp)
+{
+	switch (dspp) {
+	case DSPP_0:
+		*flushbits |= BIT(3);
+		break;
+	case DSPP_1:
+		*flushbits |= BIT(4);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static inline int sde_hw_ctl_get_bitmask_intf(struct sde_hw_ctl *ctx,
 		u32 *flushbits, enum sde_intf intf)
 {
@@ -568,6 +584,7 @@
 	ops->get_bitmask_sspp = sde_hw_ctl_get_bitmask_sspp;
 	ops->get_bitmask_mixer = sde_hw_ctl_get_bitmask_mixer;
 	ops->get_bitmask_dspp = sde_hw_ctl_get_bitmask_dspp;
+	ops->get_bitmask_dspp_pavlut = sde_hw_ctl_get_bitmask_dspp_pavlut;
 	ops->get_bitmask_intf = sde_hw_ctl_get_bitmask_intf;
 	ops->get_bitmask_cdm = sde_hw_ctl_get_bitmask_cdm;
 	ops->get_bitmask_wb = sde_hw_ctl_get_bitmask_wb;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h
index 5d3ced3..97bc1c1 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ctl.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ctl.h
@@ -173,6 +173,10 @@
 		u32 *flushbits,
 		enum sde_dspp blk);
 
+	int (*get_bitmask_dspp_pavlut)(struct sde_hw_ctl *ctx,
+		u32 *flushbits,
+		enum sde_dspp blk);
+
 	int (*get_bitmask_intf)(struct sde_hw_ctl *ctx,
 		u32 *flushbits,
 		enum sde_intf blk);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
index 5b3f51e..d30c0ae 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
@@ -82,9 +82,12 @@
 			} else if (c->cap->sblk->vlut.version ==
 					(SDE_COLOR_PROCESS_VER(0x1, 0x8))) {
 				ret = reg_dmav1_init_dspp_op_v4(i, c->idx);
-				if (ret)
+				if (!ret)
 					c->ops.setup_vlut =
 					reg_dmav1_setup_dspp_vlutv18;
+				else
+					c->ops.setup_vlut =
+					sde_setup_dspp_pa_vlut_v1_8;
 			}
 			break;
 		case SDE_DSPP_GAMUT:
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index 55cb260..b59dd16 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -44,7 +44,7 @@
 static struct sde_reg_dma_buffer *dspp_buf[REG_DMA_FEATURES_MAX][DSPP_MAX];
 
 static u32 feature_map[SDE_DSPP_MAX] = {
-	[SDE_DSPP_VLUT] = VLUT,
+	[SDE_DSPP_VLUT] = REG_DMA_FEATURES_MAX,
 	[SDE_DSPP_GAMUT] = GAMUT,
 	[SDE_DSPP_IGC] = IGC,
 	[SDE_DSPP_PCC] = PCC,