Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: add legacy support for using degamma for gamma

The DRM core handles legacy gamma-set ioctl by setting GAMMA_LUT and
clearing CTM and DEGAMMA_LUT.

This works fine on HW where we have either:

degamma -> ctm -> gamma -> out

or

ctm -> gamma -> out

However, if the HW has gamma table before ctm, the atomic property
should be DEGAMMA_LUT, and thus we have:

degamma -> ctm -> out

This is fine for userspace which sets gamma table using the properties,
as the userspace can check for the existence of gamma & degamma, but the
legacy gamma-set ioctl does not work.

Change the DRM core to use DEGAMMA_LUT instead of GAMMA_LUT when the
latter is unavailable.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201211114237.213288-3-tomi.valkeinen@ti.com

+23 -4
+18 -4
drivers/gpu/drm/drm_color_mgmt.c
··· 91 91 * 92 92 * There is also support for a legacy gamma table, which is set up by calling 93 93 * drm_mode_crtc_set_gamma_size(). The DRM core will then alias the legacy gamma 94 - * ramp with "GAMMA_LUT". 94 + * ramp with "GAMMA_LUT" or, if that is unavailable, "DEGAMMA_LUT". 95 95 * 96 96 * Support for different non RGB color encodings is controlled through 97 97 * &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They ··· 238 238 static bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc) 239 239 { 240 240 u32 gamma_id = crtc->dev->mode_config.gamma_lut_property->base.id; 241 + u32 degamma_id = crtc->dev->mode_config.degamma_lut_property->base.id; 241 242 242 243 if (!crtc->gamma_size) 243 244 return false; ··· 246 245 if (crtc->funcs->gamma_set) 247 246 return true; 248 247 249 - return !!drm_mode_obj_find_prop_id(&crtc->base, gamma_id); 248 + return !!(drm_mode_obj_find_prop_id(&crtc->base, gamma_id) || 249 + drm_mode_obj_find_prop_id(&crtc->base, degamma_id)); 250 250 } 251 251 252 252 /** ··· 278 276 struct drm_crtc_state *crtc_state; 279 277 struct drm_property_blob *blob; 280 278 struct drm_color_lut *blob_data; 279 + u32 gamma_id = dev->mode_config.gamma_lut_property->base.id; 280 + u32 degamma_id = dev->mode_config.degamma_lut_property->base.id; 281 + bool use_gamma_lut; 281 282 int i, ret = 0; 282 283 bool replaced; 283 284 284 285 if (crtc->funcs->gamma_set) 285 286 return crtc->funcs->gamma_set(crtc, red, green, blue, size, ctx); 287 + 288 + if (drm_mode_obj_find_prop_id(&crtc->base, gamma_id)) 289 + use_gamma_lut = true; 290 + else if (drm_mode_obj_find_prop_id(&crtc->base, degamma_id)) 291 + use_gamma_lut = false; 292 + else 293 + return -ENODEV; 286 294 287 295 state = drm_atomic_state_alloc(crtc->dev); 288 296 if (!state) ··· 323 311 } 324 312 325 313 /* Set GAMMA_LUT and reset DEGAMMA_LUT and CTM */ 326 - replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL); 314 + replaced = drm_property_replace_blob(&crtc_state->degamma_lut, 315 + use_gamma_lut ? NULL : blob); 327 316 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); 328 - replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob); 317 + replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, 318 + use_gamma_lut ? blob : NULL); 329 319 crtc_state->color_mgmt_changed |= replaced; 330 320 331 321 ret = drm_atomic_commit(state);
+5
drivers/gpu/drm/drm_fb_helper.c
··· 1059 1059 goto out_state; 1060 1060 } 1061 1061 1062 + /* 1063 + * FIXME: This always uses gamma_lut. Some HW have only 1064 + * degamma_lut, in which case we should reset gamma_lut and set 1065 + * degamma_lut. See drm_crtc_legacy_gamma_set(). 1066 + */ 1062 1067 replaced = drm_property_replace_blob(&crtc_state->degamma_lut, 1063 1068 NULL); 1064 1069 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);