1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdmi_ncts.h"
10
11 #define HDF_LOG_TAG hdmi_ncts_c
12 #define HDMI_NCTS_KHZ 1000
13 #define HDMI_NCTS_TMDS_PER_PIXEL 10
14
15 #define HDMI_NCTS_INVALID_VALUE 0xffffffff
16
17 /*
18 * see hdmi1.4 table 7-1, 7-2, 7-3.
19 * The exact relationship: 128 * fs = tmdsClock * N / CTS.
20 */
21 static struct HdmiAudioNCts g_audioNctsMap[] = {
22 { 32000, 25174, 4576, 28125 },
23 { 32000, 25200, 4096, 25200 },
24 { 32000, 27000, 4096, 27000 },
25 { 32000, 27027, 4096, 27027 },
26 { 32000, 54000, 4096, 54000 },
27 { 32000, 54054, 4096, 54054 },
28 { 32000, 74175, 11648, 210937},
29 { 32000, 74250, 4096, 74250 },
30 { 32000, 148351, 11648, 421875 },
31 { 32000, 148500, 4096, 148500 },
32 { 32000, 296703, 5824, 421875 },
33 { 32000, 297000, 3072, 222750 },
34 { 32000, 593406, 5824, 843750 },
35 { 32000, 594000, 3072, 445500 },
36 { 32000, 0, 4096, 0 },
37 { 44100, 25174, 7007, 31250 },
38 { 44100, 25200, 6272, 28000 },
39 { 44100, 27000, 6272, 30000 },
40 { 44100, 27027, 6272, 30030 },
41 { 44100, 54000, 6272, 60000 },
42 { 44100, 54054, 6272, 60060 },
43 { 44100, 74175, 17836, 234375 },
44 { 44100, 74250, 6272, 82500 },
45 { 44100, 148351, 8918, 234375 },
46 { 44100, 148500, 6272, 165000 },
47 { 44100, 296703, 4459, 234375 },
48 { 44100, 297000, 4704, 247500 },
49 { 44100, 593406, 8918, 937500 },
50 { 44100, 594000, 9408, 990000 },
51 { 44100, 0, 6272, 0 },
52 { 48000, 25174, 6864, 28125 },
53 { 48000, 25200, 6144, 25200 },
54 { 48000, 27000, 6144, 27000 },
55 { 48000, 27027, 6144, 27027 },
56 { 48000, 54000, 6144, 54000 },
57 { 48000, 54054, 6144, 54054 },
58 { 48000, 74175, 11648, 140625 },
59 { 48000, 74250, 6144, 74250 },
60 { 48000, 148351, 5824, 140625 },
61 { 48000, 148500, 6144, 148500 },
62 { 48000, 296703, 5824, 281250 },
63 { 48000, 297000, 5120, 247500 },
64 { 48000, 593406, 5824, 562500 },
65 { 48000, 594000, 6144, 594000 },
66 { 48000, 0, 6144, 0 }
67 };
68
HdmiGetN(uint32_t sampleRate,uint32_t tmdsClock)69 uint32_t HdmiGetN(uint32_t sampleRate, uint32_t tmdsClock)
70 {
71 uint32_t i;
72
73 for (i = 0; i < sizeof(g_audioNctsMap) / sizeof(g_audioNctsMap[0]); i++) {
74 if (g_audioNctsMap[i].sampleRate == sampleRate &&
75 g_audioNctsMap[i].tmdsClock == tmdsClock) {
76 return g_audioNctsMap[i].n;
77 }
78 if (g_audioNctsMap[i].sampleRate == sampleRate &&
79 g_audioNctsMap[i].tmdsClock >= (tmdsClock - HDMI_NCTS_TMDS_DEVIATION) &&
80 g_audioNctsMap[i].tmdsClock <= (tmdsClock + HDMI_NCTS_TMDS_DEVIATION)) {
81 return g_audioNctsMap[i].n;
82 }
83 if (g_audioNctsMap[i].sampleRate == sampleRate &&
84 g_audioNctsMap[i].tmdsClock == 0) {
85 return g_audioNctsMap[i].n;
86 }
87 }
88 return HDMI_NCTS_N_DEFAULT;
89 }
90
HdmiGetCts(uint32_t sampleRate,uint32_t tmdsClock)91 uint32_t HdmiGetCts(uint32_t sampleRate, uint32_t tmdsClock)
92 {
93 uint32_t i;
94 uint32_t tmpN = HDMI_NCTS_INVALID_VALUE;
95 uint32_t tmpCts = HDMI_NCTS_INVALID_VALUE;
96
97 for (i = 0; i < sizeof(g_audioNctsMap) / sizeof(g_audioNctsMap[0]); i++) {
98 if (g_audioNctsMap[i].sampleRate == sampleRate &&
99 g_audioNctsMap[i].tmdsClock == tmdsClock) {
100 tmpN = g_audioNctsMap[i].n;
101 tmpCts = g_audioNctsMap[i].cts;
102 break;
103 }
104 if (g_audioNctsMap[i].sampleRate == sampleRate &&
105 g_audioNctsMap[i].tmdsClock >= (tmdsClock - HDMI_NCTS_TMDS_DEVIATION) &&
106 g_audioNctsMap[i].tmdsClock <= (tmdsClock + HDMI_NCTS_TMDS_DEVIATION)) {
107 tmpN = g_audioNctsMap[i].n;
108 tmpCts = g_audioNctsMap[i].cts;
109 break;
110 }
111 if (g_audioNctsMap[i].sampleRate == sampleRate &&
112 g_audioNctsMap[i].tmdsClock == 0) {
113 tmpN = g_audioNctsMap[i].n;
114 tmpCts = g_audioNctsMap[i].cts;
115 break;
116 }
117 }
118
119 if (tmpCts == 0 && sampleRate >= HDMI_NCTS_KHZ) {
120 tmpCts = (tmpN / HDMI_NCTS_FACTOR) * tmdsClock * HDMI_NCTS_TMDS_PER_PIXEL / (sampleRate / HDMI_NCTS_KHZ);
121 } else if (tmpCts == HDMI_NCTS_INVALID_VALUE && sampleRate >= HDMI_NCTS_KHZ) {
122 tmpCts = (HDMI_NCTS_N_DEFAULT / HDMI_NCTS_FACTOR) * tmdsClock * HDMI_NCTS_TMDS_PER_PIXEL /
123 (sampleRate / HDMI_NCTS_KHZ);
124 }
125 return tmpCts;
126 }
127