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 */ 11static 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 18static 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 25static 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 32static 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 39static 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 46const 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 69struct gamma_curve_sector { 70 u32 boundary_start; 71 u32 num_of_segments; 72 u32 segment_width; 73}; 74 75struct gamma_curve_segment { 76 u32 start; 77 u32 end; 78}; 79 80static 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 91static void 92drm_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 116void 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 121void 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