Add support for atomic update of gamma lut. With this patch the "Night light" feature of gnome3 is working properly on mgag200. Signed-off-by: Jocelyn Falempe <jfalempe@xxxxxxxxxx> --- drivers/gpu/drm/mgag200/mgag200_mode.c | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 6e18d3bbd720..9fc688e15db8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -86,6 +86,46 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) } } +static void mga_crtc_update_lut(struct mga_device *mdev, + struct drm_crtc_state *state, + u8 depth) +{ + struct drm_color_lut * lut; + int i; + + if (!state->color_mgmt_changed || !state->gamma_lut) + return + + lut = (struct drm_color_lut *) state->gamma_lut->data; + WREG8(DAC_INDEX + MGA1064_INDEX, 0); + + if (depth == 15) { + /* 16 bits r5g5b5a1 */ + for (i = 0; i < MGAG200_LUT_SIZE; i += 8) { + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].red >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].green >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].blue >> 8); + } + } else if (depth == 16) { + /* 16 bits r5g6b5, as green has one more bit, + * add padding with 0 for red and blue. */ + for (i = 0; i < MGAG200_LUT_SIZE; i += 4) { + u8 red = 2 * i < MGAG200_LUT_SIZE ? lut[2 * i].red >> 8 : 0; + u8 blue = 2 * i < MGAG200_LUT_SIZE ? lut[2 * i].red >> 8 : 0; + WREG8(DAC_INDEX + MGA1064_COL_PAL, red); + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].green >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, blue); + } + } else { + /* 24 bits r8g8b8 */ + for (i = 0; i < MGAG200_LUT_SIZE; i++) { + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].red >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].green >> 8); + WREG8(DAC_INDEX + MGA1064_COL_PAL, lut[i].blue >> 8); + } + } +} + static inline void mga_wait_vsync(struct mga_device *mdev) { unsigned long timeout = jiffies + HZ/10; @@ -953,6 +993,7 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state) { struct drm_plane *plane = &pipe->plane; + struct drm_crtc *crtc = &pipe->crtc; struct drm_device *dev = plane->dev; struct mga_device *mdev = to_mga_device(dev); struct drm_plane_state *state = plane->state; @@ -963,7 +1004,10 @@ mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe, if (!fb) return; + mga_crtc_update_lut(mdev, crtc->state, fb->format->depth); + if (drm_atomic_helper_damage_merged(old_state, state, &damage)) + mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]); } @@ -1110,6 +1154,8 @@ int mgag200_modeset_init(struct mga_device *mdev) /* FIXME: legacy gamma tables; convert to CRTC state */ drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE); + drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE); + drm_mode_config_reset(dev); return 0; -- 2.35.3