dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Jocelyn Falempe <jfalempe@redhat.com>
To: Thomas Zimmermann <tzimmermann@suse.de>,
	javierm@redhat.com, airlied@redhat.com, simona@ffwll.ch,
	airlied@gmail.com, maarten.lankhorst@linux.intel.com,
	mripard@kernel.org
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 1/5] drm: Add helpers for programming hardware gamma LUTs
Date: Mon, 12 May 2025 15:31:21 +0200	[thread overview]
Message-ID: <61e26230-e1c2-449c-965a-1f84ede0ac2e@redhat.com> (raw)
In-Reply-To: <20250509083911.39018-2-tzimmermann@suse.de>

On 09/05/2025 10:23, Thomas Zimmermann wrote:
> Provide helpers that program hardware gamma LUTs. Tha gamma ramp is
> either provided by the driver or generated by the helper.
> 
> The DRM driver exports the GAMMA_LUT property with a fixed number of
> entries per color component, such as 256 on 8-bit-wide components. The
> entries describe the gamma ramp of each individual component. The new
> helper drm_crtc_load_gamma_888() loads such gamma ramp to hardware. The
> hardware uses each displayed pixel's individial components as indeces
> into the hardware gamma table.
> 
> For color modes with less than 8 bits per color component, the helpers
> drm_crtc_load_gamma_565_from() and drm_crtc_load_gamma_555_from_888()
> interpolate the provided gamma ramp to reduce it to the correct number
> of entries; 5/6/5 for RGB565-like formats and 5/5/5 for RGB1555-like
> formats.
> 
> If no gamma ramp has been provided, drivers can use the new helper
> drm_crtc_fill_gamma_888() to load a default gamma ramp with 256 entries
> per color component. For color modes with less bits, the new helpers
> drm_crtc_fill_gamma_565() and drm_crtc_fill_gamma_555() are available.
> The default gamma ramp uses a gamma factor of 1. Later patches can
> change this. For PCs, a gamma factor of 2.2 is common.
> 
> For color modes with palette, drm_crtc_load_palette_8() load an 8-bit
> palette into the hardware. If no palette has been specified,
> drm_crtc_fill_palette_8() load a system-specific default palette. This
> is currently only a grey-scale palette with increasing luminance, but
> later patches can change this. For PCs, a VGA default palette could
> be used.

