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

drm: introduce pipe color correction properties

Patch based on a previous series by Shashank Sharma.

This introduces optional properties to enable color correction at the
pipe level. It relies on 3 transformations applied to every pixels
displayed. First a lookup into a degamma table, then a multiplication
of the rgb components by a 3x3 matrix and finally another lookup into
a gamma table.

The following properties can be added to a pipe :
- DEGAMMA_LUT : blob containing degamma LUT
- DEGAMMA_LUT_SIZE : number of elements in DEGAMMA_LUT
- CTM : transformation matrix applied after the degamma LUT
- GAMMA_LUT : blob containing gamma LUT
- GAMMA_LUT_SIZE : number of elements in GAMMA_LUT

DEGAMMA_LUT_SIZE and GAMMA_LUT_SIZE are read only properties, set by
the driver to tell userspace applications what sizes should be the
lookup tables in DEGAMMA_LUT and GAMMA_LUT.

A helper is also provided so legacy gamma correction is redirected
through these new properties.

v2: Register LUT size properties as range

v3: Fix round in drm_color_lut_get_value() helper
More docs on how degamma/gamma properties are used

v4: Update contributors

v5: Rename CTM_MATRIX property to CTM (Doh!)
Add legacy gamma_set atomic helper
Describe CTM/LUT acronyms in the kernel doc

