diff options
| author | Thomas Zimmermann <tzimmermann@suse.de> | 2025-05-20 11:40:03 +0200 |
|---|---|---|
| committer | Thomas Zimmermann <tzimmermann@suse.de> | 2025-05-26 09:18:12 +0200 |
| commit | e64693248f9054dee1283d67dc010eab8d172f23 (patch) | |
| tree | e08a7d04a178416109ac6e78fa42a05621081d48 /drivers/gpu | |
| parent | 2ea42f6e6868bc5a3d53e57a3af5b4d3d88c5dea (diff) | |
drm: Add helpers for programming hardware gamma LUTs
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 indices
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 XRGB1555-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.
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.
v2:
- drop comment on gamma factor of 2.2 (Michel, Pekka)
- fix typos in commit description (Javier)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Acked-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://lore.kernel.org/r/20250520094203.30545-2-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/drm_color_mgmt.c | 206 |
1 files changed, 206 insertions, 0 deletions
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); |