Thanks for this work. I've one comment below regarding the 
drm_crtc_set_lut_func prototype.
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
>   drivers/gpu/drm/drm_color_mgmt.c | 206 +++++++++++++++++++++++++++++++
>   include/drm/drm_color_mgmt.h     |  27 ++++
>   2 files changed, 233 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
> index 3969dc548cff..dd3e06605180 100644
> --- a/drivers/gpu/drm/drm_color_mgmt.c
> +++ b/drivers/gpu/drm/drm_color_mgmt.c
> @@ -630,3 +630,209 @@ int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests)
>   	return 0;
>   }
>   EXPORT_SYMBOL(drm_color_lut_check);
> +
> +/*
> + * Gamma-LUT programming
> + */
> +
> +/**
> + * drm_crtc_load_gamma_888 - Programs gamma ramp for RGB888-like formats
> + * @crtc: The displaying CRTC
> + * @lut: The gamma ramp to program
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs the gamma ramp specified in @lut to hardware. The input gamma
> + * ramp must have 256 entries per color component.
> + */
> +void drm_crtc_load_gamma_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +			     drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 256; ++i)
> +		set_gamma(crtc, i, lut[i].red, lut[i].green, lut[i].blue);
> +}
> +EXPORT_SYMBOL(drm_crtc_load_gamma_888);
> +
> +/**
> + * drm_crtc_load_gamma_565_from_888 - Programs gamma ramp for RGB565-like formats
> + * @crtc: The displaying CRTC
> + * @lut: The gamma ramp to program
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs the gamma ramp specified in @lut to hardware. The input gamma
> + * ramp must have 256 entries per color component. The helper interpolates
> + * the individual color components to reduce the number of entries to 5/6/5.
> + */
> +void drm_crtc_load_gamma_565_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +				      drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +	u16 r, g, b;
> +
> +	for (i = 0; i < 32; ++i) {
> +		r = lut[i * 8 + i / 4].red;
> +		g = lut[i * 4 + i / 16].green;
> +		b = lut[i * 8 + i / 4].blue;
> +		set_gamma(crtc, i, r, g, b);
> +	}
> +	/* Green has one more bit, so add padding with 0 for red and blue. */
> +	for (i = 32; i < 64; ++i) {
> +		g = lut[i * 4 + i / 16].green;
> +		set_gamma(crtc, i, 0, g, 0);
> +	}
> +}
> +EXPORT_SYMBOL(drm_crtc_load_gamma_565_from_888);
> +
> +/**
> + * drm_crtc_load_gamma_555_from_888 - Programs gamma ramp for RGB555-like formats
> + * @crtc: The displaying CRTC
> + * @lut: The gamma ramp to program
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs the gamma ramp specified in @lut to hardware. The input gamma
> + * ramp must have 256 entries per color component. The helper interpolates
> + * the individual color components to reduce the number of entries to 5/5/5.
> + */
> +void drm_crtc_load_gamma_555_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +				      drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +	u16 r, g, b;
> +
> +	for (i = 0; i < 32; ++i) {
> +		r = lut[i * 8 + i / 4].red;
> +		g = lut[i * 8 + i / 4].green;
> +		b = lut[i * 8 + i / 4].blue;
> +		set_gamma(crtc, i, r, g, b);
> +	}
> +}
> +EXPORT_SYMBOL(drm_crtc_load_gamma_555_from_888);
> +
> +static void fill_gamma_888(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b,
> +			   drm_crtc_set_lut_func set_gamma)
> +{
> +	r = (r << 8) | r;
> +	g = (g << 8) | g;
> +	b = (b << 8) | b;
> +
> +	set_gamma(crtc, i, r, g, b);
> +}
> +
> +/**
> + * drm_crtc_fill_gamma_888 - Programs a default gamma ramp for RGB888-like formats
> + * @crtc: The displaying CRTC
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs a default gamma ramp to hardware.
> + */
> +void drm_crtc_fill_gamma_888(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 256; ++i)
> +		fill_gamma_888(crtc, i, i, i, i, set_gamma);
> +}
> +EXPORT_SYMBOL(drm_crtc_fill_gamma_888);
> +
> +static void fill_gamma_565(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b,
> +			   drm_crtc_set_lut_func set_gamma)
> +{
> +	r = (r << 11) | (r << 6) | (r << 1) | (r >> 4);
> +	g = (g << 10) | (g << 4) | (g >> 2);
> +	b = (b << 11) | (b << 6) | (b << 1) | (b >> 4);
> +
> +	set_gamma(crtc, i, r, g, b);
> +}
> +
> +/**
> + * drm_crtc_fill_gamma_565 - Programs a default gamma ramp for RGB565-like formats
> + * @crtc: The displaying CRTC
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs a default gamma ramp to hardware.
> + */
> +void drm_crtc_fill_gamma_565(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 32; ++i)
> +		fill_gamma_565(crtc, i, i, i, i, set_gamma);
> +	/* Green has one more bit, so add padding with 0 for red and blue. */
> +	for (i = 32; i < 64; ++i)
> +		fill_gamma_565(crtc, i, 0, i, 0, set_gamma);
> +}
> +EXPORT_SYMBOL(drm_crtc_fill_gamma_565);
> +
> +static void fill_gamma_555(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b,
> +			   drm_crtc_set_lut_func set_gamma)
> +{
> +	r = (r << 11) | (r << 6) | (r << 1) | (r >> 4);
> +	g = (g << 11) | (g << 6) | (g << 1) | (g >> 4);
> +	b = (b << 11) | (b << 6) | (b << 1) | (r >> 4);
> +
> +	set_gamma(crtc, i, r, g, b);
> +}
> +
> +/**
> + * drm_crtc_fill_gamma_555 - Programs a default gamma ramp for RGB555-like formats
> + * @crtc: The displaying CRTC
> + * @set_gamma: Callback for programming the hardware gamma LUT
> + *
> + * Programs a default gamma ramp to hardware.
> + */
> +void drm_crtc_fill_gamma_555(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 32; ++i)
> +		fill_gamma_555(crtc, i, i, i, i, set_gamma);
> +}
> +EXPORT_SYMBOL(drm_crtc_fill_gamma_555);
> +
> +/*
> + * Color-LUT programming
> + */
> +
> +/**
> + * drm_crtc_load_palette_8 - Programs palette for C8-like formats
> + * @crtc: The displaying CRTC
> + * @lut: The palette to program
> + * @set_palette: Callback for programming the hardware palette
> + *
> + * Programs the palette specified in @lut to hardware. The input palette
> + * must have 256 entries per color component.
> + */
> +void drm_crtc_load_palette_8(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +			     drm_crtc_set_lut_func set_palette)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 256; ++i)
> +		set_palette(crtc, i, lut[i].red, lut[i].green, lut[i].blue);
> +}
> +EXPORT_SYMBOL(drm_crtc_load_palette_8);
> +
> +static void fill_palette_8(struct drm_crtc *crtc, unsigned int i,
> +			   drm_crtc_set_lut_func set_palette)
> +{
> +	u16 Y = (i << 8) | i; // relative luminance
> +
> +	set_palette(crtc, i, Y, Y, Y);
> +}
> +
> +/**
> + * drm_crtc_fill_palette_8 - Programs a default palette for C8-like formats
> + * @crtc: The displaying CRTC
> + * @set_palette: Callback for programming the hardware gamma LUT
> + *
> + * Programs a default palette to hardware.
> + */
> +void drm_crtc_fill_palette_8(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < 256; ++i)
> +		fill_palette_8(crtc, i, set_palette);
> +}
> +EXPORT_SYMBOL(drm_crtc_fill_palette_8);
> diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
> index ed81741036d7..6cb577f6dba6 100644
> --- a/include/drm/drm_color_mgmt.h
> +++ b/include/drm/drm_color_mgmt.h
> @@ -118,4 +118,31 @@ enum drm_color_lut_tests {
>   };
>   
>   int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests);
> +
> +/*
> + * Gamma-LUT programming
> + */
> +
> +typedef void (*drm_crtc_set_lut_func)(struct drm_crtc *, unsigned int, u16, u16, u16);

