[PATCH v2] drm/fsl-dcu: Implement gamma_lut atomic crtc properties
Meng Yi
meng.yi at nxp.com
Fri Jul 29 08:45:35 UTC 2016
Gamma correction is optional and can be used to adjust the color
output values to match the gamut of a particular TFT LCD panel
Gamma_R, Gamma_G and Gamma_B registers are little-endian registers
while the rest of the address-space in 2D-ACE is big-endian.
Signed-off-by: Meng Yi <meng.yi at nxp.com>
---
Changes in V2:
-title "Add gamma set for crtc" changed
-use new atomic color management properties instead
-simplify the method for workaround by using val<<24
-add registers endianness info to comments
---
drivers/gpu/drm/fsl-dcu/Kconfig | 6 +++++
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 39 ++++++++++++++++++++++++++++++
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 8 ++++++
3 files changed, 53 insertions(+)
diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
index b9c714d..ddfe3c4 100644
--- a/drivers/gpu/drm/fsl-dcu/Kconfig
+++ b/drivers/gpu/drm/fsl-dcu/Kconfig
@@ -16,3 +16,9 @@ config DRM_FSL_DCU
help
Choose this option if you have an Freescale DCU chipset.
If M is selected the module will be called fsl-dcu-drm.
+
+config DRM_FSL_DCU_GAMMA
+ bool "Gamma Correction Support for NXP/Freescale DCU"
+ depends on DRM_FSL_DCU
+ help
+ Enable support for gamma correction.
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
index 3371635..f187992 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -22,6 +22,22 @@
#include "fsl_dcu_drm_drv.h"
#include "fsl_dcu_drm_plane.h"
+static void fsl_crtc_gamma_set(struct drm_crtc *crtc, struct drm_color_lut *lut,
+ uint32_t size)
+{
+ struct fsl_dcu_drm_device *fsl_dev = crtc->dev->dev_private;
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ regmap_write(fsl_dev->regmap, FSL_GAMMA_R + 4 * i,
+ lut[i].red << 24);
+ regmap_write(fsl_dev->regmap, FSL_GAMMA_G + 4 * i,
+ lut[i].green << 24);
+ regmap_write(fsl_dev->regmap, FSL_GAMMA_B + 4 * i,
+ lut[i].blue << 24);
+ }
+}
+
static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -37,6 +53,11 @@ static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irq(&crtc->dev->event_lock);
}
+
+ if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
+ fsl_crtc_gamma_set(crtc, (struct drm_color_lut *)
+ crtc->state->gamma_lut->data,
+ 256);
}
static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
@@ -46,6 +67,11 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
drm_crtc_vblank_off(crtc);
+ if (fsl_dev->enable_color_mgmt)
+ regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
+ DCU_MODE_EN_GAMMA_MASK,
+ DCU_MODE_GAMMA_DISABLE);
+
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF));
@@ -58,6 +84,11 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+ if (fsl_dev->enable_color_mgmt)
+ regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
+ DCU_MODE_EN_GAMMA_MASK,
+ DCU_MODE_GAMMA_ENABLE);
+
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
@@ -135,6 +166,7 @@ static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.set_config = drm_atomic_helper_set_config,
+ .gamma_set = drm_atomic_helper_legacy_gamma_set,
};
int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
@@ -158,5 +190,12 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
+#ifdef CONFIG_DRM_FSL_DCU_GAMMA
+ fsl_dev->enable_color_mgmt = true;
+
+ drm_crtc_enable_color_mgmt(crtc, 0, false, 256);
+ drm_mode_crtc_set_gamma_size(crtc, 256);
+#endif
+
return 0;
}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
index 3b371fe7..a164e91 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -25,6 +25,9 @@
#define DCU_MODE_NORMAL 1
#define DCU_MODE_TEST 2
#define DCU_MODE_COLORBAR 3
+#define DCU_MODE_EN_GAMMA_MASK 0x04
+#define DCU_MODE_GAMMA_ENABLE BIT(2)
+#define DCU_MODE_GAMMA_DISABLE 0
#define DCU_BGND 0x0014
#define DCU_BGND_R(x) ((x) << 16)
@@ -165,6 +168,10 @@
#define VF610_LAYER_REG_NUM 9
#define LS1021A_LAYER_REG_NUM 10
+#define FSL_GAMMA_R 0x4000
+#define FSL_GAMMA_G 0x4400
+#define FSL_GAMMA_B 0x4800
+
struct clk;
struct device;
struct drm_device;
@@ -195,6 +202,7 @@ struct fsl_dcu_drm_device {
struct fsl_dcu_drm_connector connector;
const struct fsl_dcu_soc_data *soc;
struct drm_atomic_state *state;
+ bool enable_color_mgmt;
};
void fsl_dcu_fbdev_init(struct drm_device *dev);
--
2.1.0.27.g96db324
More information about the dri-devel
mailing list