drm/msm/sde: Add support for Memory Color in plane
Add support for skin, sky, and foliage memory color hardware in
planes which have color processing hardwares.
Change-Id: I9ec72f44f36939cae90215bc668f3186d140e8b8
Signed-off-by: Benet Clark <benetc@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index d08e65d..f35b8cf 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -84,6 +84,9 @@
PLANE_PROP_SCALER_LUT_ED,
PLANE_PROP_SCALER_LUT_CIR,
PLANE_PROP_SCALER_LUT_SEP,
+ PLANE_PROP_SKIN_COLOR,
+ PLANE_PROP_SKY_COLOR,
+ PLANE_PROP_FOLIAGE_COLOR,
/* # of blob properties */
PLANE_PROP_BLOBCOUNT,
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.h b/drivers/gpu/drm/msm/sde/sde_color_processing.h
index dbe52a2..9fa63f8 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.h
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.h
@@ -1,4 +1,3 @@
-
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -16,6 +15,18 @@
#define _SDE_COLOR_PROCESSING_H
#include <drm/drm_crtc.h>
+/*
+ * PA MEMORY COLOR types
+ * @MEMCOLOR_SKIN Skin memory color type
+ * @MEMCOLOR_SKY Sky memory color type
+ * @MEMCOLOR_FOLIAGE Foliage memory color type
+ */
+enum sde_memcolor_type {
+ MEMCOLOR_SKIN = 0,
+ MEMCOLOR_SKY,
+ MEMCOLOR_FOLIAGE
+};
+
/**
* sde_cp_crtc_init(): Initialize color processing lists for a crtc.
* Should be called during crtc initialization.
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 9f49625..47c9bd9 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
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <drm/msm_drm_pp.h>
#include "sde_hw_color_processing_v1_7.h"
#define PA_HUE_OFF 0x110
@@ -21,6 +22,23 @@
#define PA_CONT_OFF 0x11C
#define PA_CONT_MASK 0xFF
+#define MEMCOL_PWL0_OFF 0x88
+#define MEMCOL_PWL0_MASK 0xFFFF07FF
+#define MEMCOL_PWL1_OFF 0x8C
+#define MEMCOL_PWL1_MASK 0xFFFFFFFF
+#define MEMCOL_HUE_REGION_OFF 0x90
+#define MEMCOL_HUE_REGION_MASK 0x7FF07FF
+#define MEMCOL_SAT_REGION_OFF 0x94
+#define MEMCOL_SAT_REGION_MASK 0xFFFFFF
+#define MEMCOL_VAL_REGION_OFF 0x98
+#define MEMCOL_VAL_REGION_MASK 0xFFFFFF
+#define MEMCOL_P0_LEN 0x14
+#define MEMCOL_P1_LEN 0x8
+#define MEMCOL_PWL2_OFF 0x218
+#define MEMCOL_PWL2_MASK 0xFFFFFFFF
+#define MEMCOL_BLEND_GAIN_OFF 0x21C
+#define MEMCOL_PWL_HOLD_OFF 0x214
+
#define VIG_OP_PA_EN BIT(4)
#define VIG_OP_PA_SKIN_EN BIT(5)
#define VIG_OP_PA_FOL_EN BIT(6)
@@ -119,3 +137,66 @@
SDE_REG_WRITE(&ctx->hw, base, opmode);
}
+
+void sde_setup_pipe_pa_memcol_v1_7(struct sde_hw_pipe *ctx,
+ enum sde_memcolor_type type,
+ void *cfg)
+{
+ struct drm_msm_memcol *mc = cfg;
+ u32 base = ctx->cap->sblk->memcolor_blk.base;
+ u32 off, op, mc_en, hold = 0;
+ u32 mc_i = 0;
+
+ switch (type) {
+ case MEMCOLOR_SKIN:
+ mc_en = VIG_OP_PA_SKIN_EN;
+ mc_i = 0;
+ break;
+ case MEMCOLOR_SKY:
+ mc_en = VIG_OP_PA_SKY_EN;
+ mc_i = 1;
+ break;
+ case MEMCOLOR_FOLIAGE:
+ mc_en = VIG_OP_PA_FOL_EN;
+ mc_i = 2;
+ break;
+ default:
+ DRM_ERROR("Invalid memory color type %d\n", type);
+ return;
+ }
+
+ op = SDE_REG_READ(&ctx->hw, base);
+ if (!mc) {
+ op &= ~mc_en;
+ if (PA_DISABLE_REQUIRED(op))
+ op &= ~VIG_OP_PA_EN;
+ SDE_REG_WRITE(&ctx->hw, base, op);
+ return;
+ }
+
+ off = base + (mc_i * MEMCOL_P0_LEN);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_PWL0_OFF),
+ mc->color_adjust_p0 & MEMCOL_PWL0_MASK);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_PWL1_OFF),
+ mc->color_adjust_p1 & MEMCOL_PWL1_MASK);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_HUE_REGION_OFF),
+ mc->hue_region & MEMCOL_HUE_REGION_MASK);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_SAT_REGION_OFF),
+ mc->sat_region & MEMCOL_SAT_REGION_MASK);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_VAL_REGION_OFF),
+ mc->val_region & MEMCOL_VAL_REGION_MASK);
+
+ off = base + (mc_i * MEMCOL_P1_LEN);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_PWL2_OFF),
+ mc->color_adjust_p2 & MEMCOL_PWL2_MASK);
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_BLEND_GAIN_OFF), mc->blend_gain);
+
+ hold = SDE_REG_READ(&ctx->hw, off + MEMCOL_PWL_HOLD_OFF);
+ hold &= ~(0xF << (mc_i * 4));
+ hold |= ((mc->sat_hold & 0x3) << (mc_i * 4));
+ hold |= ((mc->val_hold & 0x3) << ((mc_i * 4) + 2));
+ SDE_REG_WRITE(&ctx->hw, (off + MEMCOL_PWL_HOLD_OFF), hold);
+
+ op |= VIG_OP_PA_EN | mc_en;
+ SDE_REG_WRITE(&ctx->hw, base, op);
+}
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 788bde0..174ed85 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
@@ -43,4 +43,14 @@
*/
void sde_setup_pipe_pa_cont_v1_7(struct sde_hw_pipe *ctx, void *cfg);
+/**
+ * sde_setup_pipe_pa_memcol_v1_7 - setup SSPP memory color in v1.7 hardware
+ * @ctx: Pointer to pipe context
+ * @type: Memory color type (Skin, sky, or foliage)
+ * @cfg: Pointer to memory color config data
+ */
+void sde_setup_pipe_pa_memcol_v1_7(struct sde_hw_pipe *ctx,
+ enum sde_memcolor_type type,
+ void *cfg);
+
#endif
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index dae36ef..929c59a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -879,6 +879,13 @@
c->ops.setup_pa_cont = sde_setup_pipe_pa_cont_v1_7;
}
}
+
+ if (test_bit(SDE_SSPP_MEMCOLOR, &features)) {
+ if (c->cap->sblk->memcolor_blk.version ==
+ (SDE_COLOR_PROCESS_VER(0x1, 0x7)))
+ c->ops.setup_pa_memcolor =
+ sde_setup_pipe_pa_memcol_v1_7;
+ }
}
static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index 85f2ae6..743f5e7 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -17,6 +17,7 @@
#include "sde_hw_mdss.h"
#include "sde_hw_util.h"
#include "sde_formats.h"
+#include "sde_color_processing.h"
struct sde_hw_pipe;
@@ -358,11 +359,11 @@
/**
* setup_pa_memcolor - setup source color processing
* @ctx: Pointer to pipe context
- * @memcolortype: Memcolor type
- * @en: PA enable
+ * @type: Memcolor type (Skin, sky or foliage)
+ * @cfg: Pointer to memory color config data
*/
void (*setup_pa_memcolor)(struct sde_hw_pipe *ctx,
- u32 memcolortype, u8 en);
+ enum sde_memcolor_type type, void *cfg);
/**
* setup_igc - setup inverse gamma correction
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 70b6d25..5368cbd 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -14,6 +14,7 @@
#include <linux/debugfs.h>
#include <uapi/drm/sde_drm.h>
+#include <uapi/drm/msm_drm_pp.h>
#include "msm_prop.h"
@@ -25,6 +26,7 @@
#include "sde_crtc.h"
#include "sde_vbif.h"
#include "sde_plane.h"
+#include "sde_color_processing.h"
#define SDE_DEBUG_PLANE(pl, fmt, ...) SDE_DEBUG("plane%d " fmt,\
(pl) ? (pl)->base.base.id : -1, ##__VA_ARGS__)
@@ -779,6 +781,8 @@
struct sde_plane *psde;
struct sde_plane_state *pstate;
uint32_t hue, saturation, value, contrast;
+ struct drm_msm_memcol *memcol = NULL;
+ size_t memcol_sz = 0;
psde = to_sde_plane(plane);
pstate = to_sde_plane_state(plane->state);
@@ -798,8 +802,33 @@
PLANE_PROP_CONTRAST_ADJUST);
if (psde->pipe_hw->ops.setup_pa_cont)
psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
-}
+ if (psde->pipe_hw->ops.setup_pa_memcolor) {
+ /* Skin memory color setup */
+ memcol = msm_property_get_blob(&psde->property_info,
+ pstate->property_blobs,
+ &memcol_sz,
+ PLANE_PROP_SKIN_COLOR);
+ psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
+ MEMCOLOR_SKIN, memcol);
+
+ /* Sky memory color setup */
+ memcol = msm_property_get_blob(&psde->property_info,
+ pstate->property_blobs,
+ &memcol_sz,
+ PLANE_PROP_SKY_COLOR);
+ psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
+ MEMCOLOR_SKY, memcol);
+
+ /* Foliage memory color setup */
+ memcol = msm_property_get_blob(&psde->property_info,
+ pstate->property_blobs,
+ &memcol_sz,
+ PLANE_PROP_FOLIAGE_COLOR);
+ psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
+ MEMCOLOR_FOLIAGE, memcol);
+ }
+}
static void _sde_plane_setup_scaler(struct sde_plane *psde,
const struct sde_format *fmt,
@@ -1602,6 +1631,24 @@
info->data, info->len, PLANE_PROP_INFO);
kfree(info);
+
+ if (psde->features & BIT(SDE_SSPP_MEMCOLOR)) {
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_SKIN_COLOR_V",
+ psde->pipe_sblk->memcolor_blk.version >> 16);
+ msm_property_install_blob(&psde->property_info, feature_name, 0,
+ PLANE_PROP_SKIN_COLOR);
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_SKY_COLOR_V",
+ psde->pipe_sblk->memcolor_blk.version >> 16);
+ msm_property_install_blob(&psde->property_info, feature_name, 0,
+ PLANE_PROP_SKY_COLOR);
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_FOLIAGE_COLOR_V",
+ psde->pipe_sblk->memcolor_blk.version >> 16);
+ msm_property_install_blob(&psde->property_info, feature_name, 0,
+ PLANE_PROP_FOLIAGE_COLOR);
+ }
}
static inline void _sde_plane_set_csc_v1(struct sde_plane *psde, void *usr_ptr)