Replace vesadrm's code for programming the hardware gamma LUT with DRM helpers. Either load a provided gamma ramp or program a default. Set the individual entries with a callback.
Each gamma value is given as 3 individual 16-bit values for red, green and blue. The driver reduces them to 8 bit to make them fit into hardware registers. Signed-off-by: Thomas Zimmermann <tzimmerm...@suse.de> Reviewed-by: Javier Martinez Canillas <javi...@redhat.com> --- drivers/gpu/drm/sysfb/vesadrm.c | 100 ++++++++++++-------------------- 1 file changed, 36 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c index 4d62c78e7d1e..7945544ba73e 100644 --- a/drivers/gpu/drm/sysfb/vesadrm.c +++ b/drivers/gpu/drm/sysfb/vesadrm.c @@ -9,6 +9,7 @@ #include <drm/clients/drm_client_setup.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_state_helper.h> +#include <drm/drm_color_mgmt.h> #include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> @@ -87,15 +88,10 @@ static struct vesadrm_device *to_vesadrm_device(struct drm_device *dev) static void vesadrm_vga_cmap_write(struct vesadrm_device *vesa, unsigned int index, u16 red, u16 green, u16 blue) { - u8 i8, r8, g8, b8; - - if (index > 255) - return; - - i8 = index; - r8 = red >> 8; - g8 = green >> 8; - b8 = blue >> 8; + u8 i8 = index; + u8 r8 = red >> 8; + u8 g8 = green >> 8; + u8 b8 = blue >> 8; outb_p(i8, VGA_PEL_IW); outb_p(r8, VGA_PEL_D); @@ -120,9 +116,6 @@ static void vesadrm_pmi_cmap_write(struct vesadrm_device *vesa, unsigned int ind 0x00, }; - if (index > 255) - return; - __asm__ __volatile__ ( "call *(%%esi)" : /* no return value */ @@ -135,43 +128,36 @@ static void vesadrm_pmi_cmap_write(struct vesadrm_device *vesa, unsigned int ind } #endif -static void vesadrm_set_gamma_linear(struct vesadrm_device *vesa, - const struct drm_format_info *format) +static void vesadrm_set_gamma_lut(struct drm_crtc *crtc, unsigned int index, + u16 red, u16 green, u16 blue) +{ + struct drm_device *dev = crtc->dev; + struct vesadrm_device *vesa = to_vesadrm_device(dev); + u8 i8 = index & 0xff; + + if (drm_WARN_ON_ONCE(dev, index != i8)) + return; /* driver bug */ + + vesa->cmap_write(vesa, i8, red, green, blue); +} + +static void vesadrm_fill_gamma_lut(struct vesadrm_device *vesa, + const struct drm_format_info *format) { struct drm_device *dev = &vesa->sysfb.dev; - size_t i; - u16 r16, g16, b16; + struct drm_crtc *crtc = &vesa->crtc; switch (format->format) { case DRM_FORMAT_XRGB1555: - for (i = 0; i < 32; ++i) { - r16 = i * 8 + i / 4; - r16 |= (r16 << 8) | r16; - vesa->cmap_write(vesa, i, r16, r16, r16); - } + drm_crtc_fill_gamma_555(crtc, vesadrm_set_gamma_lut); break; case DRM_FORMAT_RGB565: - for (i = 0; i < 32; ++i) { - r16 = i * 8 + i / 4; - r16 |= (r16 << 8) | r16; - g16 = i * 4 + i / 16; - g16 |= (g16 << 8) | g16; - b16 = r16; - vesa->cmap_write(vesa, i, r16, g16, b16); - } - for (i = 32; i < 64; ++i) { - g16 = i * 4 + i / 16; - g16 |= (g16 << 8) | g16; - vesa->cmap_write(vesa, i, 0, g16, 0); - } + drm_crtc_fill_gamma_565(crtc, vesadrm_set_gamma_lut); break; case DRM_FORMAT_RGB888: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_BGRX8888: - for (i = 0; i < 256; ++i) { - r16 = (i << 8) | i; - vesa->cmap_write(vesa, i, r16, r16, r16); - } + drm_crtc_fill_gamma_888(crtc, vesadrm_set_gamma_lut); break; default: drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n", @@ -180,38 +166,24 @@ static void vesadrm_set_gamma_linear(struct vesadrm_device *vesa, } } -static void vesadrm_set_gamma_lut(struct vesadrm_device *vesa, - const struct drm_format_info *format, - struct drm_color_lut *lut) +static void vesadrm_load_gamma_lut(struct vesadrm_device *vesa, + const struct drm_format_info *format, + struct drm_color_lut *lut) { struct drm_device *dev = &vesa->sysfb.dev; - size_t i; - u16 r16, g16, b16; + struct drm_crtc *crtc = &vesa->crtc; switch (format->format) { case DRM_FORMAT_XRGB1555: - for (i = 0; i < 32; ++i) { - r16 = lut[i * 8 + i / 4].red; - g16 = lut[i * 8 + i / 4].green; - b16 = lut[i * 8 + i / 4].blue; - vesa->cmap_write(vesa, i, r16, g16, b16); - } + drm_crtc_load_gamma_555_from_888(crtc, lut, vesadrm_set_gamma_lut); break; case DRM_FORMAT_RGB565: - for (i = 0; i < 32; ++i) { - r16 = lut[i * 8 + i / 4].red; - g16 = lut[i * 4 + i / 16].green; - b16 = lut[i * 8 + i / 4].blue; - vesa->cmap_write(vesa, i, r16, g16, b16); - } - for (i = 32; i < 64; ++i) - vesa->cmap_write(vesa, i, 0, lut[i * 4 + i / 16].green, 0); + drm_crtc_load_gamma_565_from_888(crtc, lut, vesadrm_set_gamma_lut); break; case DRM_FORMAT_RGB888: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_BGRX8888: - for (i = 0; i < 256; ++i) - vesa->cmap_write(vesa, i, lut[i].red, lut[i].green, lut[i].blue); + drm_crtc_load_gamma_888(crtc, lut, vesadrm_set_gamma_lut); break; default: drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n", @@ -253,13 +225,13 @@ static void vesadrm_crtc_helper_atomic_flush(struct drm_crtc *crtc, if (crtc_state->enable && crtc_state->color_mgmt_changed) { if (sysfb_crtc_state->format == sysfb->fb_format) { if (crtc_state->gamma_lut) - vesadrm_set_gamma_lut(vesa, - sysfb_crtc_state->format, - crtc_state->gamma_lut->data); + vesadrm_load_gamma_lut(vesa, + sysfb_crtc_state->format, + crtc_state->gamma_lut->data); else - vesadrm_set_gamma_linear(vesa, sysfb_crtc_state->format); + vesadrm_fill_gamma_lut(vesa, sysfb_crtc_state->format); } else { - vesadrm_set_gamma_linear(vesa, sysfb_crtc_state->format); + vesadrm_fill_gamma_lut(vesa, sysfb_crtc_state->format); } } } -- 2.49.0