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

drm/colorop: Add 3D LUT support to color pipeline

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.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Sebastian Wick <sebastian.wick@redhat.com>
Signed-off-by: Simon Ser <contact@emersion.fr>
Link: https://patch.msgid.link/20251115000237.3561250-46-alex.hung@amd.com

authored by

Alex Hung and committed by
Simon Ser
db971856 24689634

+143
+6
drivers/gpu/drm/drm_atomic.c
··· 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 }
+8
drivers/gpu/drm/drm_atomic_uapi.c
··· 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; ··· 736 732 state->curve_1d_type = val; 737 733 } else if (property == colorop->multiplier_property) { 738 734 state->multiplier = val; 735 + } else if (property == colorop->lut3d_interpolation_property) { 736 + colorop->lut3d_interpolation = val; 739 737 } else if (property == colorop->data_property) { 740 738 return drm_atomic_color_set_data_property(colorop, state, 741 739 property, val); ··· 769 763 *val = state->multiplier; 770 764 else if (property == colorop->size_property) 771 765 *val = colorop->size; 766 + else if (property == colorop->lut3d_interpolation_property) 767 + *val = colorop->lut3d_interpolation; 772 768 else if (property == colorop->data_property) 773 769 *val = (state->data) ? state->data->base.id : 0; 774 770 else
+72
drivers/gpu/drm/drm_colorop.c
··· 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[] = { ··· 81 80 82 81 static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] = { 83 82 { DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" }, 83 + }; 84 + 85 + 86 + static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = { 87 + { DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" }, 84 88 }; 85 89 86 90 /* Init Helpers */ ··· 387 381 } 388 382 EXPORT_SYMBOL(drm_plane_colorop_mult_init); 389 383 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) 389 + { 390 + struct drm_property *prop; 391 + int ret; 392 + 393 + ret = drm_plane_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, flags); 394 + if (ret) 395 + return ret; 396 + 397 + /* LUT size */ 398 + prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC, 399 + "SIZE", 0, UINT_MAX); 400 + if (!prop) 401 + return -ENOMEM; 402 + 403 + colorop->size_property = prop; 404 + drm_object_attach_property(&colorop->base, colorop->size_property, lut_size); 405 + colorop->size = lut_size; 406 + 407 + /* interpolation */ 408 + prop = drm_property_create_enum(dev, 0, "LUT3D_INTERPOLATION", 409 + drm_colorop_lut3d_interpolation_list, 410 + ARRAY_SIZE(drm_colorop_lut3d_interpolation_list)); 411 + if (!prop) 412 + return -ENOMEM; 413 + 414 + colorop->lut3d_interpolation_property = prop; 415 + drm_object_attach_property(&colorop->base, prop, interpolation); 416 + colorop->lut3d_interpolation = interpolation; 417 + 418 + /* data */ 419 + ret = drm_colorop_create_data_prop(dev, colorop); 420 + if (ret) 421 + return ret; 422 + 423 + drm_colorop_reset(colorop); 424 + 425 + return 0; 426 + } 427 + EXPORT_SYMBOL(drm_plane_colorop_3dlut_init); 428 + 390 429 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop, 391 430 struct drm_colorop_state *state) 392 431 { ··· 523 472 [DRM_COLOROP_1D_LUT] = "1D LUT", 524 473 [DRM_COLOROP_CTM_3X4] = "3x4 Matrix", 525 474 [DRM_COLOROP_MULTIPLIER] = "Multiplier", 475 + [DRM_COLOROP_3D_LUT] = "3D LUT", 526 476 }; 477 + 478 + static const char * const colorop_lu3d_interpolation_name[] = { 479 + [DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL] = "Tetrahedral", 480 + }; 481 + 527 482 static const char * const colorop_lut1d_interpolation_name[] = { 528 483 [DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear", 529 484 }; ··· 563 506 return "unknown"; 564 507 565 508 return colorop_lut1d_interpolation_name[type]; 509 + } 510 + 511 + /** 512 + * drm_get_colorop_lut3d_interpolation_name - return a string for interpolation type 513 + * @type: interpolation type to compute name of 514 + * 515 + * In contrast to the other drm_get_*_name functions this one here returns a 516 + * const pointer and hence is threadsafe. 517 + */ 518 + const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type) 519 + { 520 + if (WARN_ON(type >= ARRAY_SIZE(colorop_lu3d_interpolation_name))) 521 + return "unknown"; 522 + 523 + return colorop_lu3d_interpolation_name[type]; 566 524 } 567 525 568 526 /**
+23
include/drm/drm_colorop.h
··· 284 284 enum drm_colorop_lut1d_interpolation_type lut1d_interpolation; 285 285 286 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 + 294 + /** 287 295 * @lut1d_interpolation_property: 288 296 * 289 297 * Read-only property for DRM_COLOROP_1D_LUT interpolation ··· 318 310 * Size property for custom LUT from userspace. 319 311 */ 320 312 struct drm_property *size_property; 313 + 314 + /** 315 + * @lut3d_interpolation_property: 316 + * 317 + * Read-only property for DRM_COLOROP_3D_LUT interpolation 318 + */ 319 + struct drm_property *lut3d_interpolation_property; 321 320 322 321 /** 323 322 * @data_property: ··· 381 366 struct drm_plane *plane, uint32_t flags); 382 367 int drm_plane_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop, 383 368 struct drm_plane *plane, uint32_t flags); 369 + int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop, 370 + struct drm_plane *plane, 371 + uint32_t lut_size, 372 + enum drm_colorop_lut3d_interpolation_type interpolation, 373 + uint32_t flags); 384 374 385 375 struct drm_colorop_state * 386 376 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop); ··· 437 417 438 418 const char * 439 419 drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type); 420 + 421 + const char * 422 + drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type); 440 423 441 424 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next); 442 425
+34
include/uapi/drm/drm_mode.h
··· 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 /**