All drivers using this code, have 256 LUT size, and use 8bits value.
So I would prefer to have it declared like this:
typedef void (*drm_crtc_set_lut_func)(struct drm_crtc *, u8, u8, u8, u8);

This will avoid to upcast from u8 to u16, and then from u16 to u8 in 
each driver.

> +
> +void drm_crtc_load_gamma_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +			     drm_crtc_set_lut_func set_gamma);
> +void drm_crtc_load_gamma_565_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +				      drm_crtc_set_lut_func set_gamma);
> +void drm_crtc_load_gamma_555_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +				      drm_crtc_set_lut_func set_gamma);
> +
> +void drm_crtc_fill_gamma_888(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma);
> +void drm_crtc_fill_gamma_565(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma);
> +void drm_crtc_fill_gamma_555(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma);
> +
> +/*
> + * Color-LUT programming
> + */
> +
> +void drm_crtc_load_palette_8(struct drm_crtc *crtc, const struct drm_color_lut *lut,
> +			     drm_crtc_set_lut_func set_palette);
> +
> +void drm_crtc_fill_palette_8(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette);
> +
>   #endif


Best regards,

-- 

Jocelyn


  reply	other threads:[~2025-05-12 13:31 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-09  8:23 [PATCH 0/5] drm: Provide helpers for programming gamma ramps and palettes Thomas Zimmermann
2025-05-09  8:23 ` [PATCH 1/5] drm: Add helpers for programming hardware gamma LUTs Thomas Zimmermann
2025-05-12 13:31   ` Jocelyn Falempe [this message]
2025-05-12 13:55     ` Thomas Zimmermann
2025-05-13 12:26   ` Jocelyn Falempe
2025-05-19 13:06   ` Javier Martinez Canillas
2025-05-09  8:23 ` [PATCH 2/5] drm/ast: Use helpers for programming gamma ramps and palettes Thomas Zimmermann
2025-05-13 12:26   ` Jocelyn Falempe
2025-05-09  8:23 ` [PATCH 3/5] drm/mgag200: Use helpers for programming gamma ramps Thomas Zimmermann
2025-05-13 12:27   ` Jocelyn Falempe
2025-05-09  8:23 ` [PATCH 4/5] drm/ofdrm: " Thomas Zimmermann
2025-05-19 13:16   ` Javier Martinez Canillas
2025-05-09  8:23 ` [PATCH 5/5] drm/vesadrm: " Thomas Zimmermann
2025-05-19 13:17   ` Javier Martinez Canillas
2025-05-12 11:48 ` [PATCH 0/5] drm: Provide helpers for programming gamma ramps and palettes Thomas Zimmermann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=61e26230-e1c2-449c-965a-1f84ede0ac2e@redhat.com \
    --to=jfalempe@redhat.com \
    --cc=airlied@gmail.com \
    --cc=airlied@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=javierm@redhat.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).