1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) COPYRIGHT 2019 ARM Limited. All rights reserved. 4 * Author: James.Qian.Wang <james.qian.wang@arm.com> 5 * 6 */ 7 8 #include "komeda_color_mgmt.h" 9 10 /* 10bit precision YUV2RGB matrix */ 11 static const s32 yuv2rgb_bt601_narrow[KOMEDA_N_YUV2RGB_COEFFS] = { 12 1192, 0, 1634, 13 1192, -401, -832, 14 1192, 2066, 0, 15 64, 512, 512 16 }; 17 18 static const s32 yuv2rgb_bt601_wide[KOMEDA_N_YUV2RGB_COEFFS] = { 19 1024, 0, 1436, 20 1024, -352, -731, 21 1024, 1815, 0, 22 0, 512, 512 23 }; 24 25 static const s32 yuv2rgb_bt709_narrow[KOMEDA_N_YUV2RGB_COEFFS] = { 26 1192, 0, 1836, 27 1192, -218, -546, 28 1192, 2163, 0, 29 64, 512, 512 30 }; 31 32 static const s32 yuv2rgb_bt709_wide[KOMEDA_N_YUV2RGB_COEFFS] = { 33 1024, 0, 1613, 34 1024, -192, -479, 35 1024, 1900, 0, 36 0, 512, 512 37 }; 38 39 static const s32 yuv2rgb_bt2020[KOMEDA_N_YUV2RGB_COEFFS] = { 40 1024, 0, 1476, 41 1024, -165, -572, 42 1024, 1884, 0, 43 0, 512, 512 44 }; 45 46 const s32 *komeda_select_yuv2rgb_coeffs(u32 color_encoding, u32 color_range) 47 { 48 bool narrow = color_range == DRM_COLOR_YCBCR_LIMITED_RANGE; 49 const s32 *coeffs; 50 51 switch (color_encoding) { 52 case DRM_COLOR_YCBCR_BT709: 53 coeffs = narrow ? yuv2rgb_bt709_narrow : yuv2rgb_bt709_wide; 54 break; 55 case DRM_COLOR_YCBCR_BT601: 56 coeffs = narrow ? yuv2rgb_bt601_narrow : yuv2rgb_bt601_wide; 57 break; 58 case DRM_COLOR_YCBCR_BT2020: 59 coeffs = yuv2rgb_bt2020; 60 break; 61 default: 62 coeffs = NULL; 63 break; 64 } 65 66 return coeffs; 67 } 68 69 struct gamma_curve_sector { 70 u32 boundary_start; 71 u32 num_of_segments; 72 u32 segment_width; 73 }; 74 75 struct gamma_curve_segment { 76 u32 start; 77 u32 end; 78 }; 79 80 static struct gamma_curve_sector sector_tbl[] = { 81 { 0, 4, 4 }, 82 { 16, 4, 4 }, 83 { 32, 4, 8 }, 84 { 64, 4, 16 }, 85 { 128, 4, 32 }, 86 { 256, 4, 64 }, 87 { 512, 16, 32 }, 88 { 1024, 24, 128 }, 89 }; 90 91 static void 92 drm_lut_to_coeffs(struct drm_property_blob *lut_blob, u32 *coeffs, 93 struct gamma_curve_sector *sector_tbl, u32 num_sectors) 94 { 95 struct drm_color_lut *lut; 96 u32 i, j, in, num = 0; 97 98 if (!lut_blob) 99 return; 100 101 lut = lut_blob->data; 102 103 for (i = 0; i < num_sectors; i++) { 104 for (j = 0; j < sector_tbl[i].num_of_segments; j++) { 105 in = sector_tbl[i].boundary_start + 106 j * sector_tbl[i].segment_width; 107 108 coeffs[num++] = drm_color_lut_extract(lut[in].red, 109 KOMEDA_COLOR_PRECISION); 110 } 111 } 112 113 coeffs[num] = BIT(KOMEDA_COLOR_PRECISION); 114 } 115 116 void drm_lut_to_fgamma_coeffs(struct drm_property_blob *lut_blob, u32 *coeffs) 117 { 118 drm_lut_to_coeffs(lut_blob, coeffs, sector_tbl, ARRAY_SIZE(sector_tbl)); 119 } 120 121 void drm_ctm_to_coeffs(struct drm_property_blob *ctm_blob, u32 *coeffs) 122 { 123 struct drm_color_ctm *ctm; 124 u32 i; 125 126 if (!ctm_blob) 127 return; 128 129 ctm = ctm_blob->data; 130 131 for (i = 0; i < KOMEDA_N_CTM_COEFFS; i++) 132 coeffs[i] = drm_color_ctm_s31_32_to_qm_n(ctm->matrix[i], 3, 12); 133 } 134