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

Revert "drm/amd/display: Rework CRTC color management"

This reverts commit 7cd4b70091a5cfa1f58d3a529535304a116acc95.

Revert this to apply the version that includes DCN2 support.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

+162 -359
+10 -22
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 2857 2857 struct drm_plane_state *plane_state, 2858 2858 struct drm_crtc_state *crtc_state) 2859 2859 { 2860 - struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state); 2861 2860 const struct amdgpu_framebuffer *amdgpu_fb = 2862 2861 to_amdgpu_framebuffer(plane_state->fb); 2863 2862 struct dc_scaling_info scaling_info; ··· 2901 2902 * Always set input transfer function, since plane state is refreshed 2902 2903 * every time. 2903 2904 */ 2904 - ret = amdgpu_dm_update_plane_color_mgmt(dm_crtc_state, dc_plane_state); 2905 - if (ret) 2906 - return ret; 2905 + ret = amdgpu_dm_set_degamma_lut(crtc_state, dc_plane_state); 2906 + if (ret) { 2907 + dc_transfer_func_release(dc_plane_state->in_transfer_func); 2908 + dc_plane_state->in_transfer_func = NULL; 2909 + } 2907 2910 2908 - return 0; 2911 + return ret; 2909 2912 } 2910 2913 2911 2914 static void update_stream_scaling_settings(const struct drm_display_mode *mode, ··· 3482 3481 state->vrr_supported = cur->vrr_supported; 3483 3482 state->freesync_config = cur->freesync_config; 3484 3483 state->crc_enabled = cur->crc_enabled; 3485 - state->cm_has_degamma = cur->cm_has_degamma; 3486 - state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb; 3487 3484 3488 3485 /* TODO Duplicate dc_stream after objects are stream object is flattened */ 3489 3486 ··· 5639 5640 bundle->stream_update.dst = acrtc_state->stream->dst; 5640 5641 } 5641 5642 5642 - if (new_pcrtc_state->color_mgmt_changed) { 5643 - /* 5644 - * TODO: This isn't fully correct since we've actually 5645 - * already modified the stream in place. 5646 - */ 5647 - bundle->stream_update.gamut_remap = 5648 - &acrtc_state->stream->gamut_remap_matrix; 5649 - bundle->stream_update.output_csc_transform = 5650 - &acrtc_state->stream->csc_color_matrix; 5651 - bundle->stream_update.out_transfer_func = 5652 - acrtc_state->stream->out_transfer_func; 5653 - } 5643 + if (new_pcrtc_state->color_mgmt_changed) 5644 + bundle->stream_update.out_transfer_func = acrtc_state->stream->out_transfer_func; 5654 5645 5655 5646 acrtc_state->stream->abm_level = acrtc_state->abm_level; 5656 5647 if (acrtc_state->abm_level != dm_old_crtc_state->abm_level) ··· 6490 6501 */ 6491 6502 if (dm_new_crtc_state->base.color_mgmt_changed || 6492 6503 drm_atomic_crtc_needs_modeset(new_crtc_state)) { 6493 - ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state); 6504 + ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state); 6494 6505 if (ret) 6495 6506 goto fail; 6507 + amdgpu_dm_set_ctm(dm_new_crtc_state); 6496 6508 } 6497 6509 6498 6510 /* Update Freesync settings. */ ··· 6796 6806 new_dm_plane_state->dc_state->in_transfer_func; 6797 6807 stream_update.gamut_remap = 6798 6808 &new_dm_crtc_state->stream->gamut_remap_matrix; 6799 - stream_update.output_csc_transform = 6800 - &new_dm_crtc_state->stream->csc_color_matrix; 6801 6809 stream_update.out_transfer_func = 6802 6810 new_dm_crtc_state->stream->out_transfer_func; 6803 6811 }
+4 -6
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 271 271 struct drm_crtc_state base; 272 272 struct dc_stream_state *stream; 273 273 274 - bool cm_has_degamma; 275 - bool cm_is_degamma_srgb; 276 - 277 274 int active_planes; 278 275 bool interrupts_enabled; 279 276 ··· 360 363 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 361 364 362 365 void amdgpu_dm_init_color_mod(void); 363 - int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); 364 - int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, 365 - struct dc_plane_state *dc_plane_state); 366 + int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, 367 + struct dc_plane_state *dc_plane_state); 368 + void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc); 369 + int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc); 366 370 367 371 extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs; 368 372
+148 -331
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
··· 27 27 #include "amdgpu_dm.h" 28 28 #include "dc.h" 29 29 #include "modules/color/color_gamma.h" 30 - #include "basics/conversion.h" 31 - 32 - /* 33 - * The DC interface to HW gives us the following color management blocks 34 - * per pipe (surface): 35 - * 36 - * - Input gamma LUT (de-normalized) 37 - * - Input CSC (normalized) 38 - * - Surface degamma LUT (normalized) 39 - * - Surface CSC (normalized) 40 - * - Surface regamma LUT (normalized) 41 - * - Output CSC (normalized) 42 - * 43 - * But these aren't a direct mapping to DRM color properties. The current DRM 44 - * interface exposes CRTC degamma, CRTC CTM and CRTC regamma while our hardware 45 - * is essentially giving: 46 - * 47 - * Plane CTM -> Plane degamma -> Plane CTM -> Plane regamma -> Plane CTM 48 - * 49 - * The input gamma LUT block isn't really applicable here since it operates 50 - * on the actual input data itself rather than the HW fp representation. The 51 - * input and output CSC blocks are technically available to use as part of 52 - * the DC interface but are typically used internally by DC for conversions 53 - * between color spaces. These could be blended together with user 54 - * adjustments in the future but for now these should remain untouched. 55 - * 56 - * The pipe blending also happens after these blocks so we don't actually 57 - * support any CRTC props with correct blending with multiple planes - but we 58 - * can still support CRTC color management properties in DM in most single 59 - * plane cases correctly with clever management of the DC interface in DM. 60 - * 61 - * As per DRM documentation, blocks should be in hardware bypass when their 62 - * respective property is set to NULL. A linear DGM/RGM LUT should also 63 - * considered as putting the respective block into bypass mode. 64 - * 65 - * This means that the following 66 - * configuration is assumed to be the default: 67 - * 68 - * Plane DGM Bypass -> Plane CTM Bypass -> Plane RGM Bypass -> ... 69 - * CRTC DGM Bypass -> CRTC CTM Bypass -> CRTC RGM Bypass 70 - */ 71 30 72 31 #define MAX_DRM_LUT_VALUE 0xFFFF 73 32 ··· 41 82 setup_x_points_distribution(); 42 83 } 43 84 44 - /* Extracts the DRM lut and lut size from a blob. */ 45 - static const struct drm_color_lut * 46 - __extract_blob_lut(const struct drm_property_blob *blob, uint32_t *size) 47 - { 48 - *size = blob ? drm_color_lut_size(blob) : 0; 49 - return blob ? (struct drm_color_lut *)blob->data : NULL; 50 - } 51 85 52 86 /* 53 87 * Return true if the given lut is a linear mapping of values, i.e. it acts ··· 50 98 * f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in 51 99 * [0, MAX_COLOR_LUT_ENTRIES) 52 100 */ 53 - static bool __is_lut_linear(const struct drm_color_lut *lut, uint32_t size) 101 + static bool __is_lut_linear(struct drm_color_lut *lut, uint32_t size) 54 102 { 55 103 int i; 56 104 uint32_t expected; ··· 75 123 * Convert the drm_color_lut to dc_gamma. The conversion depends on the size 76 124 * of the lut - whether or not it's legacy. 77 125 */ 78 - static void __drm_lut_to_dc_gamma(const struct drm_color_lut *lut, 79 - struct dc_gamma *gamma, bool is_legacy) 126 + static void __drm_lut_to_dc_gamma(struct drm_color_lut *lut, 127 + struct dc_gamma *gamma, 128 + bool is_legacy) 80 129 { 81 130 uint32_t r, g, b; 82 131 int i; ··· 107 154 } 108 155 } 109 156 110 - /* 111 - * Converts a DRM CTM to a DC CSC float matrix. 112 - * The matrix needs to be a 3x4 (12 entry) matrix. 157 + /** 158 + * amdgpu_dm_set_regamma_lut: Set regamma lut for the given CRTC. 159 + * @crtc: amdgpu_dm crtc state 160 + * 161 + * Update the underlying dc_stream_state's output transfer function (OTF) in 162 + * preparation for hardware commit. If no lut is specified by user, we default 163 + * to SRGB. 164 + * 165 + * RETURNS: 166 + * 0 on success, -ENOMEM if memory cannot be allocated to calculate the OTF. 113 167 */ 114 - static void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, 115 - struct fixed31_32 *matrix) 168 + int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) 116 169 { 170 + struct drm_property_blob *blob = crtc->base.gamma_lut; 171 + struct dc_stream_state *stream = crtc->stream; 172 + struct amdgpu_device *adev = (struct amdgpu_device *) 173 + crtc->base.state->dev->dev_private; 174 + struct drm_color_lut *lut; 175 + uint32_t lut_size; 176 + struct dc_gamma *gamma = NULL; 177 + enum dc_transfer_func_type old_type = stream->out_transfer_func->type; 178 + 179 + bool ret; 180 + 181 + if (!blob && adev->asic_type <= CHIP_RAVEN) { 182 + /* By default, use the SRGB predefined curve.*/ 183 + stream->out_transfer_func->type = TF_TYPE_PREDEFINED; 184 + stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB; 185 + return 0; 186 + } 187 + 188 + if (blob) { 189 + lut = (struct drm_color_lut *)blob->data; 190 + lut_size = blob->length / sizeof(struct drm_color_lut); 191 + 192 + gamma = dc_create_gamma(); 193 + if (!gamma) 194 + return -ENOMEM; 195 + 196 + gamma->num_entries = lut_size; 197 + if (gamma->num_entries == MAX_COLOR_LEGACY_LUT_ENTRIES) 198 + gamma->type = GAMMA_RGB_256; 199 + else if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES) 200 + gamma->type = GAMMA_CS_TFM_1D; 201 + else { 202 + /* Invalid lut size */ 203 + dc_gamma_release(&gamma); 204 + return -EINVAL; 205 + } 206 + 207 + /* Convert drm_lut into dc_gamma */ 208 + __drm_lut_to_dc_gamma(lut, gamma, gamma->type == GAMMA_RGB_256); 209 + } 210 + 211 + /* predefined gamma ROM only exist for RAVEN and pre-RAVEN ASIC, 212 + * set canRomBeUsed accordingly 213 + */ 214 + stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 215 + ret = mod_color_calculate_regamma_params(stream->out_transfer_func, 216 + gamma, true, adev->asic_type <= CHIP_RAVEN, NULL); 217 + 218 + if (gamma) 219 + dc_gamma_release(&gamma); 220 + 221 + if (!ret) { 222 + stream->out_transfer_func->type = old_type; 223 + DRM_ERROR("Out of memory when calculating regamma params\n"); 224 + return -ENOMEM; 225 + } 226 + 227 + return 0; 228 + } 229 + 230 + /** 231 + * amdgpu_dm_set_ctm: Set the color transform matrix for the given CRTC. 232 + * @crtc: amdgpu_dm crtc state 233 + * 234 + * Update the underlying dc_stream_state's gamut remap matrix in preparation 235 + * for hardware commit. If no matrix is specified by user, gamut remap will be 236 + * disabled. 237 + */ 238 + void amdgpu_dm_set_ctm(struct dm_crtc_state *crtc) 239 + { 240 + 241 + struct drm_property_blob *blob = crtc->base.ctm; 242 + struct dc_stream_state *stream = crtc->stream; 243 + struct drm_color_ctm *ctm; 117 244 int64_t val; 118 245 int i; 119 246 247 + if (!blob) { 248 + stream->gamut_remap_matrix.enable_remap = false; 249 + return; 250 + } 251 + 252 + stream->gamut_remap_matrix.enable_remap = true; 253 + ctm = (struct drm_color_ctm *)blob->data; 120 254 /* 121 255 * DRM gives a 3x3 matrix, but DC wants 3x4. Assuming we're operating 122 256 * with homogeneous coordinates, augment the matrix with 0's. ··· 215 175 for (i = 0; i < 12; i++) { 216 176 /* Skip 4th element */ 217 177 if (i % 4 == 3) { 218 - matrix[i] = dc_fixpt_zero; 178 + stream->gamut_remap_matrix.matrix[i] = dc_fixpt_zero; 219 179 continue; 220 180 } 221 181 222 182 /* gamut_remap_matrix[i] = ctm[i - floor(i/4)] */ 223 - val = ctm->matrix[i - (i / 4)]; 183 + val = ctm->matrix[i - (i/4)]; 224 184 /* If negative, convert to 2's complement. */ 225 185 if (val & (1ULL << 63)) 226 186 val = -(val & ~(1ULL << 63)); 227 187 228 - matrix[i].value = val; 188 + stream->gamut_remap_matrix.matrix[i].value = val; 229 189 } 230 190 } 231 191 232 - /* Calculates the legacy transfer function - only for sRGB input space. */ 233 - static int __set_legacy_tf(struct dc_transfer_func *func, 234 - const struct drm_color_lut *lut, uint32_t lut_size, 235 - bool has_rom) 236 - { 237 - struct dc_gamma *gamma = NULL; 238 - bool res; 239 - 240 - ASSERT(lut && lut_size == MAX_COLOR_LEGACY_LUT_ENTRIES); 241 - 242 - gamma = dc_create_gamma(); 243 - if (!gamma) 244 - return -ENOMEM; 245 - 246 - gamma->type = GAMMA_RGB_256; 247 - gamma->num_entries = lut_size; 248 - __drm_lut_to_dc_gamma(lut, gamma, true); 249 - 250 - res = mod_color_calculate_regamma_params(func, gamma, true, has_rom, 251 - NULL); 252 - 253 - return res ? 0 : -ENOMEM; 254 - } 255 - 256 - /* Calculates the output transfer function based on expected input space. */ 257 - static int __set_output_tf(struct dc_transfer_func *func, 258 - const struct drm_color_lut *lut, uint32_t lut_size, 259 - bool has_rom) 260 - { 261 - struct dc_gamma *gamma = NULL; 262 - bool res; 263 - 264 - ASSERT(lut && lut_size == MAX_COLOR_LUT_ENTRIES); 265 - 266 - gamma = dc_create_gamma(); 267 - if (!gamma) 268 - return -ENOMEM; 269 - 270 - gamma->num_entries = lut_size; 271 - __drm_lut_to_dc_gamma(lut, gamma, false); 272 - 273 - if (func->tf == TRANSFER_FUNCTION_LINEAR) { 274 - /* 275 - * Color module doesn't like calculating regamma params 276 - * on top of a linear input. But degamma params can be used 277 - * instead to simulate this. 278 - */ 279 - gamma->type = GAMMA_CUSTOM; 280 - res = mod_color_calculate_degamma_params(func, gamma, true); 281 - } else { 282 - /* 283 - * Assume sRGB. The actual mapping will depend on whether the 284 - * input was legacy or not. 285 - */ 286 - gamma->type = GAMMA_CS_TFM_1D; 287 - res = mod_color_calculate_regamma_params(func, gamma, false, 288 - has_rom, NULL); 289 - } 290 - 291 - dc_gamma_release(&gamma); 292 - 293 - return res ? 0 : -ENOMEM; 294 - } 295 - 296 - /* Caculates the input transfer function based on expected input space. */ 297 - static int __set_input_tf(struct dc_transfer_func *func, 298 - const struct drm_color_lut *lut, uint32_t lut_size) 299 - { 300 - struct dc_gamma *gamma = NULL; 301 - bool res; 302 - 303 - gamma = dc_create_gamma(); 304 - if (!gamma) 305 - return -ENOMEM; 306 - 307 - gamma->type = GAMMA_CUSTOM; 308 - gamma->num_entries = lut_size; 309 - 310 - __drm_lut_to_dc_gamma(lut, gamma, false); 311 - 312 - res = mod_color_calculate_degamma_params(func, gamma, true); 313 - dc_gamma_release(&gamma); 314 - 315 - return res ? 0 : -ENOMEM; 316 - } 317 192 318 193 /** 319 - * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. 194 + * amdgpu_dm_set_degamma_lut: Set degamma lut for the given CRTC. 320 195 * @crtc: amdgpu_dm crtc state 321 - * 322 - * With no plane level color management properties we're free to use any 323 - * of the HW blocks as long as the CRTC CTM always comes before the 324 - * CRTC RGM and after the CRTC DGM. 325 - * 326 - * The CRTC RGM block will be placed in the RGM LUT block if it is non-linear. 327 - * The CRTC DGM block will be placed in the DGM LUT block if it is non-linear. 328 - * The CRTC CTM will be placed in the gamut remap block if it is non-linear. 329 - * 330 - * The RGM block is typically more fully featured and accurate across 331 - * all ASICs - DCE can't support a custom non-linear CRTC DGM. 332 - * 333 - * For supporting both plane level color management and CRTC level color 334 - * management at once we have to either restrict the usage of CRTC properties 335 - * or blend adjustments together. 336 - * 337 - * Returns 0 on success. 338 - */ 339 - int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) 340 - { 341 - struct dc_stream_state *stream = crtc->stream; 342 - struct amdgpu_device *adev = 343 - (struct amdgpu_device *)crtc->base.state->dev->dev_private; 344 - bool has_rom = adev->asic_type <= CHIP_RAVEN; 345 - struct drm_color_ctm *ctm = NULL; 346 - const struct drm_color_lut *degamma_lut, *regamma_lut; 347 - uint32_t degamma_size, regamma_size; 348 - bool has_regamma, has_degamma; 349 - bool is_legacy; 350 - int r; 351 - 352 - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, &degamma_size); 353 - if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) 354 - return -EINVAL; 355 - 356 - regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, &regamma_size); 357 - if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES && 358 - regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES) 359 - return -EINVAL; 360 - 361 - has_degamma = 362 - degamma_lut && !__is_lut_linear(degamma_lut, degamma_size); 363 - 364 - has_regamma = 365 - regamma_lut && !__is_lut_linear(regamma_lut, regamma_size); 366 - 367 - is_legacy = regamma_size == MAX_COLOR_LEGACY_LUT_ENTRIES; 368 - 369 - /* Reset all adjustments. */ 370 - crtc->cm_has_degamma = false; 371 - crtc->cm_is_degamma_srgb = false; 372 - 373 - /* Setup regamma and degamma. */ 374 - if (is_legacy) { 375 - /* 376 - * Legacy regamma forces us to use the sRGB RGM as a base. 377 - * This also means we can't use linear DGM since DGM needs 378 - * to use sRGB as a base as well, resulting in incorrect CRTC 379 - * DGM and CRTC CTM. 380 - * 381 - * TODO: Just map this to the standard regamma interface 382 - * instead since this isn't really right. One of the cases 383 - * where this setup currently fails is trying to do an 384 - * inverse color ramp in legacy userspace. 385 - */ 386 - crtc->cm_is_degamma_srgb = true; 387 - stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 388 - stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB; 389 - 390 - r = __set_legacy_tf(stream->out_transfer_func, regamma_lut, 391 - regamma_size, has_rom); 392 - if (r) 393 - return r; 394 - } else if (has_regamma) { 395 - /* CRTC RGM goes into RGM LUT. */ 396 - stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 397 - stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 398 - 399 - r = __set_output_tf(stream->out_transfer_func, regamma_lut, 400 - regamma_size, has_rom); 401 - if (r) 402 - return r; 403 - } else { 404 - /* 405 - * No CRTC RGM means we can just put the block into bypass 406 - * since we don't have any plane level adjustments using it. 407 - */ 408 - stream->out_transfer_func->type = TF_TYPE_BYPASS; 409 - stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 410 - } 411 - 412 - /* 413 - * CRTC DGM goes into DGM LUT. It would be nice to place it 414 - * into the RGM since it's a more featured block but we'd 415 - * have to place the CTM in the OCSC in that case. 416 - */ 417 - crtc->cm_has_degamma = has_degamma; 418 - 419 - /* Setup CRTC CTM. */ 420 - if (crtc->base.ctm) { 421 - ctm = (struct drm_color_ctm *)crtc->base.ctm->data; 422 - 423 - /* 424 - * Gamut remapping must be used for gamma correction 425 - * since it comes before the regamma correction. 426 - * 427 - * OCSC could be used for gamma correction, but we'd need to 428 - * blend the adjustments together with the required output 429 - * conversion matrix - so just use the gamut remap block 430 - * for now. 431 - */ 432 - __drm_ctm_to_dc_matrix(ctm, stream->gamut_remap_matrix.matrix); 433 - 434 - stream->gamut_remap_matrix.enable_remap = true; 435 - stream->csc_color_matrix.enable_adjustment = false; 436 - } else { 437 - /* Bypass CTM. */ 438 - stream->gamut_remap_matrix.enable_remap = false; 439 - stream->csc_color_matrix.enable_adjustment = false; 440 - } 441 - 442 - return 0; 443 - } 444 - 445 - /** 446 - * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane. 447 - * @crtc: amdgpu_dm crtc state 448 - * @ dc_plane_state: target DC surface 449 196 * 450 197 * Update the underlying dc_stream_state's input transfer function (ITF) in 451 - * preparation for hardware commit. The transfer function used depends on 452 - * the prepartion done on the stream for color management. 198 + * preparation for hardware commit. If no lut is specified by user, we default 199 + * to SRGB degamma. 453 200 * 454 - * Returns 0 on success. 201 + * We support degamma bypass, predefined SRGB, and custom degamma 202 + * 203 + * RETURNS: 204 + * 0 on success 205 + * -EINVAL if crtc_state has a degamma_lut of invalid size 206 + * -ENOMEM if gamma allocation fails 455 207 */ 456 - int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, 457 - struct dc_plane_state *dc_plane_state) 208 + int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, 209 + struct dc_plane_state *dc_plane_state) 458 210 { 459 - const struct drm_color_lut *degamma_lut; 460 - uint32_t degamma_size; 461 - int r; 211 + struct drm_property_blob *blob = crtc_state->degamma_lut; 212 + struct drm_color_lut *lut; 213 + uint32_t lut_size; 214 + struct dc_gamma *gamma; 215 + bool ret; 462 216 463 - if (crtc->cm_has_degamma) { 464 - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, 465 - &degamma_size); 466 - ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); 467 - 468 - dc_plane_state->in_transfer_func->type = 469 - TF_TYPE_DISTRIBUTED_POINTS; 470 - 471 - /* 472 - * This case isn't fully correct, but also fairly 473 - * uncommon. This is userspace trying to use a 474 - * legacy gamma LUT + atomic degamma LUT 475 - * at the same time. 476 - * 477 - * Legacy gamma requires the input to be in linear 478 - * space, so that means we need to apply an sRGB 479 - * degamma. But color module also doesn't support 480 - * a user ramp in this case so the degamma will 481 - * be lost. 482 - * 483 - * Even if we did support it, it's still not right: 484 - * 485 - * Input -> CRTC DGM -> sRGB DGM -> CRTC CTM -> 486 - * sRGB RGM -> CRTC RGM -> Output 487 - * 488 - * The CSC will be done in the wrong space since 489 - * we're applying an sRGB DGM on top of the CRTC 490 - * DGM. 491 - * 492 - * TODO: Don't use the legacy gamma interface and just 493 - * map these to the atomic one instead. 494 - */ 495 - if (crtc->cm_is_degamma_srgb) 496 - dc_plane_state->in_transfer_func->tf = 497 - TRANSFER_FUNCTION_SRGB; 498 - else 499 - dc_plane_state->in_transfer_func->tf = 500 - TRANSFER_FUNCTION_LINEAR; 501 - 502 - r = __set_input_tf(dc_plane_state->in_transfer_func, 503 - degamma_lut, degamma_size); 504 - if (r) 505 - return r; 506 - } else if (crtc->cm_is_degamma_srgb) { 507 - /* 508 - * For legacy gamma support we need the regamma input 509 - * in linear space. Assume that the input is sRGB. 510 - */ 217 + if (!blob) { 218 + /* Default to SRGB */ 511 219 dc_plane_state->in_transfer_func->type = TF_TYPE_PREDEFINED; 512 220 dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_SRGB; 513 - } else { 514 - /* ...Otherwise we can just bypass the DGM block. */ 221 + return 0; 222 + } 223 + 224 + lut = (struct drm_color_lut *)blob->data; 225 + if (__is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES)) { 515 226 dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 516 227 dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; 228 + return 0; 229 + } 230 + 231 + gamma = dc_create_gamma(); 232 + if (!gamma) 233 + return -ENOMEM; 234 + 235 + lut_size = blob->length / sizeof(struct drm_color_lut); 236 + gamma->num_entries = lut_size; 237 + if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES) 238 + gamma->type = GAMMA_CUSTOM; 239 + else { 240 + dc_gamma_release(&gamma); 241 + return -EINVAL; 242 + } 243 + 244 + __drm_lut_to_dc_gamma(lut, gamma, false); 245 + 246 + dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; 247 + ret = mod_color_calculate_degamma_params(dc_plane_state->in_transfer_func, gamma, true); 248 + dc_gamma_release(&gamma); 249 + if (!ret) { 250 + dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; 251 + DRM_ERROR("Out of memory when calculating degamma params\n"); 252 + return -ENOMEM; 517 253 } 518 254 519 255 return 0; 520 256 } 257 +