It is to be used to enable HDR by allowing userpace to create and pass 3D LUTs to kernel and hardware. new drm_colorop_type: DRM_COLOROP_3D_LUT.
Unified · Split
| @@ -807,6 +807,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p, · 806 unmodified lines | ||
| 807 | 807 | case DRM_COLOROP_MULTIPLIER: |
| 808 | 808 | drm_printf(p, "\tmultiplier=%llu\n", state->multiplier); |
| 809 | 809 | break; |
| 810 | + case DRM_COLOROP_3D_LUT: | |
| 811 | + drm_printf(p, "\tsize=%d\n", colorop->size); | |
| 812 | + drm_printf(p, "\tinterpolation=%s\n", | |
| 813 | + drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation)); | |
| 814 | + drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0); | |
| 815 | + break; | |
| 810 | 816 | default: |
| 811 | 817 | break; |
| 812 | 818 | } |
| @@ -705,6 +705,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop, · 704 unmodified lines | ||
| 705 | 705 | case DRM_COLOROP_CTM_3X4: |
| 706 | 706 | size = sizeof(struct drm_color_ctm_3x4); |
| 707 | 707 | break; |
| 708 | + case DRM_COLOROP_3D_LUT: | |
| 709 | + size = colorop->size * colorop->size * colorop->size * | |
| 710 | + sizeof(struct drm_color_lut32); | |
| 711 | + break; | |
| 708 | 712 | default: |
| 709 | 713 | /* should never get here */ |
| 710 | 714 | return -EINVAL; |
| @@ -732,6 +736,8 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop, · 21 unmodified lines | ||
| 732 | 736 | state->curve_1d_type = val; |
| 733 | 737 | } else if (property == colorop->multiplier_property) { |
| 734 | 738 | state->multiplier = val; |
| 739 | + } else if (property == colorop->lut3d_interpolation_property) { | |
| 740 | + colorop->lut3d_interpolation = val; | |
| 735 | 741 | } else if (property == colorop->data_property) { |
| 736 | 742 | return drm_atomic_color_set_data_property(colorop, state, |
| 737 | 743 | property, val); |
| @@ -763,6 +769,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop, · 25 unmodified lines | ||
| 763 | 769 | *val = state->multiplier; |
| 764 | 770 | else if (property == colorop->size_property) |
| 765 | 771 | *val = colorop->size; |
| 772 | + else if (property == colorop->lut3d_interpolation_property) | |
| 773 | + *val = colorop->lut3d_interpolation; | |
| 766 | 774 | else if (property == colorop->data_property) |
| 767 | 775 | *val = (state->data) ? state->data->base.id : 0; |
| 768 | 776 | else |
| @@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = { · 66 unmodified lines | ||
| 67 | 67 | { DRM_COLOROP_1D_LUT, "1D LUT" }, |
| 68 | 68 | { DRM_COLOROP_CTM_3X4, "3x4 Matrix"}, |
| 69 | 69 | { DRM_COLOROP_MULTIPLIER, "Multiplier"}, |
| 70 | + { DRM_COLOROP_3D_LUT, "3D LUT"}, | |
| 70 | 71 | }; |
| 71 | 72 | |
| 72 | 73 | static const char * const colorop_curve_1d_type_names[] = { |
| @@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] = · 9 unmodified lines | ||
| 82 | 83 | { DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" }, |
| 83 | 84 | }; |
| 84 | 85 | |
| 86 | + | |
| 87 | +static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = { | |
| 88 | + { DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" }, | |
| 89 | +}; | |
| 90 | + | |
| 85 | 91 | /* Init Helpers */ |
| 86 | 92 | |
| 87 | 93 | static int drm_plane_colorop_init(struct drm_device *dev, struct drm_colorop *colorop, |
| @@ -381,6 +387,51 @@ int drm_plane_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colo · 293 unmodified lines | ||
| 381 | 387 | } |
| 382 | 388 | EXPORT_SYMBOL(drm_plane_colorop_mult_init); |
| 383 | 389 | |
| 390 | +int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop, | |
| 391 | + struct drm_plane *plane, | |
| 392 | + uint32_t lut_size, | |
| 393 | + enum drm_colorop_lut3d_interpolation_type interpolation, | |
| 394 | + uint32_t flags) | |
| 395 | +{ | |
| 396 | + struct drm_property *prop; | |
| 397 | + int ret; | |
| 398 | + | |
| 399 | + ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, flags); | |
| 400 | + if (ret) | |
| 401 | + return ret; | |
| 402 | + | |
| 403 | + /* LUT size */ | |
| 404 | + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC, | |
| 405 | + "SIZE", 0, UINT_MAX); | |
| 406 | + if (!prop) | |
| 407 | + return -ENOMEM; | |
| 408 | + | |
| 409 | + colorop->size_property = prop; | |
| 410 | + drm_object_attach_property(&colorop->base, colorop->size_property, lut_size); | |
| 411 | + colorop->size = lut_size; | |
| 412 | + | |
| 413 | + /* interpolation */ | |
| 414 | + prop = drm_property_create_enum(dev, 0, "LUT3D_INTERPOLATION", | |
| 415 | + drm_colorop_lut3d_interpolation_list, | |
| 416 | + ARRAY_SIZE(drm_colorop_lut3d_interpolation_list)); | |
| 417 | + if (!prop) | |
| 418 | + return -ENOMEM; | |
| 419 | + | |
| 420 | + colorop->lut3d_interpolation_property = prop; | |
| 421 | + drm_object_attach_property(&colorop->base, prop, interpolation); | |
| 422 | + colorop->lut3d_interpolation = interpolation; | |
| 423 | + | |
| 424 | + /* data */ | |
| 425 | + ret = drm_colorop_create_data_prop(dev, colorop); | |
| 426 | + if (ret) | |
| 427 | + return ret; | |
| 428 | + | |
| 429 | + drm_colorop_reset(colorop); | |
| 430 | + | |
| 431 | + return 0; | |
| 432 | +} | |
| 433 | +EXPORT_SYMBOL(drm_plane_colorop_3dlut_init); | |
| 434 | + | |
| 384 | 435 | static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop, |
| 385 | 436 | struct drm_colorop_state *state) |
| 386 | 437 | { |
| @@ -472,7 +523,13 @@ static const char * const colorop_type_name[] = { · 85 unmodified lines | ||
| 472 | 523 | [DRM_COLOROP_1D_LUT] = "1D LUT", |
| 473 | 524 | [DRM_COLOROP_CTM_3X4] = "3x4 Matrix", |
| 474 | 525 | [DRM_COLOROP_MULTIPLIER] = "Multiplier", |
| 526 | + [DRM_COLOROP_3D_LUT] = "3D LUT", | |
| 527 | +}; | |
| 528 | + | |
| 529 | +static const char * const colorop_lu3d_interpolation_name[] = { | |
| 530 | + [DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL] = "Tetrahedral", | |
| 475 | 531 | }; |
| 532 | + | |
| 476 | 533 | static const char * const colorop_lut1d_interpolation_name[] = { |
| 477 | 534 | [DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear", |
| 478 | 535 | }; |
| @@ -508,6 +565,21 @@ const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_inte · 29 unmodified lines | ||
| 508 | 565 | return colorop_lut1d_interpolation_name[type]; |
| 509 | 566 | } |
| 510 | 567 | |
| 568 | +/** | |
| 569 | + * drm_get_colorop_lut3d_interpolation_name - return a string for interpolation type | |
| 570 | + * @type: interpolation type to compute name of | |
| 571 | + * | |
| 572 | + * In contrast to the other drm_get_*_name functions this one here returns a | |
| 573 | + * const pointer and hence is threadsafe. | |
| 574 | + */ | |
| 575 | +const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type) | |
| 576 | +{ | |
| 577 | + if (WARN_ON(type >= ARRAY_SIZE(colorop_lu3d_interpolation_name))) | |
| 578 | + return "unknown"; | |
| 579 | + | |
| 580 | + return colorop_lu3d_interpolation_name[type]; | |
| 581 | +} | |
| 582 | + | |
| 511 | 583 | /** |
| 512 | 584 | * drm_colorop_set_next_property - sets the next pointer |
| 513 | 585 | * @colorop: drm colorop |
| @@ -283,6 +283,14 @@ struct drm_colorop { · 282 unmodified lines | ||
| 283 | 283 | */ |
| 284 | 284 | enum drm_colorop_lut1d_interpolation_type lut1d_interpolation; |
| 285 | 285 | |
| 286 | + /** | |
| 287 | + * @lut3d_interpolation: | |
| 288 | + * | |
| 289 | + * Read-only | |
| 290 | + * Interpolation for DRM_COLOROP_3D_LUT | |
| 291 | + */ | |
| 292 | + enum drm_colorop_lut3d_interpolation_type lut3d_interpolation; | |
| 293 | + | |
| 286 | 294 | /** |
| 287 | 295 | * @lut1d_interpolation_property: |
| 288 | 296 | * |
| @@ -311,6 +319,13 @@ struct drm_colorop { · 22 unmodified lines | ||
| 311 | 319 | */ |
| 312 | 320 | struct drm_property *size_property; |
| 313 | 321 | |
| 322 | + /** | |
| 323 | + * @lut3d_interpolation_property: | |
| 324 | + * | |
| 325 | + * Read-only property for DRM_COLOROP_3D_LUT interpolation | |
| 326 | + */ | |
| 327 | + struct drm_property *lut3d_interpolation_property; | |
| 328 | + | |
| 314 | 329 | /** |
| 315 | 330 | * @data_property: |
| 316 | 331 | * |
| @@ -366,6 +381,11 @@ int drm_plane_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *c · 49 unmodified lines | ||
| 366 | 381 | struct drm_plane *plane, uint32_t flags); |
| 367 | 382 | int drm_plane_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop, |
| 368 | 383 | struct drm_plane *plane, uint32_t flags); |
| 384 | +int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop, | |
| 385 | + struct drm_plane *plane, | |
| 386 | + uint32_t lut_size, | |
| 387 | + enum drm_colorop_lut3d_interpolation_type interpolation, | |
| 388 | + uint32_t flags); | |
| 369 | 389 | |
| 370 | 390 | struct drm_colorop_state * |
| 371 | 391 | drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop); |
| @@ -418,6 +438,9 @@ const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type ty · 46 unmodified lines | ||
| 418 | 438 | const char * |
| 419 | 439 | drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type); |
| 420 | 440 | |
| 441 | +const char * | |
| 442 | +drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type); | |
| 443 | + | |
| 421 | 444 | void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next); |
| 422 | 445 | |
| 423 | 446 | #endif /* __DRM_COLOROP_H__ */ |
| @@ -942,6 +942,40 @@ enum drm_colorop_type { · 941 unmodified lines | ||
| 942 | 942 | * property. |
| 943 | 943 | */ |
| 944 | 944 | DRM_COLOROP_MULTIPLIER, |
| 945 | + | |
| 946 | + /** | |
| 947 | + * @DRM_COLOROP_3D_LUT: | |
| 948 | + * | |
| 949 | + * enum string "3D LUT" | |
| 950 | + * | |
| 951 | + * A 3D LUT of &drm_color_lut32 entries, | |
| 952 | + * packed into a blob via the DATA property. The driver's expected | |
| 953 | + * LUT size is advertised via the SIZE property, i.e., a 3D LUT with | |
| 954 | + * 17x17x17 entries will have SIZE set to 17. | |
| 955 | + * | |
| 956 | + * The DATA blob is a 3D array of struct drm_color_lut32 with dimension | |
| 957 | + * length of "size". | |
| 958 | + * The LUT elements are traversed like so: | |
| 959 | + * | |
| 960 | + * for B in range 0..n | |
| 961 | + * for G in range 0..n | |
| 962 | + * for R in range 0..n | |
| 963 | + * index = R + n * (G + n * B) | |
| 964 | + * color = lut3d[index] | |
| 965 | + */ | |
| 966 | + DRM_COLOROP_3D_LUT, | |
| 967 | +}; | |
| 968 | + | |
| 969 | +/** | |
| 970 | + * enum drm_colorop_lut3d_interpolation_type - type of 3DLUT interpolation | |
| 971 | + */ | |
| 972 | +enum drm_colorop_lut3d_interpolation_type { | |
| 973 | + /** | |
| 974 | + * @DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL: | |
| 975 | + * | |
| 976 | + * Tetrahedral 3DLUT interpolation | |
| 977 | + */ | |
| 978 | + DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, | |
| 945 | 979 | }; |
| 946 | 980 | |
| 947 | 981 | /** |