1 /* 2 * Copyright (c) 2016 Intel Corporation 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23 #include <linux/export.h> 24 #include <linux/uaccess.h> 25 26 #include <drm/drm_atomic.h> 27 #include <drm/drm_color_mgmt.h> 28 #include <drm/drm_crtc.h> 29 #include <drm/drm_device.h> 30 #include <drm/drm_drv.h> 31 #include <drm/drm_print.h> 32 #include <kunit/visibility.h> 33 34 #include "drm_crtc_internal.h" 35 36 /** 37 * DOC: overview 38 * 39 * Color management or color space adjustments is supported through a set of 5 40 * properties on the &drm_crtc object. They are set up by calling 41 * drm_crtc_enable_color_mgmt(). 42 * 43 * "DEGAMMA_LUT”: 44 * Blob property to set the degamma lookup table (LUT) mapping pixel data 45 * from the framebuffer before it is given to the transformation matrix. 46 * The data is interpreted as an array of &struct drm_color_lut elements. 47 * Hardware might choose not to use the full precision of the LUT elements 48 * nor use all the elements of the LUT (for example the hardware might 49 * choose to interpolate between LUT[0] and LUT[4]). 50 * 51 * Setting this to NULL (blob property value set to 0) means a 52 * linear/pass-thru gamma table should be used. This is generally the 53 * driver boot-up state too. Drivers can access this blob through 54 * &drm_crtc_state.degamma_lut. 55 * 56 * “DEGAMMA_LUT_SIZE”: 57 * Unsigned range property to give the size of the lookup table to be set 58 * on the DEGAMMA_LUT property (the size depends on the underlying 59 * hardware). If drivers support multiple LUT sizes then they should 60 * publish the largest size, and sub-sample smaller sized LUTs (e.g. for 61 * split-gamma modes) appropriately. 62 * 63 * “CTM”: 64 * Blob property to set the current transformation matrix (CTM) apply to 65 * pixel data after the lookup through the degamma LUT and before the 66 * lookup through the gamma LUT. The data is interpreted as a struct 67 * &drm_color_ctm. 68 * 69 * Setting this to NULL (blob property value set to 0) means a 70 * unit/pass-thru matrix should be used. This is generally the driver 71 * boot-up state too. Drivers can access the blob for the color conversion 72 * matrix through &drm_crtc_state.ctm. 73 * 74 * “GAMMA_LUT”: 75 * Blob property to set the gamma lookup table (LUT) mapping pixel data 76 * after the transformation matrix to data sent to the connector. The 77 * data is interpreted as an array of &struct drm_color_lut elements. 78 * Hardware might choose not to use the full precision of the LUT elements 79 * nor use all the elements of the LUT (for example the hardware might 80 * choose to interpolate between LUT[0] and LUT[4]). 81 * 82 * Setting this to NULL (blob property value set to 0) means a 83 * linear/pass-thru gamma table should be used. This is generally the 84 * driver boot-up state too. Drivers can access this blob through 85 * &drm_crtc_state.gamma_lut. 86 * 87 * Note that for mostly historical reasons stemming from Xorg heritage, 88 * this is also used to store the color map (also sometimes color lut, CLUT 89 * or color palette) for indexed formats like DRM_FORMAT_C8. 90 * 91 * “GAMMA_LUT_SIZE”: 92 * Unsigned range property to give the size of the lookup table to be set 93 * on the GAMMA_LUT property (the size depends on the underlying hardware). 94 * If drivers support multiple LUT sizes then they should publish the 95 * largest size, and sub-sample smaller sized LUTs (e.g. for split-gamma 96 * modes) appropriately. 97 * 98 * There is also support for a legacy gamma table, which is set up by calling 99 * drm_mode_crtc_set_gamma_size(). The DRM core will then alias the legacy gamma 100 * ramp with "GAMMA_LUT" or, if that is unavailable, "DEGAMMA_LUT". 101 * 102 * Support for different non RGB color encodings is controlled through 103 * &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They 104 * are set up by calling drm_plane_create_color_properties(). 105 * 106 * "COLOR_ENCODING": 107 * Optional plane enum property to support different non RGB 108 * color encodings. The driver can provide a subset of standard 109 * enum values supported by the DRM plane. 110 * 111 * "COLOR_RANGE": 112 * Optional plane enum property to support different non RGB 113 * color parameter ranges. The driver can provide a subset of 114 * standard enum values supported by the DRM plane. 115 */ 116 117 /** 118 * drm_color_ctm_s31_32_to_qm_n 119 * 120 * @user_input: input value 121 * @m: number of integer bits, only support m <= 32, include the sign-bit 122 * @n: number of fractional bits, only support n <= 32 123 * 124 * Convert and clamp S31.32 sign-magnitude to Qm.n (signed 2's complement). 125 * The sign-bit BIT(m+n-1) and above are 0 for positive value and 1 for negative 126 * the range of value is [-2^(m-1), 2^(m-1) - 2^-n] 127 * 128 * For example 129 * A Q3.12 format number: 130 * - required bit: 3 + 12 = 15bits 131 * - range: [-2^2, 2^2 - 2^−15] 132 * 133 * NOTE: the m can be zero if all bit_precision are used to present fractional 134 * bits like Q0.32 135 */ 136 u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n) 137 { 138 u64 mag = (user_input & ~BIT_ULL(63)) >> (32 - n); 139 bool negative = !!(user_input & BIT_ULL(63)); 140 s64 val; 141 142 WARN_ON(m > 32 || n > 32); 143 144 val = clamp_val(mag, 0, negative ? 145 BIT_ULL(n + m - 1) : BIT_ULL(n + m - 1) - 1); 146 147 return negative ? -val : val; 148 } 149 EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n); 150 151 /** 152 * drm_crtc_enable_color_mgmt - enable color management properties 153 * @crtc: DRM CRTC 154 * @degamma_lut_size: the size of the degamma lut (before CSC) 155 * @has_ctm: whether to attach ctm_property for CSC matrix 156 * @gamma_lut_size: the size of the gamma lut (after CSC) 157 * 158 * This function lets the driver enable the color correction 159 * properties on a CRTC. This includes 3 degamma, csc and gamma 160 * properties that userspace can set and 2 size properties to inform 161 * the userspace of the lut sizes. Each of the properties are 162 * optional. The gamma and degamma properties are only attached if 163 * their size is not 0 and ctm_property is only attached if has_ctm is 164 * true. 165 */ 166 void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, 167 uint degamma_lut_size, 168 bool has_ctm, 169 uint gamma_lut_size) 170 { 171 struct drm_device *dev = crtc->dev; 172 struct drm_mode_config *config = &dev->mode_config; 173 174 if (degamma_lut_size) { 175 drm_object_attach_property(&crtc->base, 176 config->degamma_lut_property, 0); 177 drm_object_attach_property(&crtc->base, 178 config->degamma_lut_size_property, 179 degamma_lut_size); 180 } 181 182 if (has_ctm) 183 drm_object_attach_property(&crtc->base, 184 config->ctm_property, 0); 185 186 if (gamma_lut_size) { 187 drm_object_attach_property(&crtc->base, 188 config->gamma_lut_property, 0); 189 drm_object_attach_property(&crtc->base, 190 config->gamma_lut_size_property, 191 gamma_lut_size); 192 } 193 } 194 EXPORT_SYMBOL(drm_crtc_enable_color_mgmt); 195 196 /** 197 * drm_mode_crtc_set_gamma_size - set the gamma table size 198 * @crtc: CRTC to set the gamma table size for 199 * @gamma_size: size of the gamma table 200 * 201 * Drivers which support gamma tables should set this to the supported gamma 202 * table size when initializing the CRTC. Currently the drm core only supports a 203 * fixed gamma table size. 204 * 205 * Returns: 206 * Zero on success, negative errno on failure. 207 */ 208 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 209 int gamma_size) 210 { 211 uint16_t *r_base, *g_base, *b_base; 212 int i; 213 214 crtc->gamma_size = gamma_size; 215 216 crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, 217 GFP_KERNEL); 218 if (!crtc->gamma_store) { 219 crtc->gamma_size = 0; 220 return -ENOMEM; 221 } 222 223 r_base = crtc->gamma_store; 224 g_base = r_base + gamma_size; 225 b_base = g_base + gamma_size; 226 for (i = 0; i < gamma_size; i++) { 227 r_base[i] = i << 8; 228 g_base[i] = i << 8; 229 b_base[i] = i << 8; 230 } 231 232 233 return 0; 234 } 235 EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); 236 237 /** 238 * drm_crtc_supports_legacy_gamma - does the crtc support legacy gamma correction table 239 * @crtc: CRTC object 240 * 241 * Returns true/false if the given crtc supports setting the legacy gamma 242 * correction table. 243 */ 244 static bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc) 245 { 246 u32 gamma_id = crtc->dev->mode_config.gamma_lut_property->base.id; 247 u32 degamma_id = crtc->dev->mode_config.degamma_lut_property->base.id; 248 249 if (!crtc->gamma_size) 250 return false; 251 252 if (crtc->funcs->gamma_set) 253 return true; 254 255 return !!(drm_mode_obj_find_prop_id(&crtc->base, gamma_id) || 256 drm_mode_obj_find_prop_id(&crtc->base, degamma_id)); 257 } 258 259 /** 260 * drm_crtc_legacy_gamma_set - set the legacy gamma correction table 261 * @crtc: CRTC object 262 * @red: red correction table 263 * @green: green correction table 264 * @blue: blue correction table 265 * @size: size of the tables 266 * @ctx: lock acquire context 267 * 268 * Implements support for legacy gamma correction table for drivers 269 * that have set drm_crtc_funcs.gamma_set or that support color management 270 * through the DEGAMMA_LUT/GAMMA_LUT properties. See 271 * drm_crtc_enable_color_mgmt() and the containing chapter for 272 * how the atomic color management and gamma tables work. 273 * 274 * This function sets the gamma using drm_crtc_funcs.gamma_set if set, or 275 * alternatively using crtc color management properties. 276 */ 277 static int drm_crtc_legacy_gamma_set(struct drm_crtc *crtc, 278 u16 *red, u16 *green, u16 *blue, 279 u32 size, 280 struct drm_modeset_acquire_ctx *ctx) 281 { 282 struct drm_device *dev = crtc->dev; 283 struct drm_atomic_commit *state; 284 struct drm_crtc_state *crtc_state; 285 struct drm_property_blob *blob; 286 struct drm_color_lut *blob_data; 287 u32 gamma_id = dev->mode_config.gamma_lut_property->base.id; 288 u32 degamma_id = dev->mode_config.degamma_lut_property->base.id; 289 bool use_gamma_lut; 290 int i, ret = 0; 291 bool replaced; 292 293 if (crtc->funcs->gamma_set) 294 return crtc->funcs->gamma_set(crtc, red, green, blue, size, ctx); 295 296 if (drm_mode_obj_find_prop_id(&crtc->base, gamma_id)) 297 use_gamma_lut = true; 298 else if (drm_mode_obj_find_prop_id(&crtc->base, degamma_id)) 299 use_gamma_lut = false; 300 else 301 return -ENODEV; 302 303 state = drm_atomic_commit_alloc(crtc->dev); 304 if (!state) 305 return -ENOMEM; 306 307 blob = drm_property_create_blob(dev, 308 sizeof(struct drm_color_lut) * size, 309 NULL); 310 if (IS_ERR(blob)) { 311 ret = PTR_ERR(blob); 312 blob = NULL; 313 goto fail; 314 } 315 316 /* Prepare GAMMA_LUT with the legacy values. */ 317 blob_data = blob->data; 318 for (i = 0; i < size; i++) { 319 blob_data[i].red = red[i]; 320 blob_data[i].green = green[i]; 321 blob_data[i].blue = blue[i]; 322 } 323 324 state->acquire_ctx = ctx; 325 crtc_state = drm_atomic_get_crtc_state(state, crtc); 326 if (IS_ERR(crtc_state)) { 327 ret = PTR_ERR(crtc_state); 328 goto fail; 329 } 330 331 /* Set GAMMA_LUT and reset DEGAMMA_LUT and CTM */ 332 replaced = drm_property_replace_blob(&crtc_state->degamma_lut, 333 use_gamma_lut ? NULL : blob); 334 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL); 335 replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, 336 use_gamma_lut ? blob : NULL); 337 crtc_state->color_mgmt_changed |= replaced; 338 339 ret = drm_atomic_commit(state); 340 341 fail: 342 drm_atomic_commit_put(state); 343 drm_property_blob_put(blob); 344 return ret; 345 } 346 347 /** 348 * drm_mode_gamma_set_ioctl - set the gamma table 349 * @dev: DRM device 350 * @data: ioctl data 351 * @file_priv: DRM file info 352 * 353 * Set the gamma table of a CRTC to the one passed in by the user. Userspace can 354 * inquire the required gamma table size through drm_mode_gamma_get_ioctl. 355 * 356 * Called by the user via ioctl. 357 * 358 * Returns: 359 * Zero on success, negative errno on failure. 360 */ 361 int drm_mode_gamma_set_ioctl(struct drm_device *dev, 362 void *data, struct drm_file *file_priv) 363 { 364 struct drm_mode_crtc_lut *crtc_lut = data; 365 struct drm_crtc *crtc; 366 void *r_base, *g_base, *b_base; 367 int size; 368 struct drm_modeset_acquire_ctx ctx; 369 int ret = 0; 370 371 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 372 return -EOPNOTSUPP; 373 374 crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id); 375 if (!crtc) 376 return -ENOENT; 377 378 if (!drm_crtc_supports_legacy_gamma(crtc)) 379 return -ENOSYS; 380 381 /* memcpy into gamma store */ 382 if (crtc_lut->gamma_size != crtc->gamma_size) 383 return -EINVAL; 384 385 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); 386 387 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 388 r_base = crtc->gamma_store; 389 if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) { 390 ret = -EFAULT; 391 goto out; 392 } 393 394 g_base = r_base + size; 395 if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) { 396 ret = -EFAULT; 397 goto out; 398 } 399 400 b_base = g_base + size; 401 if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) { 402 ret = -EFAULT; 403 goto out; 404 } 405 406 ret = drm_crtc_legacy_gamma_set(crtc, r_base, g_base, b_base, 407 crtc->gamma_size, &ctx); 408 409 out: 410 DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); 411 return ret; 412 413 } 414 415 /** 416 * drm_mode_gamma_get_ioctl - get the gamma table 417 * @dev: DRM device 418 * @data: ioctl data 419 * @file_priv: DRM file info 420 * 421 * Copy the current gamma table into the storage provided. This also provides 422 * the gamma table size the driver expects, which can be used to size the 423 * allocated storage. 424 * 425 * Called by the user via ioctl. 426 * 427 * Returns: 428 * Zero on success, negative errno on failure. 429 */ 430 int drm_mode_gamma_get_ioctl(struct drm_device *dev, 431 void *data, struct drm_file *file_priv) 432 { 433 struct drm_mode_crtc_lut *crtc_lut = data; 434 struct drm_crtc *crtc; 435 void *r_base, *g_base, *b_base; 436 int size; 437 int ret = 0; 438 439 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 440 return -EOPNOTSUPP; 441 442 crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id); 443 if (!crtc) 444 return -ENOENT; 445 446 /* memcpy into gamma store */ 447 if (crtc_lut->gamma_size != crtc->gamma_size) 448 return -EINVAL; 449 450 drm_modeset_lock(&crtc->mutex, NULL); 451 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 452 r_base = crtc->gamma_store; 453 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { 454 ret = -EFAULT; 455 goto out; 456 } 457 458 g_base = r_base + size; 459 if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) { 460 ret = -EFAULT; 461 goto out; 462 } 463 464 b_base = g_base + size; 465 if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) { 466 ret = -EFAULT; 467 goto out; 468 } 469 out: 470 drm_modeset_unlock(&crtc->mutex); 471 return ret; 472 } 473 474 static const char * const color_encoding_name[] = { 475 [DRM_COLOR_YCBCR_BT601] = "ITU-R BT.601 YCbCr", 476 [DRM_COLOR_YCBCR_BT709] = "ITU-R BT.709 YCbCr", 477 [DRM_COLOR_YCBCR_BT2020] = "ITU-R BT.2020 YCbCr", 478 }; 479 480 static const char * const color_range_name[] = { 481 [DRM_COLOR_YCBCR_FULL_RANGE] = "YCbCr full range", 482 [DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range", 483 }; 484 485 /** 486 * drm_get_color_encoding_name - return a string for color encoding 487 * @encoding: color encoding to compute name of 488 * 489 * In contrast to the other drm_get_*_name functions this one here returns a 490 * const pointer and hence is threadsafe. 491 */ 492 const char *drm_get_color_encoding_name(enum drm_color_encoding encoding) 493 { 494 if (WARN_ON(encoding >= ARRAY_SIZE(color_encoding_name))) 495 return "unknown"; 496 497 return color_encoding_name[encoding]; 498 } 499 EXPORT_SYMBOL_IF_KUNIT(drm_get_color_encoding_name); 500 501 /** 502 * drm_get_color_range_name - return a string for color range 503 * @range: color range to compute name of 504 * 505 * In contrast to the other drm_get_*_name functions this one here returns a 506 * const pointer and hence is threadsafe. 507 */ 508 const char *drm_get_color_range_name(enum drm_color_range range) 509 { 510 if (WARN_ON(range >= ARRAY_SIZE(color_range_name))) 511 return "unknown"; 512 513 return color_range_name[range]; 514 } 515 EXPORT_SYMBOL_IF_KUNIT(drm_get_color_range_name); 516 517 /** 518 * drm_plane_create_color_properties - color encoding related plane properties 519 * @plane: plane object 520 * @supported_encodings: bitfield indicating supported color encodings 521 * @supported_ranges: bitfileld indicating supported color ranges 522 * @default_encoding: default color encoding 523 * @default_range: default color range 524 * 525 * Create and attach plane specific COLOR_ENCODING and COLOR_RANGE 526 * properties to @plane. The supported encodings and ranges should 527 * be provided in supported_encodings and supported_ranges bitmasks. 528 * Each bit set in the bitmask indicates that its number as enum 529 * value is supported. 530 */ 531 int drm_plane_create_color_properties(struct drm_plane *plane, 532 u32 supported_encodings, 533 u32 supported_ranges, 534 enum drm_color_encoding default_encoding, 535 enum drm_color_range default_range) 536 { 537 struct drm_device *dev = plane->dev; 538 struct drm_property *prop; 539 struct drm_prop_enum_list enum_list[MAX_T(int, DRM_COLOR_ENCODING_MAX, 540 DRM_COLOR_RANGE_MAX)]; 541 int i, len; 542 543 if (WARN_ON(supported_encodings == 0 || 544 (supported_encodings & -BIT(DRM_COLOR_ENCODING_MAX)) != 0 || 545 (supported_encodings & BIT(default_encoding)) == 0)) 546 return -EINVAL; 547 548 if (WARN_ON(supported_ranges == 0 || 549 (supported_ranges & -BIT(DRM_COLOR_RANGE_MAX)) != 0 || 550 (supported_ranges & BIT(default_range)) == 0)) 551 return -EINVAL; 552 553 len = 0; 554 for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) { 555 if ((supported_encodings & BIT(i)) == 0) 556 continue; 557 558 enum_list[len].type = i; 559 enum_list[len].name = color_encoding_name[i]; 560 len++; 561 } 562 563 prop = drm_property_create_enum(dev, 0, "COLOR_ENCODING", 564 enum_list, len); 565 if (!prop) 566 return -ENOMEM; 567 plane->color_encoding_property = prop; 568 drm_object_attach_property(&plane->base, prop, default_encoding); 569 if (plane->state) 570 plane->state->color_encoding = default_encoding; 571 572 len = 0; 573 for (i = 0; i < DRM_COLOR_RANGE_MAX; i++) { 574 if ((supported_ranges & BIT(i)) == 0) 575 continue; 576 577 enum_list[len].type = i; 578 enum_list[len].name = color_range_name[i]; 579 len++; 580 } 581 582 prop = drm_property_create_enum(dev, 0, "COLOR_RANGE", 583 enum_list, len); 584 if (!prop) 585 return -ENOMEM; 586 plane->color_range_property = prop; 587 drm_object_attach_property(&plane->base, prop, default_range); 588 if (plane->state) 589 plane->state->color_range = default_range; 590 591 return 0; 592 } 593 EXPORT_SYMBOL(drm_plane_create_color_properties); 594 595 /** 596 * drm_color_lut_check - check validity of lookup table 597 * @lut: property blob containing LUT to check 598 * @tests: bitmask of tests to run 599 * 600 * Helper to check whether a userspace-provided lookup table is valid and 601 * satisfies hardware requirements. Drivers pass a bitmask indicating which of 602 * the tests in &drm_color_lut_tests should be performed. 603 * 604 * Returns 0 on success, -EINVAL on failure. 605 */ 606 int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) 607 { 608 const struct drm_color_lut *entry; 609 int i; 610 611 if (!lut || !tests) 612 return 0; 613 614 entry = lut->data; 615 for (i = 0; i < drm_color_lut_size(lut); i++) { 616 if (tests & DRM_COLOR_LUT_EQUAL_CHANNELS) { 617 if (entry[i].red != entry[i].blue || 618 entry[i].red != entry[i].green) { 619 DRM_DEBUG_KMS("All LUT entries must have equal r/g/b\n"); 620 return -EINVAL; 621 } 622 } 623 624 if (i > 0 && tests & DRM_COLOR_LUT_NON_DECREASING) { 625 if (entry[i].red < entry[i - 1].red || 626 entry[i].green < entry[i - 1].green || 627 entry[i].blue < entry[i - 1].blue) { 628 DRM_DEBUG_KMS("LUT entries must never decrease.\n"); 629 return -EINVAL; 630 } 631 } 632 } 633 634 return 0; 635 } 636 EXPORT_SYMBOL(drm_color_lut_check); 637 638 /* 639 * Gamma-LUT programming 640 */ 641 642 /** 643 * drm_crtc_load_gamma_888 - Programs gamma ramp for RGB888-like formats 644 * @crtc: The displaying CRTC 645 * @lut: The gamma ramp to program 646 * @set_gamma: Callback for programming the hardware gamma LUT 647 * 648 * Programs the gamma ramp specified in @lut to hardware. The input gamma 649 * ramp must have 256 entries per color component. 650 */ 651 void drm_crtc_load_gamma_888(struct drm_crtc *crtc, const struct drm_color_lut *lut, 652 drm_crtc_set_lut_func set_gamma) 653 { 654 unsigned int i; 655 656 for (i = 0; i < 256; ++i) 657 set_gamma(crtc, i, lut[i].red, lut[i].green, lut[i].blue); 658 } 659 EXPORT_SYMBOL(drm_crtc_load_gamma_888); 660 661 /** 662 * drm_crtc_load_gamma_565_from_888 - Programs gamma ramp for RGB565-like formats 663 * @crtc: The displaying CRTC 664 * @lut: The gamma ramp to program 665 * @set_gamma: Callback for programming the hardware gamma LUT 666 * 667 * Programs the gamma ramp specified in @lut to hardware. The input gamma 668 * ramp must have 256 entries per color component. The helper interpolates 669 * the individual color components to reduce the number of entries to 5/6/5. 670 */ 671 void drm_crtc_load_gamma_565_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut, 672 drm_crtc_set_lut_func set_gamma) 673 { 674 unsigned int i; 675 u16 r, g, b; 676 677 for (i = 0; i < 32; ++i) { 678 r = lut[i * 8 + i / 4].red; 679 g = lut[i * 4 + i / 16].green; 680 b = lut[i * 8 + i / 4].blue; 681 set_gamma(crtc, i, r, g, b); 682 } 683 /* Green has one more bit, so add padding with 0 for red and blue. */ 684 for (i = 32; i < 64; ++i) { 685 g = lut[i * 4 + i / 16].green; 686 set_gamma(crtc, i, 0, g, 0); 687 } 688 } 689 EXPORT_SYMBOL(drm_crtc_load_gamma_565_from_888); 690 691 /** 692 * drm_crtc_load_gamma_555_from_888 - Programs gamma ramp for RGB555-like formats 693 * @crtc: The displaying CRTC 694 * @lut: The gamma ramp to program 695 * @set_gamma: Callback for programming the hardware gamma LUT 696 * 697 * Programs the gamma ramp specified in @lut to hardware. The input gamma 698 * ramp must have 256 entries per color component. The helper interpolates 699 * the individual color components to reduce the number of entries to 5/5/5. 700 */ 701 void drm_crtc_load_gamma_555_from_888(struct drm_crtc *crtc, const struct drm_color_lut *lut, 702 drm_crtc_set_lut_func set_gamma) 703 { 704 unsigned int i; 705 u16 r, g, b; 706 707 for (i = 0; i < 32; ++i) { 708 r = lut[i * 8 + i / 4].red; 709 g = lut[i * 8 + i / 4].green; 710 b = lut[i * 8 + i / 4].blue; 711 set_gamma(crtc, i, r, g, b); 712 } 713 } 714 EXPORT_SYMBOL(drm_crtc_load_gamma_555_from_888); 715 716 static void fill_gamma_888(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b, 717 drm_crtc_set_lut_func set_gamma) 718 { 719 r = (r << 8) | r; 720 g = (g << 8) | g; 721 b = (b << 8) | b; 722 723 set_gamma(crtc, i, r, g, b); 724 } 725 726 /** 727 * drm_crtc_fill_gamma_888 - Programs a default gamma ramp for RGB888-like formats 728 * @crtc: The displaying CRTC 729 * @set_gamma: Callback for programming the hardware gamma LUT 730 * 731 * Programs a default gamma ramp to hardware. 732 */ 733 void drm_crtc_fill_gamma_888(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma) 734 { 735 unsigned int i; 736 737 for (i = 0; i < 256; ++i) 738 fill_gamma_888(crtc, i, i, i, i, set_gamma); 739 } 740 EXPORT_SYMBOL(drm_crtc_fill_gamma_888); 741 742 static void fill_gamma_565(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b, 743 drm_crtc_set_lut_func set_gamma) 744 { 745 r = (r << 11) | (r << 6) | (r << 1) | (r >> 4); 746 g = (g << 10) | (g << 4) | (g >> 2); 747 b = (b << 11) | (b << 6) | (b << 1) | (b >> 4); 748 749 set_gamma(crtc, i, r, g, b); 750 } 751 752 /** 753 * drm_crtc_fill_gamma_565 - Programs a default gamma ramp for RGB565-like formats 754 * @crtc: The displaying CRTC 755 * @set_gamma: Callback for programming the hardware gamma LUT 756 * 757 * Programs a default gamma ramp to hardware. 758 */ 759 void drm_crtc_fill_gamma_565(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma) 760 { 761 unsigned int i; 762 763 for (i = 0; i < 32; ++i) 764 fill_gamma_565(crtc, i, i, i, i, set_gamma); 765 /* Green has one more bit, so add padding with 0 for red and blue. */ 766 for (i = 32; i < 64; ++i) 767 fill_gamma_565(crtc, i, 0, i, 0, set_gamma); 768 } 769 EXPORT_SYMBOL(drm_crtc_fill_gamma_565); 770 771 static void fill_gamma_555(struct drm_crtc *crtc, unsigned int i, u16 r, u16 g, u16 b, 772 drm_crtc_set_lut_func set_gamma) 773 { 774 r = (r << 11) | (r << 6) | (r << 1) | (r >> 4); 775 g = (g << 11) | (g << 6) | (g << 1) | (g >> 4); 776 b = (b << 11) | (b << 6) | (b << 1) | (r >> 4); 777 778 set_gamma(crtc, i, r, g, b); 779 } 780 781 /** 782 * drm_crtc_fill_gamma_555 - Programs a default gamma ramp for RGB555-like formats 783 * @crtc: The displaying CRTC 784 * @set_gamma: Callback for programming the hardware gamma LUT 785 * 786 * Programs a default gamma ramp to hardware. 787 */ 788 void drm_crtc_fill_gamma_555(struct drm_crtc *crtc, drm_crtc_set_lut_func set_gamma) 789 { 790 unsigned int i; 791 792 for (i = 0; i < 32; ++i) 793 fill_gamma_555(crtc, i, i, i, i, set_gamma); 794 } 795 EXPORT_SYMBOL(drm_crtc_fill_gamma_555); 796 797 /* 798 * Color-LUT programming 799 */ 800 801 /** 802 * drm_crtc_load_palette_8 - Programs palette for C8-like formats 803 * @crtc: The displaying CRTC 804 * @lut: The palette to program 805 * @set_palette: Callback for programming the hardware palette 806 * 807 * Programs the palette specified in @lut to hardware. The input palette 808 * must have 256 entries per color component. 809 */ 810 void drm_crtc_load_palette_8(struct drm_crtc *crtc, const struct drm_color_lut *lut, 811 drm_crtc_set_lut_func set_palette) 812 { 813 unsigned int i; 814 815 for (i = 0; i < 256; ++i) 816 set_palette(crtc, i, lut[i].red, lut[i].green, lut[i].blue); 817 } 818 EXPORT_SYMBOL(drm_crtc_load_palette_8); 819 820 static void fill_palette_332(struct drm_crtc *crtc, u16 r, u16 g, u16 b, 821 drm_crtc_set_lut_func set_palette) 822 { 823 unsigned int i = (r << 5) | (g << 2) | b; /* 8-bit palette index */ 824 825 /* Expand R (3-bit) G (3-bit) and B (2-bit) values to 16-bit values */ 826 r = (r << 13) | (r << 10) | (r << 7) | (r << 4) | (r << 1) | (r >> 2); 827 g = (g << 13) | (g << 10) | (g << 7) | (g << 4) | (g << 1) | (g >> 2); 828 b = (b << 14) | (b << 12) | (b << 10) | (b << 8) | (b << 6) | (b << 4) | (b << 2) | b; 829 830 set_palette(crtc, i, r, g, b); 831 } 832 833 /** 834 * drm_crtc_fill_palette_332 - Programs a default palette for RGB332-like formats 835 * @crtc: The displaying CRTC 836 * @set_palette: Callback for programming the hardware gamma LUT 837 * 838 * Programs an RGB332 palette to hardware. 839 */ 840 void drm_crtc_fill_palette_332(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette) 841 { 842 unsigned int r, g, b; 843 844 /* Limits of 8-8-4 are the maximum number of values for each channel. */ 845 for (r = 0; r < 8; ++r) { 846 for (g = 0; g < 8; ++g) { 847 for (b = 0; b < 4; ++b) 848 fill_palette_332(crtc, r, g, b, set_palette); 849 } 850 } 851 } 852 EXPORT_SYMBOL(drm_crtc_fill_palette_332); 853 854 static void fill_palette_8(struct drm_crtc *crtc, unsigned int i, 855 drm_crtc_set_lut_func set_palette) 856 { 857 u16 Y = (i << 8) | i; // relative luminance 858 859 set_palette(crtc, i, Y, Y, Y); 860 } 861 862 /** 863 * drm_crtc_fill_palette_8 - Programs a default palette for C8-like formats 864 * @crtc: The displaying CRTC 865 * @set_palette: Callback for programming the hardware gamma LUT 866 * 867 * Programs a default palette to hardware. 868 */ 869 void drm_crtc_fill_palette_8(struct drm_crtc *crtc, drm_crtc_set_lut_func set_palette) 870 { 871 unsigned int i; 872 873 for (i = 0; i < 256; ++i) 874 fill_palette_8(crtc, i, set_palette); 875 } 876 EXPORT_SYMBOL(drm_crtc_fill_palette_8); 877 878 /** 879 * drm_color_lut32_check - check validity of extended lookup table 880 * @lut: property blob containing extended LUT to check 881 * @tests: bitmask of tests to run 882 * 883 * Helper to check whether a userspace-provided extended lookup table is valid and 884 * satisfies hardware requirements. Drivers pass a bitmask indicating which of 885 * the tests in &drm_color_lut_tests should be performed. 886 * 887 * Returns 0 on success, -EINVAL on failure. 888 */ 889 int drm_color_lut32_check(const struct drm_property_blob *lut, u32 tests) 890 { 891 const struct drm_color_lut32 *entry; 892 int i; 893 894 if (!lut || !tests) 895 return 0; 896 897 entry = lut->data; 898 for (i = 0; i < drm_color_lut32_size(lut); i++) { 899 if (tests & DRM_COLOR_LUT_EQUAL_CHANNELS) { 900 if (entry[i].red != entry[i].blue || 901 entry[i].red != entry[i].green) { 902 DRM_DEBUG_KMS("All LUT entries must have equal r/g/b\n"); 903 return -EINVAL; 904 } 905 } 906 907 if (i > 0 && tests & DRM_COLOR_LUT_NON_DECREASING) { 908 if (entry[i].red < entry[i - 1].red || 909 entry[i].green < entry[i - 1].green || 910 entry[i].blue < entry[i - 1].blue) { 911 DRM_DEBUG_KMS("LUT entries must never decrease.\n"); 912 return -EINVAL; 913 } 914 } 915 } 916 917 return 0; 918 } 919 EXPORT_SYMBOL(drm_color_lut32_check); 920