diff mbox

[v2] drm/fsl-dcu: Implement gamma_lut atomic crtc properties

Message ID 1469781935-9326-1-git-send-email-meng.yi@nxp.com (mailing list archive)
State New, archived
Headers show

Commit Message

Meng Yi July 29, 2016, 8:45 a.m. UTC
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@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(+)

Comments

Meng Yi Aug. 22, 2016, 7:10 a.m. UTC | #1
Hi Stefan,
	What do you think about this patch for gamma correction. 
	I see many people approach gamma correction this way. Do you have any comments?

Best Regards,
Meng

> +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,
>  };
>
diff mbox

Patch

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);