v6: Fix missing blob unref in drm_atomic_helper_crtc_reset

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Kumar, Kiran S <kiran.s.kumar@intel.com>
Signed-off-by: Kausal Malladi <kausalmalladi@gmail.com>
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Acked-by: Rob Bradford <robert.bradford@intel.com>
[danvet: CrOS maintainers are also happy with the userspacde side:
https://codereview.chromium.org/1182063002/ ]
Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1456506302-640-4-git-send-email-lionel.g.landwerlin@intel.com

authored by

Lionel Landwerlin and committed by
Daniel Vetter
5488dc16 9b8d1e53

+386 -6
+57 -2
Documentation/DocBook/gpu.tmpl
··· 1816 1816 <td valign="top" >Description/Restrictions</td> 1817 1817 </tr> 1818 1818 <tr> 1819 - <td rowspan="37" valign="top" >DRM</td> 1819 + <td rowspan="42" valign="top" >DRM</td> 1820 1820 <td valign="top" >Generic</td> 1821 1821 <td valign="top" >“rotation”</td> 1822 1822 <td valign="top" >BITMASK</td> ··· 2068 2068 <td valign="top" >property to suggest an Y offset for a connector</td> 2069 2069 </tr> 2070 2070 <tr> 2071 - <td rowspan="3" valign="top" >Optional</td> 2071 + <td rowspan="8" valign="top" >Optional</td> 2072 2072 <td valign="top" >“scaling mode”</td> 2073 2073 <td valign="top" >ENUM</td> 2074 2074 <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td> ··· 2090 2090 <td valign="top" >{ "Off", "On", "Annotate" }</td> 2091 2091 <td valign="top" >Connector</td> 2092 2092 <td valign="top" >TBD</td> 2093 + </tr> 2094 + <tr> 2095 + <td valign="top" >“DEGAMMA_LUT”</td> 2096 + <td valign="top" >BLOB</td> 2097 + <td valign="top" >0</td> 2098 + <td valign="top" >CRTC</td> 2099 + <td valign="top" >DRM property to set the degamma lookup table 2100 + (LUT) mapping pixel data from the framebuffer before it is 2101 + given to the transformation matrix. The data is an interpreted 2102 + as an array of struct drm_color_lut elements. Hardware might 2103 + choose not to use the full precision of the LUT elements nor 2104 + use all the elements of the LUT (for example the hardware 2105 + might choose to interpolate between LUT[0] and LUT[4]). </td> 2106 + </tr> 2107 + <tr> 2108 + <td valign="top" >“DEGAMMA_LUT_SIZE”</td> 2109 + <td valign="top" >RANGE | IMMUTABLE</td> 2110 + <td valign="top" >Min=0, Max=UINT_MAX</td> 2111 + <td valign="top" >CRTC</td> 2112 + <td valign="top" >DRM property to gives the size of the lookup 2113 + table to be set on the DEGAMMA_LUT property (the size depends 2114 + on the underlying hardware).</td> 2115 + </tr> 2116 + <tr> 2117 + <td valign="top" >“CTM”</td> 2118 + <td valign="top" >BLOB</td> 2119 + <td valign="top" >0</td> 2120 + <td valign="top" >CRTC</td> 2121 + <td valign="top" >DRM property to set the current 2122 + transformation matrix (CTM) apply to pixel data after the 2123 + lookup through the degamma LUT and before the lookup through 2124 + the gamma LUT. The data is an interpreted as a struct 2125 + drm_color_ctm.</td> 2126 + </tr> 2127 + <tr> 2128 + <td valign="top" >“GAMMA_LUT”</td> 2129 + <td valign="top" >BLOB</td> 2130 + <td valign="top" >0</td> 2131 + <td valign="top" >CRTC</td> 2132 + <td valign="top" >DRM property to set the gamma lookup table 2133 + (LUT) mapping pixel data after to the transformation matrix to 2134 + data sent to the connector. The data is an interpreted as an 2135 + array of struct drm_color_lut elements. Hardware might choose 2136 + not to use the full precision of the LUT elements nor use all 2137 + the elements of the LUT (for example the hardware might choose 2138 + to interpolate between LUT[0] and LUT[4]).</td> 2139 + </tr> 2140 + <tr> 2141 + <td valign="top" >“GAMMA_LUT_SIZE”</td> 2142 + <td valign="top" >RANGE | IMMUTABLE</td> 2143 + <td valign="top" >Min=0, Max=UINT_MAX</td> 2144 + <td valign="top" >CRTC</td> 2145 + <td valign="top" >DRM property to gives the size of the lookup 2146 + table to be set on the GAMMA_LUT property (the size depends on 2147 + the underlying hardware).</td> 2093 2148 </tr> 2094 2149 <tr> 2095 2150 <td rowspan="20" valign="top" >i915</td>
+86 -2
drivers/gpu/drm/drm_atomic.c
··· 28 28 29 29 #include <drm/drmP.h> 30 30 #include <drm/drm_atomic.h> 31 + #include <drm/drm_mode.h> 31 32 #include <drm/drm_plane_helper.h> 32 33 33 34 /** ··· 389 388 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); 390 389 391 390 /** 391 + * drm_atomic_replace_property_blob - replace a blob property 392 + * @blob: a pointer to the member blob to be replaced 393 + * @new_blob: the new blob to replace with 394 + * @expected_size: the expected size of the new blob 395 + * @replaced: whether the blob has been replaced 396 + * 397 + * RETURNS: 398 + * Zero on success, error code on failure 399 + */ 400 + static void 401 + drm_atomic_replace_property_blob(struct drm_property_blob **blob, 402 + struct drm_property_blob *new_blob, 403 + bool *replaced) 404 + { 405 + struct drm_property_blob *old_blob = *blob; 406 + 407 + if (old_blob == new_blob) 408 + return; 409 + 410 + if (old_blob) 411 + drm_property_unreference_blob(old_blob); 412 + if (new_blob) 413 + drm_property_reference_blob(new_blob); 414 + *blob = new_blob; 415 + *replaced = true; 416 + 417 + return; 418 + } 419 + 420 + static int 421 + drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, 422 + struct drm_property_blob **blob, 423 + uint64_t blob_id, 424 + ssize_t expected_size, 425 + bool *replaced) 426 + { 427 + struct drm_device *dev = crtc->dev; 428 + struct drm_property_blob *new_blob = NULL; 429 + 430 + if (blob_id != 0) { 431 + new_blob = drm_property_lookup_blob(dev, blob_id); 432 + if (new_blob == NULL) 433 + return -EINVAL; 434 + if (expected_size > 0 && expected_size != new_blob->length) 435 + return -EINVAL; 436 + } 437 + 438 + drm_atomic_replace_property_blob(blob, new_blob, replaced); 439 + 440 + return 0; 441 + } 442 + 443 + /** 392 444 * drm_atomic_crtc_set_property - set property on CRTC 393 445 * @crtc: the drm CRTC to set a property on 394 446 * @state: the state object to update with the new property value ··· 463 409 { 464 410 struct drm_device *dev = crtc->dev; 465 411 struct drm_mode_config *config = &dev->mode_config; 412 + bool replaced = false; 466 413 int ret; 467 414 468 415 if (property == config->prop_active) ··· 474 419 ret = drm_atomic_set_mode_prop_for_crtc(state, mode); 475 420 drm_property_unreference_blob(mode); 476 421 return ret; 477 - } 478 - else if (crtc->funcs->atomic_set_property) 422 + } else if (property == config->degamma_lut_property) { 423 + ret = drm_atomic_replace_property_blob_from_id(crtc, 424 + &state->degamma_lut, 425 + val, 426 + -1, 427 + &replaced); 428 + state->color_mgmt_changed = replaced; 429 + return ret; 430 + } else if (property == config->ctm_property) { 431 + ret = drm_atomic_replace_property_blob_from_id(crtc, 432 + &state->ctm, 433 + val, 434 + sizeof(struct drm_color_ctm), 435 + &replaced); 436 + state->color_mgmt_changed = replaced; 437 + return ret; 438 + } else if (property == config->gamma_lut_property) { 439 + ret = drm_atomic_replace_property_blob_from_id(crtc, 440 + &state->gamma_lut, 441 + val, 442 + -1, 443 + &replaced); 444 + state->color_mgmt_changed = replaced; 445 + return ret; 446 + } else if (crtc->funcs->atomic_set_property) 479 447 return crtc->funcs->atomic_set_property(crtc, state, property, val); 480 448 else 481 449 return -EINVAL; ··· 534 456 *val = state->active; 535 457 else if (property == config->prop_mode_id) 536 458 *val = (state->mode_blob) ? state->mode_blob->base.id : 0; 459 + else if (property == config->degamma_lut_property) 460 + *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; 461 + else if (property == config->ctm_property) 462 + *val = (state->ctm) ? state->ctm->base.id : 0; 463 + else if (property == config->gamma_lut_property) 464 + *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; 537 465 else if (crtc->funcs->atomic_get_property) 538 466 return crtc->funcs->atomic_get_property(crtc, state, property, val); 539 467 else
+109 -1
drivers/gpu/drm/drm_atomic_helper.c
··· 2495 2495 */ 2496 2496 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) 2497 2497 { 2498 - if (crtc->state) 2498 + if (crtc->state) { 2499 2499 drm_property_unreference_blob(crtc->state->mode_blob); 2500 + drm_property_unreference_blob(crtc->state->degamma_lut); 2501 + drm_property_unreference_blob(crtc->state->ctm); 2502 + drm_property_unreference_blob(crtc->state->gamma_lut); 2503 + } 2500 2504 kfree(crtc->state); 2501 2505 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); 2502 2506 ··· 2524 2520 2525 2521 if (state->mode_blob) 2526 2522 drm_property_reference_blob(state->mode_blob); 2523 + if (state->degamma_lut) 2524 + drm_property_reference_blob(state->degamma_lut); 2525 + if (state->ctm) 2526 + drm_property_reference_blob(state->ctm); 2527 + if (state->gamma_lut) 2528 + drm_property_reference_blob(state->gamma_lut); 2527 2529 state->mode_changed = false; 2528 2530 state->active_changed = false; 2529 2531 state->planes_changed = false; 2530 2532 state->connectors_changed = false; 2533 + state->color_mgmt_changed = false; 2531 2534 state->event = NULL; 2532 2535 } 2533 2536 EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); ··· 2575 2564 struct drm_crtc_state *state) 2576 2565 { 2577 2566 drm_property_unreference_blob(state->mode_blob); 2567 + drm_property_unreference_blob(state->degamma_lut); 2568 + drm_property_unreference_blob(state->ctm); 2569 + drm_property_unreference_blob(state->gamma_lut); 2578 2570 } 2579 2571 EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); 2580 2572 ··· 2891 2877 kfree(state); 2892 2878 } 2893 2879 EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); 2880 + 2881 + /** 2882 + * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table 2883 + * @crtc: CRTC object 2884 + * @red: red correction table 2885 + * @green: green correction table 2886 + * @blue: green correction table 2887 + * @start: 2888 + * @size: size of the tables 2889 + * 2890 + * Implements support for legacy gamma correction table for drivers 2891 + * that support color management through the DEGAMMA_LUT/GAMMA_LUT 2892 + * properties. 2893 + */ 2894 + void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 2895 + u16 *red, u16 *green, u16 *blue, 2896 + uint32_t start, uint32_t size) 2897 + { 2898 + struct drm_device *dev = crtc->dev; 2899 + struct drm_mode_config *config = &dev->mode_config; 2900 + struct drm_atomic_state *state; 2901 + struct drm_crtc_state *crtc_state; 2902 + struct drm_property_blob *blob = NULL; 2903 + struct drm_color_lut *blob_data; 2904 + int i, ret = 0; 2905 + 2906 + state = drm_atomic_state_alloc(crtc->dev); 2907 + if (!state) 2908 + return; 2909 + 2910 + blob = drm_property_create_blob(dev, 2911 + sizeof(struct drm_color_lut) * size, 2912 + NULL); 2913 + if (!blob) { 2914 + ret = -ENOMEM; 2915 + goto fail; 2916 + } 2917 + 2918 + /* Prepare GAMMA_LUT with the legacy values. */ 2919 + blob_data = (struct drm_color_lut *) blob->data; 2920 + for (i = 0; i < size; i++) { 2921 + blob_data[i].red = red[i]; 2922 + blob_data[i].green = green[i]; 2923 + blob_data[i].blue = blue[i]; 2924 + } 2925 + 2926 + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; 2927 + retry: 2928 + crtc_state = drm_atomic_get_crtc_state(state, crtc); 2929 + if (IS_ERR(crtc_state)) { 2930 + ret = PTR_ERR(crtc_state); 2931 + goto fail; 2932 + } 2933 + 2934 + /* Reset DEGAMMA_LUT and CTM properties. */ 2935 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2936 + config->degamma_lut_property, 0); 2937 + if (ret) 2938 + goto fail; 2939 + 2940 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2941 + config->ctm_property, 0); 2942 + if (ret) 2943 + goto fail; 2944 + 2945 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2946 + config->gamma_lut_property, blob->base.id); 2947 + if (ret) 2948 + goto fail; 2949 + 2950 + ret = drm_atomic_commit(state); 2951 + if (ret) 2952 + goto fail; 2953 + 2954 + /* Driver takes ownership of state on successful commit. */ 2955 + 2956 + drm_property_unreference_blob(blob); 2957 + 2958 + return; 2959 + fail: 2960 + if (ret == -EDEADLK) 2961 + goto backoff; 2962 + 2963 + drm_atomic_state_free(state); 2964 + drm_property_unreference_blob(blob); 2965 + 2966 + return; 2967 + backoff: 2968 + drm_atomic_state_clear(state); 2969 + drm_atomic_legacy_backoff(state); 2970 + 2971 + goto retry; 2972 + } 2973 + EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+35
drivers/gpu/drm/drm_crtc.c
··· 1563 1563 return -ENOMEM; 1564 1564 dev->mode_config.prop_mode_id = prop; 1565 1565 1566 + prop = drm_property_create(dev, 1567 + DRM_MODE_PROP_BLOB, 1568 + "DEGAMMA_LUT", 0); 1569 + if (!prop) 1570 + return -ENOMEM; 1571 + dev->mode_config.degamma_lut_property = prop; 1572 + 1573 + prop = drm_property_create_range(dev, 1574 + DRM_MODE_PROP_IMMUTABLE, 1575 + "DEGAMMA_LUT_SIZE", 0, UINT_MAX); 1576 + if (!prop) 1577 + return -ENOMEM; 1578 + dev->mode_config.degamma_lut_size_property = prop; 1579 + 1580 + prop = drm_property_create(dev, 1581 + DRM_MODE_PROP_BLOB, 1582 + "CTM", 0); 1583 + if (!prop) 1584 + return -ENOMEM; 1585 + dev->mode_config.ctm_property = prop; 1586 + 1587 + prop = drm_property_create(dev, 1588 + DRM_MODE_PROP_BLOB, 1589 + "GAMMA_LUT", 0); 1590 + if (!prop) 1591 + return -ENOMEM; 1592 + dev->mode_config.gamma_lut_property = prop; 1593 + 1594 + prop = drm_property_create_range(dev, 1595 + DRM_MODE_PROP_IMMUTABLE, 1596 + "GAMMA_LUT_SIZE", 0, UINT_MAX); 1597 + if (!prop) 1598 + return -ENOMEM; 1599 + dev->mode_config.gamma_lut_size_property = prop; 1600 + 1566 1601 return 0; 1567 1602 } 1568 1603
+33
drivers/gpu/drm/drm_crtc_helper.c
··· 1075 1075 return drm_plane_helper_commit(plane, plane_state, old_fb); 1076 1076 } 1077 1077 EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); 1078 + 1079 + /** 1080 + * drm_helper_crtc_enable_color_mgmt - enable color management properties 1081 + * @crtc: DRM CRTC 1082 + * @degamma_lut_size: the size of the degamma lut (before CSC) 1083 + * @gamma_lut_size: the size of the gamma lut (after CSC) 1084 + * 1085 + * This function lets the driver enable the color correction properties on a 1086 + * CRTC. This includes 3 degamma, csc and gamma properties that userspace can 1087 + * set and 2 size properties to inform the userspace of the lut sizes. 1088 + */ 1089 + void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, 1090 + int degamma_lut_size, 1091 + int gamma_lut_size) 1092 + { 1093 + struct drm_device *dev = crtc->dev; 1094 + struct drm_mode_config *config = &dev->mode_config; 1095 + 1096 + drm_object_attach_property(&crtc->base, 1097 + config->degamma_lut_property, 0); 1098 + drm_object_attach_property(&crtc->base, 1099 + config->ctm_property, 0); 1100 + drm_object_attach_property(&crtc->base, 1101 + config->gamma_lut_property, 0); 1102 + 1103 + drm_object_attach_property(&crtc->base, 1104 + config->degamma_lut_size_property, 1105 + degamma_lut_size); 1106 + drm_object_attach_property(&crtc->base, 1107 + config->gamma_lut_size_property, 1108 + gamma_lut_size); 1109 + } 1110 + EXPORT_SYMBOL(drm_helper_crtc_enable_color_mgmt);
+3
include/drm/drm_atomic_helper.h
··· 146 146 struct drm_connector_state *state); 147 147 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, 148 148 struct drm_connector_state *state); 149 + void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 150 + u16 *red, u16 *green, u16 *blue, 151 + uint32_t start, uint32_t size); 149 152 150 153 /** 151 154 * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
+45 -1
include/drm/drm_crtc.h
··· 305 305 * @mode_changed: crtc_state->mode or crtc_state->enable has been changed 306 306 * @active_changed: crtc_state->active has been toggled. 307 307 * @connectors_changed: connectors to this crtc have been updated 308 + * @color_mgmt_changed: color management properties have changed (degamma or 309 + * gamma LUT or CSC matrix) 308 310 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes 309 311 * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors 310 312 * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders ··· 314 312 * update to ensure framebuffer cleanup isn't done too early 315 313 * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings 316 314 * @mode: current mode timings 315 + * @degamma_lut: Lookup table for converting framebuffer pixel data 316 + * before apply the conversion matrix 317 + * @ctm: Transformation matrix 318 + * @gamma_lut: Lookup table for converting pixel data after the 319 + * conversion matrix 317 320 * @event: optional pointer to a DRM event to signal upon completion of the 318 321 * state update 319 322 * @state: backpointer to global drm_atomic_state ··· 340 333 bool mode_changed : 1; 341 334 bool active_changed : 1; 342 335 bool connectors_changed : 1; 336 + bool color_mgmt_changed : 1; 343 337 344 338 /* attached planes bitmask: 345 339 * WARNING: transitional helpers do not maintain plane_mask so ··· 362 354 363 355 /* blob property to expose current mode to atomic userspace */ 364 356 struct drm_property_blob *mode_blob; 357 + 358 + /* blob property to expose color management to userspace */ 359 + struct drm_property_blob *degamma_lut; 360 + struct drm_property_blob *ctm; 361 + struct drm_property_blob *gamma_lut; 365 362 366 363 struct drm_pending_vblank_event *event; 367 364 ··· 770 757 int x, y; 771 758 const struct drm_crtc_funcs *funcs; 772 759 773 - /* CRTC gamma size for reporting to userspace */ 760 + /* Legacy FB CRTC gamma size for reporting to userspace */ 774 761 uint32_t gamma_size; 775 762 uint16_t *gamma_store; 776 763 ··· 2040 2027 * @property_blob_list: list of all the blob property objects 2041 2028 * @blob_lock: mutex for blob property allocation and management 2042 2029 * @*_property: core property tracking 2030 + * @degamma_lut_property: LUT used to convert the framebuffer's colors to linear 2031 + * gamma 2032 + * @degamma_lut_size_property: size of the degamma LUT as supported by the 2033 + * driver (read-only) 2034 + * @ctm_property: Matrix used to convert colors after the lookup in the 2035 + * degamma LUT 2036 + * @gamma_lut_property: LUT used to convert the colors, after the CSC matrix, to 2037 + * the gamma space of the connected screen (read-only) 2038 + * @gamma_lut_size_property: size of the gamma LUT as supported by the driver 2043 2039 * @preferred_depth: preferred RBG pixel depth, used by fb helpers 2044 2040 * @prefer_shadow: hint to userspace to prefer shadow-fb rendering 2045 2041 * @async_page_flip: does this device support async flips on the primary plane? ··· 2149 2127 struct drm_property *scaling_mode_property; 2150 2128 struct drm_property *aspect_ratio_property; 2151 2129 struct drm_property *dirty_info_property; 2130 + 2131 + /* Optional color correction properties */ 2132 + struct drm_property *degamma_lut_property; 2133 + struct drm_property *degamma_lut_size_property; 2134 + struct drm_property *ctm_property; 2135 + struct drm_property *gamma_lut_property; 2136 + struct drm_property *gamma_lut_size_property; 2152 2137 2153 2138 /* properties for virtual machine layout */ 2154 2139 struct drm_property *suggested_x_property; ··· 2577 2548 struct drm_mode_object *mo; 2578 2549 mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY); 2579 2550 return mo ? obj_to_property(mo) : NULL; 2551 + } 2552 + 2553 + /* 2554 + * Extract a degamma/gamma LUT value provided by user and round it to the 2555 + * precision supported by the hardware. 2556 + */ 2557 + static inline uint32_t drm_color_lut_extract(uint32_t user_input, 2558 + uint32_t bit_precision) 2559 + { 2560 + uint32_t val = user_input + (1 << (16 - bit_precision - 1)); 2561 + uint32_t max = 0xffff >> (16 - bit_precision); 2562 + 2563 + val >>= 16 - bit_precision; 2564 + 2565 + return clamp_val(val, 0, max); 2580 2566 } 2581 2567 2582 2568 /* Plane list iterator for legacy (overlay only) planes. */
+3
include/drm/drm_crtc_helper.h
··· 48 48 struct drm_display_mode *mode, 49 49 int x, int y, 50 50 struct drm_framebuffer *old_fb); 51 + extern void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, 52 + int degamma_lut_size, 53 + int gamma_lut_size); 51 54 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); 52 55 extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); 53 56
+15
include/uapi/drm/drm_mode.h
··· 487 487 __u64 blue; 488 488 }; 489 489 490 + struct drm_color_ctm { 491 + /* Conversion matrix in S31.32 format. */ 492 + __s64 matrix[9]; 493 + }; 494 + 495 + struct drm_color_lut { 496 + /* 497 + * Data is U0.16 fixed point format. 498 + */ 499 + __u16 red; 500 + __u16 green; 501 + __u16 blue; 502 + __u16 reserved; 503 + }; 504 + 490 505 #define DRM_MODE_PAGE_FLIP_EVENT 0x01 491 506 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 492 507 #define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC)