drm/msm/sde: Add PA global adjustment properties to plane
Add support for hue, saturation, intensity, and contrast adjustment
in planes that have color processing support.
Change-Id: I4c794deb7a5a1c0cc30cc0d64fbffd967eb1d399
Signed-off-by: Benet Clark <benetc@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 8ef30cc..c988279 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -119,7 +119,8 @@
sde/sde_hw_interrupts.o \
sde/sde_hw_vbif.o \
sde/sde_formats.o \
- sde_power_handle.o
+ sde_power_handle.o \
+ sde/sde_hw_color_processing_v1_7.o
msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
sde/sde_encoder_phys_wb.o
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 91660c9..d08e65d 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -95,6 +95,10 @@
PLANE_PROP_H_DECIMATE,
PLANE_PROP_V_DECIMATE,
PLANE_PROP_INPUT_FENCE,
+ PLANE_PROP_HUE_ADJUST,
+ PLANE_PROP_SATURATION_ADJUST,
+ PLANE_PROP_VALUE_ADJUST,
+ PLANE_PROP_CONTRAST_ADJUST,
/* enum/bitmask properties */
PLANE_PROP_ROTATION,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing.h b/drivers/gpu/drm/msm/sde/sde_hw_color_processing.h
new file mode 100644
index 0000000..a30e1a5
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SDE_HW_COLOR_PROCESSING_H
+#define _SDE_HW_COLOR_PROCESSING_H
+
+#include "sde_hw_color_processing_v1_7.h"
+
+#endif
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
new file mode 100644
index 0000000..9f49625
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
@@ -0,0 +1,121 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sde_hw_color_processing_v1_7.h"
+
+#define PA_HUE_OFF 0x110
+#define PA_HUE_MASK 0xFFF
+#define PA_SAT_OFF 0x114
+#define PA_SAT_MASK 0xFFFF
+#define PA_VAL_OFF 0x118
+#define PA_VAL_MASK 0xFF
+#define PA_CONT_OFF 0x11C
+#define PA_CONT_MASK 0xFF
+
+#define VIG_OP_PA_EN BIT(4)
+#define VIG_OP_PA_SKIN_EN BIT(5)
+#define VIG_OP_PA_FOL_EN BIT(6)
+#define VIG_OP_PA_SKY_EN BIT(7)
+#define VIG_OP_PA_HUE_EN BIT(25)
+#define VIG_OP_PA_SAT_EN BIT(26)
+#define VIG_OP_PA_VAL_EN BIT(27)
+#define VIG_OP_PA_CONT_EN BIT(28)
+
+#define PA_DISABLE_REQUIRED(x) !((x) & \
+ (VIG_OP_PA_SKIN_EN | VIG_OP_PA_SKY_EN | \
+ VIG_OP_PA_FOL_EN | VIG_OP_PA_HUE_EN | \
+ VIG_OP_PA_SAT_EN | VIG_OP_PA_VAL_EN | \
+ VIG_OP_PA_CONT_EN))
+
+void sde_setup_pipe_pa_hue_v1_7(struct sde_hw_pipe *ctx, void *cfg)
+{
+ uint32_t hue = *((uint32_t *)cfg);
+ u32 base = ctx->cap->sblk->hsic_blk.base;
+ u32 opmode = 0;
+
+ SDE_REG_WRITE(&ctx->hw, base + PA_HUE_OFF, hue & PA_HUE_MASK);
+
+ opmode = SDE_REG_READ(&ctx->hw, base);
+
+ if (!hue) {
+ opmode &= ~VIG_OP_PA_HUE_EN;
+ if (PA_DISABLE_REQUIRED(opmode))
+ opmode &= ~VIG_OP_PA_EN;
+ } else {
+ opmode |= VIG_OP_PA_HUE_EN | VIG_OP_PA_EN;
+ }
+
+ SDE_REG_WRITE(&ctx->hw, base, opmode);
+}
+
+void sde_setup_pipe_pa_sat_v1_7(struct sde_hw_pipe *ctx, void *cfg)
+{
+ uint32_t sat = *((uint32_t *)cfg);
+ u32 base = ctx->cap->sblk->hsic_blk.base;
+ u32 opmode = 0;
+
+ SDE_REG_WRITE(&ctx->hw, base + PA_SAT_OFF, sat & PA_SAT_MASK);
+
+ opmode = SDE_REG_READ(&ctx->hw, base);
+
+ if (!sat) {
+ opmode &= ~VIG_OP_PA_SAT_EN;
+ if (PA_DISABLE_REQUIRED(opmode))
+ opmode &= ~VIG_OP_PA_EN;
+ } else {
+ opmode |= VIG_OP_PA_SAT_EN | VIG_OP_PA_EN;
+ }
+
+ SDE_REG_WRITE(&ctx->hw, base, opmode);
+}
+
+void sde_setup_pipe_pa_val_v1_7(struct sde_hw_pipe *ctx, void *cfg)
+{
+ uint32_t value = *((uint32_t *)cfg);
+ u32 base = ctx->cap->sblk->hsic_blk.base;
+ u32 opmode = 0;
+
+ SDE_REG_WRITE(&ctx->hw, base + PA_VAL_OFF, value & PA_VAL_MASK);
+
+ opmode = SDE_REG_READ(&ctx->hw, base);
+
+ if (!value) {
+ opmode &= ~VIG_OP_PA_VAL_EN;
+ if (PA_DISABLE_REQUIRED(opmode))
+ opmode &= ~VIG_OP_PA_EN;
+ } else {
+ opmode |= VIG_OP_PA_VAL_EN | VIG_OP_PA_EN;
+ }
+
+ SDE_REG_WRITE(&ctx->hw, base, opmode);
+}
+
+void sde_setup_pipe_pa_cont_v1_7(struct sde_hw_pipe *ctx, void *cfg)
+{
+ uint32_t contrast = *((uint32_t *)cfg);
+ u32 base = ctx->cap->sblk->hsic_blk.base;
+ u32 opmode = 0;
+
+ SDE_REG_WRITE(&ctx->hw, base + PA_CONT_OFF, contrast & PA_CONT_MASK);
+
+ opmode = SDE_REG_READ(&ctx->hw, base);
+
+ if (!contrast) {
+ opmode &= ~VIG_OP_PA_CONT_EN;
+ if (PA_DISABLE_REQUIRED(opmode))
+ opmode &= ~VIG_OP_PA_EN;
+ } else {
+ opmode |= VIG_OP_PA_CONT_EN | VIG_OP_PA_EN;
+ }
+
+ SDE_REG_WRITE(&ctx->hw, base, opmode);
+}
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
new file mode 100644
index 0000000..788bde0
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SDE_HW_COLOR_PROCESSING_V1_7_H
+#define _SDE_HW_COLOR_PROCESSING_V1_7_H
+
+#include "sde_hw_sspp.h"
+
+/**
+ * sde_setup_pipe_pa_hue_v1_7 - setup SSPP hue feature in v1.7 hardware
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to hue data
+ */
+void sde_setup_pipe_pa_hue_v1_7(struct sde_hw_pipe *ctx, void *cfg);
+
+/**
+ * sde_setup_pipe_pa_sat_v1_7 - setup SSPP saturation feature in v1.7 hardware
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to saturation data
+ */
+void sde_setup_pipe_pa_sat_v1_7(struct sde_hw_pipe *ctx, void *cfg);
+
+/**
+ * sde_setup_pipe_pa_val_v1_7 - setup SSPP value feature in v1.7 hardware
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to value data
+ */
+void sde_setup_pipe_pa_val_v1_7(struct sde_hw_pipe *ctx, void *cfg);
+
+/**
+ * sde_setup_pipe_pa_cont_v1_7 - setup SSPP contrast feature in v1.7 hardware
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to contrast data
+ */
+void sde_setup_pipe_pa_cont_v1_7(struct sde_hw_pipe *ctx, 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 f590f91..dae36ef 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -14,6 +14,7 @@
#include "sde_hw_catalog.h"
#include "sde_hw_lm.h"
#include "sde_hw_sspp.h"
+#include "sde_hw_color_processing.h"
#define SDE_FETCH_CONFIG_RESET_VALUE 0x00000087
@@ -840,31 +841,44 @@
SDE_REG_WRITE(&ctx->hw, SSPP_QOS_CTRL + idx, qos_ctrl);
}
-static void _setup_layer_ops(struct sde_hw_sspp_ops *ops,
+static void _setup_layer_ops(struct sde_hw_pipe *c,
unsigned long features)
{
if (test_bit(SDE_SSPP_SRC, &features)) {
- ops->setup_format = sde_hw_sspp_setup_format;
- ops->setup_rects = sde_hw_sspp_setup_rects;
- ops->setup_sourceaddress = sde_hw_sspp_setup_sourceaddress;
- ops->setup_solidfill = sde_hw_sspp_setup_solidfill;
+ c->ops.setup_format = sde_hw_sspp_setup_format;
+ c->ops.setup_rects = sde_hw_sspp_setup_rects;
+ c->ops.setup_sourceaddress = sde_hw_sspp_setup_sourceaddress;
+ c->ops.setup_solidfill = sde_hw_sspp_setup_solidfill;
}
if (test_bit(SDE_SSPP_QOS, &features)) {
- ops->setup_danger_safe_lut = sde_hw_sspp_setup_danger_safe_lut;
- ops->setup_creq_lut = sde_hw_sspp_setup_creq_lut;
- ops->setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl;
+ c->ops.setup_danger_safe_lut =
+ sde_hw_sspp_setup_danger_safe_lut;
+ c->ops.setup_creq_lut = sde_hw_sspp_setup_creq_lut;
+ c->ops.setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl;
}
+
if (test_bit(SDE_SSPP_CSC, &features) ||
test_bit(SDE_SSPP_CSC_10BIT, &features))
- ops->setup_csc = sde_hw_sspp_setup_csc;
+ c->ops.setup_csc = sde_hw_sspp_setup_csc;
if (test_bit(SDE_SSPP_SCALER_QSEED2, &features))
- ops->setup_sharpening = sde_hw_sspp_setup_sharpening;
+ c->ops.setup_sharpening = sde_hw_sspp_setup_sharpening;
if (test_bit(SDE_SSPP_SCALER_QSEED3, &features))
- ops->setup_scaler = _sde_hw_sspp_setup_scaler3;
+ c->ops.setup_scaler = _sde_hw_sspp_setup_scaler3;
else
- ops->setup_scaler = _sde_hw_sspp_setup_scaler;
+ c->ops.setup_scaler = _sde_hw_sspp_setup_scaler;
+
+ if (test_bit(SDE_SSPP_HSIC, &features)) {
+ /* TODO: add version based assignment here as inline or macro */
+ if (c->cap->sblk->hsic_blk.version ==
+ (SDE_COLOR_PROCESS_VER(0x1, 0x7))) {
+ c->ops.setup_pa_hue = sde_setup_pipe_pa_hue_v1_7;
+ c->ops.setup_pa_sat = sde_setup_pipe_pa_sat_v1_7;
+ c->ops.setup_pa_val = sde_setup_pipe_pa_val_v1_7;
+ c->ops.setup_pa_cont = sde_setup_pipe_pa_cont_v1_7;
+ }
+ }
}
static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,
@@ -909,7 +923,7 @@
/* Assign ops */
ctx->idx = idx;
ctx->cap = cfg;
- _setup_layer_ops(&ctx->ops, ctx->cap->features);
+ _setup_layer_ops(ctx, ctx->cap->features);
ctx->highest_bank_bit = catalog->mdp[0].highest_bank_bit;
return ctx;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
index 488936e..85f2ae6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h
@@ -326,6 +326,35 @@
void (*setup_sharpening)(struct sde_hw_pipe *ctx,
struct sde_hw_sharp_cfg *cfg);
+
+ /**
+ * setup_pa_hue(): Setup source hue adjustment
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to hue data
+ */
+ void (*setup_pa_hue)(struct sde_hw_pipe *ctx, void *cfg);
+
+ /**
+ * setup_pa_sat(): Setup source saturation adjustment
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to saturation data
+ */
+ void (*setup_pa_sat)(struct sde_hw_pipe *ctx, void *cfg);
+
+ /**
+ * setup_pa_val(): Setup source value adjustment
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer to value data
+ */
+ void (*setup_pa_val)(struct sde_hw_pipe *ctx, void *cfg);
+
+ /**
+ * setup_pa_cont(): Setup source contrast adjustment
+ * @ctx: Pointer to pipe context
+ * @cfg: Pointer contrast data
+ */
+ void (*setup_pa_cont)(struct sde_hw_pipe *ctx, void *cfg);
+
/**
* setup_pa_memcolor - setup source color processing
* @ctx: Pointer to pipe context
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index cd4dbb7..70b6d25 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -774,6 +774,33 @@
psde->csc_ptr->csc_mv[2]);
}
+static void sde_color_process_plane_setup(struct drm_plane *plane)
+{
+ struct sde_plane *psde;
+ struct sde_plane_state *pstate;
+ uint32_t hue, saturation, value, contrast;
+
+ psde = to_sde_plane(plane);
+ pstate = to_sde_plane_state(plane->state);
+
+ hue = (uint32_t) sde_plane_get_property(pstate, PLANE_PROP_HUE_ADJUST);
+ if (psde->pipe_hw->ops.setup_pa_hue)
+ psde->pipe_hw->ops.setup_pa_hue(psde->pipe_hw, &hue);
+ saturation = (uint32_t) sde_plane_get_property(pstate,
+ PLANE_PROP_SATURATION_ADJUST);
+ if (psde->pipe_hw->ops.setup_pa_sat)
+ psde->pipe_hw->ops.setup_pa_sat(psde->pipe_hw, &saturation);
+ value = (uint32_t) sde_plane_get_property(pstate,
+ PLANE_PROP_VALUE_ADJUST);
+ if (psde->pipe_hw->ops.setup_pa_val)
+ psde->pipe_hw->ops.setup_pa_val(psde->pipe_hw, &value);
+ contrast = (uint32_t) sde_plane_get_property(pstate,
+ PLANE_PROP_CONTRAST_ADJUST);
+ if (psde->pipe_hw->ops.setup_pa_cont)
+ psde->pipe_hw->ops.setup_pa_cont(psde->pipe_hw, &contrast);
+}
+
+
static void _sde_plane_setup_scaler(struct sde_plane *psde,
const struct sde_format *fmt,
struct sde_plane_state *pstate)
@@ -1081,6 +1108,8 @@
psde->csc_ptr = 0;
}
+ sde_color_process_plane_setup(plane);
+
/* update sharpening */
if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
psde->pipe_hw->ops.setup_sharpening) {
@@ -1429,6 +1458,7 @@
struct sde_plane *psde = to_sde_plane(plane);
int zpos_max = 255;
int zpos_def = 0;
+ char feature_name[256];
if (!plane || !psde) {
SDE_ERROR("invalid plane\n");
@@ -1495,6 +1525,33 @@
"csc_v1", 0x0, 0, ~0, 0, PLANE_PROP_CSC_V1);
}
+ if (psde->features & BIT(SDE_SSPP_HSIC)) {
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_HUE_V",
+ psde->pipe_sblk->hsic_blk.version >> 16);
+ msm_property_install_range(&psde->property_info,
+ feature_name, 0, 0, 0xFFFFFFFF, 0,
+ PLANE_PROP_HUE_ADJUST);
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_SATURATION_V",
+ psde->pipe_sblk->hsic_blk.version >> 16);
+ msm_property_install_range(&psde->property_info,
+ feature_name, 0, 0, 0xFFFFFFFF, 0,
+ PLANE_PROP_SATURATION_ADJUST);
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_VALUE_V",
+ psde->pipe_sblk->hsic_blk.version >> 16);
+ msm_property_install_range(&psde->property_info,
+ feature_name, 0, 0, 0xFFFFFFFF, 0,
+ PLANE_PROP_VALUE_ADJUST);
+ snprintf(feature_name, sizeof(feature_name), "%s%d",
+ "SDE_SSPP_CONTRAST_V",
+ psde->pipe_sblk->hsic_blk.version >> 16);
+ msm_property_install_range(&psde->property_info,
+ feature_name, 0, 0, 0xFFFFFFFF, 0,
+ PLANE_PROP_CONTRAST_ADJUST);
+ }
+
/* standard properties */
msm_property_install_rotation(&psde->property_info,
BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y), PLANE_PROP_ROTATION);