diff mbox

[RFC,v2,1/3] drm: atmel-hlcdc: add support for 8-bit color lookup table mode

Message ID 1497721684-3002-2-git-send-email-peda@axentia.se (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Rosin June 17, 2017, 5:48 p.m. UTC
All layers of all supported chips support this, the only variable is the
base address of the lookup table in the register map.

Signed-off-by: Peter Rosin <peda@axentia.se>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c  |  5 +++++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c    | 13 +++++++++++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    | 16 ++++++++++++++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 +++++++++++++++++++++++++
 4 files changed, 63 insertions(+)

Comments

Daniel Vetter June 20, 2017, 9:40 a.m. UTC | #1
On Sat, Jun 17, 2017 at 07:48:02PM +0200, Peter Rosin wrote:
> All layers of all supported chips support this, the only variable is the
> base address of the lookup table in the register map.
> 
> Signed-off-by: Peter Rosin <peda@axentia.se>

As Boris said, pls use the new color manager stuff for atomic drivers, and
then use the helper to implement the legacy kms LUT support on top of it,
it's drm_atomic_helper_legacy_gamma_set().
-Daniel

> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c  |  5 +++++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c    | 13 +++++++++++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    | 16 ++++++++++++++
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 +++++++++++++++++++++++++
>  4 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> index 5348985..694adcc 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> @@ -429,6 +429,8 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
>  	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
>  	.enable_vblank = atmel_hlcdc_crtc_enable_vblank,
>  	.disable_vblank = atmel_hlcdc_crtc_disable_vblank,
> +	.set_property = drm_atomic_helper_crtc_set_property,
> +	.gamma_set = drm_atomic_helper_legacy_gamma_set,
>  };
>  
>  int atmel_hlcdc_crtc_create(struct drm_device *dev)
> @@ -484,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
>  	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
>  	drm_crtc_vblank_reset(&crtc->base);
>  
> +	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
> +	drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE);
> +
>  	dc->crtc = &crtc->base;
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index 30dbffd..4f6ef07 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = {
>  			.default_color = 3,
>  			.general_config = 4,
>  		},
> +		.clut_offset = 0x400,
>  	},
>  };
>  
> @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>  			.disc_pos = 5,
>  			.disc_size = 6,
>  		},
> +		.clut_offset = 0x400,
>  	},
>  	{
>  		.name = "overlay1",
> @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>  			.chroma_key_mask = 8,
>  			.general_config = 9,
>  		},
> +		.clut_offset = 0x800,
>  	},
>  	{
>  		.name = "high-end-overlay",
> @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>  			.scaler_config = 13,
>  			.csc = 14,
>  		},
> +		.clut_offset = 0x1000,
>  	},
>  	{
>  		.name = "cursor",
> @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>  			.chroma_key_mask = 8,
>  			.general_config = 9,
>  		},
> +		.clut_offset = 0x1400,
>  	},
>  };
>  
> @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>  			.disc_pos = 5,
>  			.disc_size = 6,
>  		},
> +		.clut_offset = 0x600,
>  	},
>  	{
>  		.name = "overlay1",
> @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>  			.chroma_key_mask = 8,
>  			.general_config = 9,
>  		},
> +		.clut_offset = 0xa00,
>  	},
>  	{
>  		.name = "overlay2",
> @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>  			.chroma_key_mask = 8,
>  			.general_config = 9,
>  		},
> +		.clut_offset = 0xe00,
>  	},
>  	{
>  		.name = "high-end-overlay",
> @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>  			},
>  			.csc = 14,
>  		},
> +		.clut_offset = 0x1200,
>  	},
>  	{
>  		.name = "cursor",
> @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>  			.general_config = 9,
>  			.scaler_config = 13,
>  		},
> +		.clut_offset = 0x1600,
>  	},
>  };
>  
> @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>  			.disc_pos = 5,
>  			.disc_size = 6,
>  		},
> +		.clut_offset = 0x600,
>  	},
>  	{
>  		.name = "overlay1",
> @@ -293,6 +304,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>  			.chroma_key_mask = 8,
>  			.general_config = 9,
>  		},
> +		.clut_offset = 0xa00,
>  	},
>  	{
>  		.name = "overlay2",
> @@ -336,6 +348,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>  			},
>  			.csc = 14,
>  		},
> +		.clut_offset = 0x1200,
>  	},
>  };
>  
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> index b0596a8..709f7b9 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> @@ -88,6 +88,11 @@
>  #define ATMEL_HLCDC_YUV422SWP			BIT(17)
>  #define ATMEL_HLCDC_DSCALEOPT			BIT(20)
>  
> +#define ATMEL_HLCDC_C1_MODE			ATMEL_HLCDC_CLUT_MODE(0)
> +#define ATMEL_HLCDC_C2_MODE			ATMEL_HLCDC_CLUT_MODE(1)
> +#define ATMEL_HLCDC_C4_MODE			ATMEL_HLCDC_CLUT_MODE(2)
> +#define ATMEL_HLCDC_C8_MODE			ATMEL_HLCDC_CLUT_MODE(3)
> +
>  #define ATMEL_HLCDC_XRGB4444_MODE		ATMEL_HLCDC_RGB_MODE(0)
>  #define ATMEL_HLCDC_ARGB4444_MODE		ATMEL_HLCDC_RGB_MODE(1)
>  #define ATMEL_HLCDC_RGBA4444_MODE		ATMEL_HLCDC_RGB_MODE(2)
> @@ -142,6 +147,8 @@
>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE	BIT(2)
>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN	BIT(3)
>  
> +#define ATMEL_HLCDC_CLUT_SIZE			256
> +
>  #define ATMEL_HLCDC_MAX_LAYERS			6
>  
>  /**
> @@ -259,6 +266,7 @@ struct atmel_hlcdc_layer_desc {
>  	int id;
>  	int regs_offset;
>  	int cfgs_offset;
> +	int clut_offset;
>  	struct atmel_hlcdc_formats *formats;
>  	struct atmel_hlcdc_layer_cfg_layout layout;
>  	int max_width;
> @@ -414,6 +422,14 @@ static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer,
>  					  (cfgid * sizeof(u32)));
>  }
>  
> +static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer,
> +						unsigned int c, u32 val)
> +{
> +	atmel_hlcdc_layer_write_reg(layer,
> +				    layer->desc->clut_offset + c * sizeof(u32),
> +				    val);
> +}
> +
>  static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
>  				const struct atmel_hlcdc_layer_desc *desc,
>  				struct regmap *regmap)
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> index 1124200..b5bd9b0 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> @@ -83,6 +83,7 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
>  #define SUBPIXEL_MASK			0xffff
>  
>  static uint32_t rgb_formats[] = {
> +	DRM_FORMAT_C8,
>  	DRM_FORMAT_XRGB4444,
>  	DRM_FORMAT_ARGB4444,
>  	DRM_FORMAT_RGBA4444,
> @@ -100,6 +101,7 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
>  };
>  
>  static uint32_t rgb_and_yuv_formats[] = {
> +	DRM_FORMAT_C8,
>  	DRM_FORMAT_XRGB4444,
>  	DRM_FORMAT_ARGB4444,
>  	DRM_FORMAT_RGBA4444,
> @@ -128,6 +130,9 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
>  static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
>  {
>  	switch (format) {
> +	case DRM_FORMAT_C8:
> +		*mode = ATMEL_HLCDC_C8_MODE;
> +		break;
>  	case DRM_FORMAT_XRGB4444:
>  		*mode = ATMEL_HLCDC_XRGB4444_MODE;
>  		break;
> @@ -424,6 +429,29 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
>  				    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
>  }
>  
> +static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane)
> +{
> +	struct drm_crtc *crtc = plane->base.crtc;
> +	struct drm_color_lut *lut;
> +	int idx;
> +
> +	if (!crtc || !crtc->state)
> +		return;
> +
> +	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
> +		return;
> +
> +	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
> +
> +	for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
> +		u32 val = ((lut->red << 8) & 0xff0000) |
> +			(lut->green & 0xff00) |
> +			(lut->blue >> 8);
> +
> +		atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
> +	}
> +}
> +
>  static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
>  					struct atmel_hlcdc_plane_state *state)
>  {
> @@ -768,6 +796,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
>  	atmel_hlcdc_plane_update_pos_and_size(plane, state);
>  	atmel_hlcdc_plane_update_general_settings(plane, state);
>  	atmel_hlcdc_plane_update_format(plane, state);
> +	atmel_hlcdc_plane_update_clut(plane);
>  	atmel_hlcdc_plane_update_buffers(plane, state);
>  	atmel_hlcdc_plane_update_disc_area(plane, state);
>  
> -- 
> 2.1.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Peter Rosin June 20, 2017, 9:55 a.m. UTC | #2
On 2017-06-20 11:40, Daniel Vetter wrote:
> On Sat, Jun 17, 2017 at 07:48:02PM +0200, Peter Rosin wrote:
>> All layers of all supported chips support this, the only variable is the
>> base address of the lookup table in the register map.
>>
>> Signed-off-by: Peter Rosin <peda@axentia.se>
> 
> As Boris said, pls use the new color manager stuff for atomic drivers, and
> then use the helper to implement the legacy kms LUT support on top of it,
> it's drm_atomic_helper_legacy_gamma_set().
> -Daniel

Hmm, I don't see how this comment applies to this patch? Isn't this
patch good as is, because I thought I already did wire this up with
the drm_atomic_helper_legacy_gamma_set helper as requested?
(sure, v3 has a register offset tweak, but that's just a detail)

I totally agree that 2/3 and 3/3 are ugly and I am working on that, but
if 1/3 is also not in the right direction I'd like to know ASAP. Thanks!

Cheers,
peda

> 
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c  |  5 +++++
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c    | 13 +++++++++++
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    | 16 ++++++++++++++
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 +++++++++++++++++++++++++
>>  4 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
>> index 5348985..694adcc 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
>> @@ -429,6 +429,8 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
>>  	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
>>  	.enable_vblank = atmel_hlcdc_crtc_enable_vblank,
>>  	.disable_vblank = atmel_hlcdc_crtc_disable_vblank,
>> +	.set_property = drm_atomic_helper_crtc_set_property,
>> +	.gamma_set = drm_atomic_helper_legacy_gamma_set,
>>  };
>>  
>>  int atmel_hlcdc_crtc_create(struct drm_device *dev)
>> @@ -484,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
>>  	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
>>  	drm_crtc_vblank_reset(&crtc->base);
>>  
>> +	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
>> +	drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE);
>> +
>>  	dc->crtc = &crtc->base;
>>  
>>  	return 0;
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 30dbffd..4f6ef07 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = {
>>  			.default_color = 3,
>>  			.general_config = 4,
>>  		},
>> +		.clut_offset = 0x400,
>>  	},
>>  };
>>  
>> @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>>  			.disc_pos = 5,
>>  			.disc_size = 6,
>>  		},
>> +		.clut_offset = 0x400,
>>  	},
>>  	{
>>  		.name = "overlay1",
>> @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>>  			.chroma_key_mask = 8,
>>  			.general_config = 9,
>>  		},
>> +		.clut_offset = 0x800,
>>  	},
>>  	{
>>  		.name = "high-end-overlay",
>> @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>>  			.scaler_config = 13,
>>  			.csc = 14,
>>  		},
>> +		.clut_offset = 0x1000,
>>  	},
>>  	{
>>  		.name = "cursor",
>> @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
>>  			.chroma_key_mask = 8,
>>  			.general_config = 9,
>>  		},
>> +		.clut_offset = 0x1400,
>>  	},
>>  };
>>  
>> @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>>  			.disc_pos = 5,
>>  			.disc_size = 6,
>>  		},
>> +		.clut_offset = 0x600,
>>  	},
>>  	{
>>  		.name = "overlay1",
>> @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>>  			.chroma_key_mask = 8,
>>  			.general_config = 9,
>>  		},
>> +		.clut_offset = 0xa00,
>>  	},
>>  	{
>>  		.name = "overlay2",
>> @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>>  			.chroma_key_mask = 8,
>>  			.general_config = 9,
>>  		},
>> +		.clut_offset = 0xe00,
>>  	},
>>  	{
>>  		.name = "high-end-overlay",
>> @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>>  			},
>>  			.csc = 14,
>>  		},
>> +		.clut_offset = 0x1200,
>>  	},
>>  	{
>>  		.name = "cursor",
>> @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
>>  			.general_config = 9,
>>  			.scaler_config = 13,
>>  		},
>> +		.clut_offset = 0x1600,
>>  	},
>>  };
>>  
>> @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>>  			.disc_pos = 5,
>>  			.disc_size = 6,
>>  		},
>> +		.clut_offset = 0x600,
>>  	},
>>  	{
>>  		.name = "overlay1",
>> @@ -293,6 +304,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>>  			.chroma_key_mask = 8,
>>  			.general_config = 9,
>>  		},
>> +		.clut_offset = 0xa00,
>>  	},
>>  	{
>>  		.name = "overlay2",
>> @@ -336,6 +348,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
>>  			},
>>  			.csc = 14,
>>  		},
>> +		.clut_offset = 0x1200,
>>  	},
>>  };
>>  
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
>> index b0596a8..709f7b9 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
>> @@ -88,6 +88,11 @@
>>  #define ATMEL_HLCDC_YUV422SWP			BIT(17)
>>  #define ATMEL_HLCDC_DSCALEOPT			BIT(20)
>>  
>> +#define ATMEL_HLCDC_C1_MODE			ATMEL_HLCDC_CLUT_MODE(0)
>> +#define ATMEL_HLCDC_C2_MODE			ATMEL_HLCDC_CLUT_MODE(1)
>> +#define ATMEL_HLCDC_C4_MODE			ATMEL_HLCDC_CLUT_MODE(2)
>> +#define ATMEL_HLCDC_C8_MODE			ATMEL_HLCDC_CLUT_MODE(3)
>> +
>>  #define ATMEL_HLCDC_XRGB4444_MODE		ATMEL_HLCDC_RGB_MODE(0)
>>  #define ATMEL_HLCDC_ARGB4444_MODE		ATMEL_HLCDC_RGB_MODE(1)
>>  #define ATMEL_HLCDC_RGBA4444_MODE		ATMEL_HLCDC_RGB_MODE(2)
>> @@ -142,6 +147,8 @@
>>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE	BIT(2)
>>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN	BIT(3)
>>  
>> +#define ATMEL_HLCDC_CLUT_SIZE			256
>> +
>>  #define ATMEL_HLCDC_MAX_LAYERS			6
>>  
>>  /**
>> @@ -259,6 +266,7 @@ struct atmel_hlcdc_layer_desc {
>>  	int id;
>>  	int regs_offset;
>>  	int cfgs_offset;
>> +	int clut_offset;
>>  	struct atmel_hlcdc_formats *formats;
>>  	struct atmel_hlcdc_layer_cfg_layout layout;
>>  	int max_width;
>> @@ -414,6 +422,14 @@ static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer,
>>  					  (cfgid * sizeof(u32)));
>>  }
>>  
>> +static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer,
>> +						unsigned int c, u32 val)
>> +{
>> +	atmel_hlcdc_layer_write_reg(layer,
>> +				    layer->desc->clut_offset + c * sizeof(u32),
>> +				    val);
>> +}
>> +
>>  static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
>>  				const struct atmel_hlcdc_layer_desc *desc,
>>  				struct regmap *regmap)
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
>> index 1124200..b5bd9b0 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
>> @@ -83,6 +83,7 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
>>  #define SUBPIXEL_MASK			0xffff
>>  
>>  static uint32_t rgb_formats[] = {
>> +	DRM_FORMAT_C8,
>>  	DRM_FORMAT_XRGB4444,
>>  	DRM_FORMAT_ARGB4444,
>>  	DRM_FORMAT_RGBA4444,
>> @@ -100,6 +101,7 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
>>  };
>>  
>>  static uint32_t rgb_and_yuv_formats[] = {
>> +	DRM_FORMAT_C8,
>>  	DRM_FORMAT_XRGB4444,
>>  	DRM_FORMAT_ARGB4444,
>>  	DRM_FORMAT_RGBA4444,
>> @@ -128,6 +130,9 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
>>  static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
>>  {
>>  	switch (format) {
>> +	case DRM_FORMAT_C8:
>> +		*mode = ATMEL_HLCDC_C8_MODE;
>> +		break;
>>  	case DRM_FORMAT_XRGB4444:
>>  		*mode = ATMEL_HLCDC_XRGB4444_MODE;
>>  		break;
>> @@ -424,6 +429,29 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
>>  				    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
>>  }
>>  
>> +static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane)
>> +{
>> +	struct drm_crtc *crtc = plane->base.crtc;
>> +	struct drm_color_lut *lut;
>> +	int idx;
>> +
>> +	if (!crtc || !crtc->state)
>> +		return;
>> +
>> +	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
>> +		return;
>> +
>> +	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
>> +
>> +	for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
>> +		u32 val = ((lut->red << 8) & 0xff0000) |
>> +			(lut->green & 0xff00) |
>> +			(lut->blue >> 8);
>> +
>> +		atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
>> +	}
>> +}
>> +
>>  static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
>>  					struct atmel_hlcdc_plane_state *state)
>>  {
>> @@ -768,6 +796,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
>>  	atmel_hlcdc_plane_update_pos_and_size(plane, state);
>>  	atmel_hlcdc_plane_update_general_settings(plane, state);
>>  	atmel_hlcdc_plane_update_format(plane, state);
>> +	atmel_hlcdc_plane_update_clut(plane);
>>  	atmel_hlcdc_plane_update_buffers(plane, state);
>>  	atmel_hlcdc_plane_update_disc_area(plane, state);
>>  
>> -- 
>> 2.1.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
Daniel Vetter June 21, 2017, 7:04 a.m. UTC | #3
On Tue, Jun 20, 2017 at 11:55:01AM +0200, Peter Rosin wrote:
> On 2017-06-20 11:40, Daniel Vetter wrote:
> > On Sat, Jun 17, 2017 at 07:48:02PM +0200, Peter Rosin wrote:
> >> All layers of all supported chips support this, the only variable is the
> >> base address of the lookup table in the register map.
> >>
> >> Signed-off-by: Peter Rosin <peda@axentia.se>
> > 
> > As Boris said, pls use the new color manager stuff for atomic drivers, and
> > then use the helper to implement the legacy kms LUT support on top of it,
> > it's drm_atomic_helper_legacy_gamma_set().
> > -Daniel
> 
> Hmm, I don't see how this comment applies to this patch? Isn't this
> patch good as is, because I thought I already did wire this up with
> the drm_atomic_helper_legacy_gamma_set helper as requested?
> (sure, v3 has a register offset tweak, but that's just a detail)
> 
> I totally agree that 2/3 and 3/3 are ugly and I am working on that, but
> if 1/3 is also not in the right direction I'd like to know ASAP. Thanks!

Sorry, I must have mixed up your patches. This one here indeed looks like
it does things properly. For this one here:

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Cheers, Daniel

> 
> Cheers,
> peda
> 
> > 
> >> ---
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c  |  5 +++++
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c    | 13 +++++++++++
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h    | 16 ++++++++++++++
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 29 +++++++++++++++++++++++++
> >>  4 files changed, 63 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> >> index 5348985..694adcc 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
> >> @@ -429,6 +429,8 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
> >>  	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
> >>  	.enable_vblank = atmel_hlcdc_crtc_enable_vblank,
> >>  	.disable_vblank = atmel_hlcdc_crtc_disable_vblank,
> >> +	.set_property = drm_atomic_helper_crtc_set_property,
> >> +	.gamma_set = drm_atomic_helper_legacy_gamma_set,
> >>  };
> >>  
> >>  int atmel_hlcdc_crtc_create(struct drm_device *dev)
> >> @@ -484,6 +486,9 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
> >>  	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
> >>  	drm_crtc_vblank_reset(&crtc->base);
> >>  
> >> +	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
> >> +	drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE);
> >> +
> >>  	dc->crtc = &crtc->base;
> >>  
> >>  	return 0;
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> index 30dbffd..4f6ef07 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> @@ -42,6 +42,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = {
> >>  			.default_color = 3,
> >>  			.general_config = 4,
> >>  		},
> >> +		.clut_offset = 0x400,
> >>  	},
> >>  };
> >>  
> >> @@ -73,6 +74,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
> >>  			.disc_pos = 5,
> >>  			.disc_size = 6,
> >>  		},
> >> +		.clut_offset = 0x400,
> >>  	},
> >>  	{
> >>  		.name = "overlay1",
> >> @@ -91,6 +93,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
> >>  			.chroma_key_mask = 8,
> >>  			.general_config = 9,
> >>  		},
> >> +		.clut_offset = 0x800,
> >>  	},
> >>  	{
> >>  		.name = "high-end-overlay",
> >> @@ -112,6 +115,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
> >>  			.scaler_config = 13,
> >>  			.csc = 14,
> >>  		},
> >> +		.clut_offset = 0x1000,
> >>  	},
> >>  	{
> >>  		.name = "cursor",
> >> @@ -131,6 +135,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
> >>  			.chroma_key_mask = 8,
> >>  			.general_config = 9,
> >>  		},
> >> +		.clut_offset = 0x1400,
> >>  	},
> >>  };
> >>  
> >> @@ -162,6 +167,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
> >>  			.disc_pos = 5,
> >>  			.disc_size = 6,
> >>  		},
> >> +		.clut_offset = 0x600,
> >>  	},
> >>  	{
> >>  		.name = "overlay1",
> >> @@ -180,6 +186,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
> >>  			.chroma_key_mask = 8,
> >>  			.general_config = 9,
> >>  		},
> >> +		.clut_offset = 0xa00,
> >>  	},
> >>  	{
> >>  		.name = "overlay2",
> >> @@ -198,6 +205,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
> >>  			.chroma_key_mask = 8,
> >>  			.general_config = 9,
> >>  		},
> >> +		.clut_offset = 0xe00,
> >>  	},
> >>  	{
> >>  		.name = "high-end-overlay",
> >> @@ -223,6 +231,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
> >>  			},
> >>  			.csc = 14,
> >>  		},
> >> +		.clut_offset = 0x1200,
> >>  	},
> >>  	{
> >>  		.name = "cursor",
> >> @@ -244,6 +253,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
> >>  			.general_config = 9,
> >>  			.scaler_config = 13,
> >>  		},
> >> +		.clut_offset = 0x1600,
> >>  	},
> >>  };
> >>  
> >> @@ -275,6 +285,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
> >>  			.disc_pos = 5,
> >>  			.disc_size = 6,
> >>  		},
> >> +		.clut_offset = 0x600,
> >>  	},
> >>  	{
> >>  		.name = "overlay1",
> >> @@ -293,6 +304,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
> >>  			.chroma_key_mask = 8,
> >>  			.general_config = 9,
> >>  		},
> >> +		.clut_offset = 0xa00,
> >>  	},
> >>  	{
> >>  		.name = "overlay2",
> >> @@ -336,6 +348,7 @@ static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
> >>  			},
> >>  			.csc = 14,
> >>  		},
> >> +		.clut_offset = 0x1200,
> >>  	},
> >>  };
> >>  
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> >> index b0596a8..709f7b9 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
> >> @@ -88,6 +88,11 @@
> >>  #define ATMEL_HLCDC_YUV422SWP			BIT(17)
> >>  #define ATMEL_HLCDC_DSCALEOPT			BIT(20)
> >>  
> >> +#define ATMEL_HLCDC_C1_MODE			ATMEL_HLCDC_CLUT_MODE(0)
> >> +#define ATMEL_HLCDC_C2_MODE			ATMEL_HLCDC_CLUT_MODE(1)
> >> +#define ATMEL_HLCDC_C4_MODE			ATMEL_HLCDC_CLUT_MODE(2)
> >> +#define ATMEL_HLCDC_C8_MODE			ATMEL_HLCDC_CLUT_MODE(3)
> >> +
> >>  #define ATMEL_HLCDC_XRGB4444_MODE		ATMEL_HLCDC_RGB_MODE(0)
> >>  #define ATMEL_HLCDC_ARGB4444_MODE		ATMEL_HLCDC_RGB_MODE(1)
> >>  #define ATMEL_HLCDC_RGBA4444_MODE		ATMEL_HLCDC_RGB_MODE(2)
> >> @@ -142,6 +147,8 @@
> >>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE	BIT(2)
> >>  #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN	BIT(3)
> >>  
> >> +#define ATMEL_HLCDC_CLUT_SIZE			256
> >> +
> >>  #define ATMEL_HLCDC_MAX_LAYERS			6
> >>  
> >>  /**
> >> @@ -259,6 +266,7 @@ struct atmel_hlcdc_layer_desc {
> >>  	int id;
> >>  	int regs_offset;
> >>  	int cfgs_offset;
> >> +	int clut_offset;
> >>  	struct atmel_hlcdc_formats *formats;
> >>  	struct atmel_hlcdc_layer_cfg_layout layout;
> >>  	int max_width;
> >> @@ -414,6 +422,14 @@ static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer,
> >>  					  (cfgid * sizeof(u32)));
> >>  }
> >>  
> >> +static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer,
> >> +						unsigned int c, u32 val)
> >> +{
> >> +	atmel_hlcdc_layer_write_reg(layer,
> >> +				    layer->desc->clut_offset + c * sizeof(u32),
> >> +				    val);
> >> +}
> >> +
> >>  static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
> >>  				const struct atmel_hlcdc_layer_desc *desc,
> >>  				struct regmap *regmap)
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> >> index 1124200..b5bd9b0 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
> >> @@ -83,6 +83,7 @@ drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
> >>  #define SUBPIXEL_MASK			0xffff
> >>  
> >>  static uint32_t rgb_formats[] = {
> >> +	DRM_FORMAT_C8,
> >>  	DRM_FORMAT_XRGB4444,
> >>  	DRM_FORMAT_ARGB4444,
> >>  	DRM_FORMAT_RGBA4444,
> >> @@ -100,6 +101,7 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
> >>  };
> >>  
> >>  static uint32_t rgb_and_yuv_formats[] = {
> >> +	DRM_FORMAT_C8,
> >>  	DRM_FORMAT_XRGB4444,
> >>  	DRM_FORMAT_ARGB4444,
> >>  	DRM_FORMAT_RGBA4444,
> >> @@ -128,6 +130,9 @@ struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
> >>  static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
> >>  {
> >>  	switch (format) {
> >> +	case DRM_FORMAT_C8:
> >> +		*mode = ATMEL_HLCDC_C8_MODE;
> >> +		break;
> >>  	case DRM_FORMAT_XRGB4444:
> >>  		*mode = ATMEL_HLCDC_XRGB4444_MODE;
> >>  		break;
> >> @@ -424,6 +429,29 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
> >>  				    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
> >>  }
> >>  
> >> +static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane)
> >> +{
> >> +	struct drm_crtc *crtc = plane->base.crtc;
> >> +	struct drm_color_lut *lut;
> >> +	int idx;
> >> +
> >> +	if (!crtc || !crtc->state)
> >> +		return;
> >> +
> >> +	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
> >> +		return;
> >> +
> >> +	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
> >> +
> >> +	for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
> >> +		u32 val = ((lut->red << 8) & 0xff0000) |
> >> +			(lut->green & 0xff00) |
> >> +			(lut->blue >> 8);
> >> +
> >> +		atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
> >> +	}
> >> +}
> >> +
> >>  static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
> >>  					struct atmel_hlcdc_plane_state *state)
> >>  {
> >> @@ -768,6 +796,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
> >>  	atmel_hlcdc_plane_update_pos_and_size(plane, state);
> >>  	atmel_hlcdc_plane_update_general_settings(plane, state);
> >>  	atmel_hlcdc_plane_update_format(plane, state);
> >> +	atmel_hlcdc_plane_update_clut(plane);
> >>  	atmel_hlcdc_plane_update_buffers(plane, state);
> >>  	atmel_hlcdc_plane_update_disc_area(plane, state);
> >>  
> >> -- 
> >> 2.1.4
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> > 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 5348985..694adcc 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -429,6 +429,8 @@  static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
 	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
 	.enable_vblank = atmel_hlcdc_crtc_enable_vblank,
 	.disable_vblank = atmel_hlcdc_crtc_disable_vblank,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.gamma_set = drm_atomic_helper_legacy_gamma_set,
 };
 
 int atmel_hlcdc_crtc_create(struct drm_device *dev)
@@ -484,6 +486,9 @@  int atmel_hlcdc_crtc_create(struct drm_device *dev)
 	drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
 	drm_crtc_vblank_reset(&crtc->base);
 
+	drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
+	drm_crtc_enable_color_mgmt(&crtc->base, 0, false, ATMEL_HLCDC_CLUT_SIZE);
+
 	dc->crtc = &crtc->base;
 
 	return 0;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 30dbffd..4f6ef07 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -42,6 +42,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9n12_layers[] = {
 			.default_color = 3,
 			.general_config = 4,
 		},
+		.clut_offset = 0x400,
 	},
 };
 
@@ -73,6 +74,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
 			.disc_pos = 5,
 			.disc_size = 6,
 		},
+		.clut_offset = 0x400,
 	},
 	{
 		.name = "overlay1",
@@ -91,6 +93,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
 			.chroma_key_mask = 8,
 			.general_config = 9,
 		},
+		.clut_offset = 0x800,
 	},
 	{
 		.name = "high-end-overlay",
@@ -112,6 +115,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
 			.scaler_config = 13,
 			.csc = 14,
 		},
+		.clut_offset = 0x1000,
 	},
 	{
 		.name = "cursor",
@@ -131,6 +135,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
 			.chroma_key_mask = 8,
 			.general_config = 9,
 		},
+		.clut_offset = 0x1400,
 	},
 };
 
@@ -162,6 +167,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
 			.disc_pos = 5,
 			.disc_size = 6,
 		},
+		.clut_offset = 0x600,
 	},
 	{
 		.name = "overlay1",
@@ -180,6 +186,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
 			.chroma_key_mask = 8,
 			.general_config = 9,
 		},
+		.clut_offset = 0xa00,
 	},
 	{
 		.name = "overlay2",
@@ -198,6 +205,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
 			.chroma_key_mask = 8,
 			.general_config = 9,
 		},
+		.clut_offset = 0xe00,
 	},
 	{
 		.name = "high-end-overlay",
@@ -223,6 +231,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
 			},
 			.csc = 14,
 		},
+		.clut_offset = 0x1200,
 	},
 	{
 		.name = "cursor",
@@ -244,6 +253,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
 			.general_config = 9,
 			.scaler_config = 13,
 		},
+		.clut_offset = 0x1600,
 	},
 };
 
@@ -275,6 +285,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
 			.disc_pos = 5,
 			.disc_size = 6,
 		},
+		.clut_offset = 0x600,
 	},
 	{
 		.name = "overlay1",
@@ -293,6 +304,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
 			.chroma_key_mask = 8,
 			.general_config = 9,
 		},
+		.clut_offset = 0xa00,
 	},
 	{
 		.name = "overlay2",
@@ -336,6 +348,7 @@  static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
 			},
 			.csc = 14,
 		},
+		.clut_offset = 0x1200,
 	},
 };
 
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index b0596a8..709f7b9 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -88,6 +88,11 @@ 
 #define ATMEL_HLCDC_YUV422SWP			BIT(17)
 #define ATMEL_HLCDC_DSCALEOPT			BIT(20)
 
+#define ATMEL_HLCDC_C1_MODE			ATMEL_HLCDC_CLUT_MODE(0)
+#define ATMEL_HLCDC_C2_MODE			ATMEL_HLCDC_CLUT_MODE(1)
+#define ATMEL_HLCDC_C4_MODE			ATMEL_HLCDC_CLUT_MODE(2)
+#define ATMEL_HLCDC_C8_MODE			ATMEL_HLCDC_CLUT_MODE(3)
+
 #define ATMEL_HLCDC_XRGB4444_MODE		ATMEL_HLCDC_RGB_MODE(0)
 #define ATMEL_HLCDC_ARGB4444_MODE		ATMEL_HLCDC_RGB_MODE(1)
 #define ATMEL_HLCDC_RGBA4444_MODE		ATMEL_HLCDC_RGB_MODE(2)
@@ -142,6 +147,8 @@ 
 #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_DONE	BIT(2)
 #define ATMEL_HLCDC_DMA_CHANNEL_DSCR_OVERRUN	BIT(3)
 
+#define ATMEL_HLCDC_CLUT_SIZE			256
+
 #define ATMEL_HLCDC_MAX_LAYERS			6
 
 /**
@@ -259,6 +266,7 @@  struct atmel_hlcdc_layer_desc {
 	int id;
 	int regs_offset;
 	int cfgs_offset;
+	int clut_offset;
 	struct atmel_hlcdc_formats *formats;
 	struct atmel_hlcdc_layer_cfg_layout layout;
 	int max_width;
@@ -414,6 +422,14 @@  static inline u32 atmel_hlcdc_layer_read_cfg(struct atmel_hlcdc_layer *layer,
 					  (cfgid * sizeof(u32)));
 }
 
+static inline void atmel_hlcdc_layer_write_clut(struct atmel_hlcdc_layer *layer,
+						unsigned int c, u32 val)
+{
+	atmel_hlcdc_layer_write_reg(layer,
+				    layer->desc->clut_offset + c * sizeof(u32),
+				    val);
+}
+
 static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
 				const struct atmel_hlcdc_layer_desc *desc,
 				struct regmap *regmap)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 1124200..b5bd9b0 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -83,6 +83,7 @@  drm_plane_state_to_atmel_hlcdc_plane_state(struct drm_plane_state *s)
 #define SUBPIXEL_MASK			0xffff
 
 static uint32_t rgb_formats[] = {
+	DRM_FORMAT_C8,
 	DRM_FORMAT_XRGB4444,
 	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_RGBA4444,
@@ -100,6 +101,7 @@  struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats = {
 };
 
 static uint32_t rgb_and_yuv_formats[] = {
+	DRM_FORMAT_C8,
 	DRM_FORMAT_XRGB4444,
 	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_RGBA4444,
@@ -128,6 +130,9 @@  struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_and_yuv_formats = {
 static int atmel_hlcdc_format_to_plane_mode(u32 format, u32 *mode)
 {
 	switch (format) {
+	case DRM_FORMAT_C8:
+		*mode = ATMEL_HLCDC_C8_MODE;
+		break;
 	case DRM_FORMAT_XRGB4444:
 		*mode = ATMEL_HLCDC_XRGB4444_MODE;
 		break;
@@ -424,6 +429,29 @@  static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
 				    ATMEL_HLCDC_LAYER_FORMAT_CFG, cfg);
 }
 
+static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane)
+{
+	struct drm_crtc *crtc = plane->base.crtc;
+	struct drm_color_lut *lut;
+	int idx;
+
+	if (!crtc || !crtc->state)
+		return;
+
+	if (!crtc->state->color_mgmt_changed || !crtc->state->gamma_lut)
+		return;
+
+	lut = (struct drm_color_lut *)crtc->state->gamma_lut->data;
+
+	for (idx = 0; idx < ATMEL_HLCDC_CLUT_SIZE; idx++, lut++) {
+		u32 val = ((lut->red << 8) & 0xff0000) |
+			(lut->green & 0xff00) |
+			(lut->blue >> 8);
+
+		atmel_hlcdc_layer_write_clut(&plane->layer, idx, val);
+	}
+}
+
 static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
 					struct atmel_hlcdc_plane_state *state)
 {
@@ -768,6 +796,7 @@  static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
 	atmel_hlcdc_plane_update_pos_and_size(plane, state);
 	atmel_hlcdc_plane_update_general_settings(plane, state);
 	atmel_hlcdc_plane_update_format(plane, state);
+	atmel_hlcdc_plane_update_clut(plane);
 	atmel_hlcdc_plane_update_buffers(plane, state);
 	atmel_hlcdc_plane_update_disc_area(plane, state);