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@xxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel