1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 #include "drv_hdmi_compatibility.h"
19 #include "hdmi_osal.h"
20
21 #define DEF_FILE_NAMELENGTH 32
22
23 typedef struct {
24 hi_char mfrs_name[4];
25 hi_u32 product_code;
26 hi_u32 serial_number;
27 hi_u32 week;
28 hi_u32 year;
29 } compat_edid_manufacture_info;
30
31 typedef struct {
32 compat_edid_manufacture_info edid;
33 hi_u64 ms_under340_m;
34 hi_u64 ms_over340_m;
35 } compat_hdcp_ms;
36
37 typedef struct {
38 compat_edid_manufacture_info edid;
39 hdmi_video_timing timing;
40 hdmi_avmute_cfg avmute_cfg;
41 } compat_sink_avmute;
42
43 typedef struct {
44 compat_edid_manufacture_info edid;
45 hdmi_video_timing timing;
46 hi_u32 fmt_delay;
47 hi_u32 mute_delay;
48 } compat_sink_delay;
49
50 typedef struct {
51 compat_edid_manufacture_info edid;
52 hi_u32 stop_delay;
53 } compat_sink_stop_delay;
54
55 compatibility_info g_compat_info[HDMI_DEVICE_ID_BUTT];
56
57 static compat_hdcp_ms g_sink_hdcp_ms[] = {
58 /* name prod_code serial_no week year under340 over340 */
59 {{ "SNY", 51203, 16843009, 1, 2015 }, 500, 2100 },
60 {{ "MEI", 41622, 16843009, 0, 2014 }, 2000, 3000 },
61 {{ "GSM", 1, 16843009, 1, 2016 }, 500, 6000 }
62 };
63
64 static compat_sink_avmute g_sink_avmute[] = {
65 /* name prod_code serial_no week year timing mute_pkg_en set(no use) mute_clr rpt rpt_cnt */
66 // default config for all other TV have no problem.
67 {{ "DEF", 0, 0, 0, 0 }, HDMI_VIDEO_TIMING_BUTT, { HI_TRUE, HI_TRUE, HI_TRUE, HI_TRUE, 17 }},
68 {{ "HEC", 48, 1, 35, 2010 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
69 {{ "SAM", 3140, 16777217, 42, 2014 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
70 {{ "SHP", 4452, 0, 255, 2016 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
71 {{ "MST", 48, 1, 0, 2007 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
72 {{ "GSM", 1, 16843009, 1, 2016 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
73 {{ "CHD", 36897, 1, 32, 2008 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
74 {{ "HEC", 48, 1, 28, 2016 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
75 {{ "SHP", 17446, 0, 255, 2015 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
76 {{ "SKY", 1, 16843009, 34, 2017 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
77 {{ "HRE", 1691, 1, 51, 2010 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
78 {{ "SKY", 1, 16843009, 2, 2016 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
79 {{ "GSM", 22928, 524660, 9, 2013 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }},
80 {{ "GSM", 22925, 181207, 10, 2013 }, HDMI_VIDEO_TIMING_BUTT, { HI_FALSE, HI_FALSE, HI_FALSE, HI_FALSE, 0 }}
81 };
82
83 static compat_edid_manufacture_info g_sink_scdc_pos[] = {
84 /* name prod_code serial_no week year */
85 { "GSM", 1, 16843009, 1, 2016 }
86 };
87
88 static compat_sink_delay g_sink_delay[] = {
89 /* name prod_code serial_no week year timing fmt mute */
90 {{ "SKW", 48, 1, 1, 2008 }, HDMI_VIDEO_TIMING_BUTT, 500, 900 },
91 {{ "SKY", 48, 1, 10, 2010 }, HDMI_VIDEO_TIMING_BUTT, 200, 0 },
92 {{ "TCL", 0, 0, 20, 2013 }, HDMI_VIDEO_TIMING_BUTT, 500, 500 },
93 {{ "DWE", 533, 825241648, 7, 2019 }, HDMI_VIDEO_TIMING_BUTT, 600, 500 },
94 {{ "ZDH", 8950, 16843009, 0, 2015 }, HDMI_VIDEO_TIMING_BUTT, 500, 500 }
95 };
96
97 static compat_sink_stop_delay g_sink_stop_delay[] = {
98 /* name prod_code serial_no week year stop_delay */
99 {{ "SKW", 48, 1, 1, 2008 }, 1000 },
100 {{ "GSM", 1, 16843009, 1, 2011 }, 1000 },
101 {{ "LTV", 48, 1, 6, 2014 }, 1000 }
102 };
103
104 static compat_edid_manufacture_info g_avi_use_gen5[] = {
105 /* name prod_code serial_no week year */
106 { "SHP", 4485, 0, 255, 2018, }, /* Sharp */
107 { "SHP", 4488, 0, 255, 2018, }, /* Sharp */
108 { "SHP", 4491, 0, 255, 2018, }, /* Sharp */
109 { "SHP", 4494, 0, 255, 2018, }, /* Sharp */
110 { "SHP", 4506, 0, 255, 2018, }, /* Sharp */
111 { "SHP", 4507, 0, 255, 2018, }, /* Sharp */
112 { "SHP", 9301, 0, 255, 2018, }, /* Sharp */
113 { "SHP", 9304, 0, 255, 2018, }, /* Sharp */
114 { "ATO", 45098, 0, 13, 2019, }, /* Astro */
115 };
116
compat_info_get(hdmi_device_id hdmi_id)117 compatibility_info *compat_info_get(hdmi_device_id hdmi_id)
118 {
119 if (hdmi_id < HDMI_DEVICE_ID_BUTT) {
120 return &g_compat_info[hdmi_id];
121 }
122
123 return HI_NULL;
124 }
125
compat_edid_match_chk(const compat_edid_manufacture_info * tmp_manu_info,const hdmi_edid_manufacture_info * sink_manu_info)126 static hi_bool compat_edid_match_chk(const compat_edid_manufacture_info *tmp_manu_info,
127 const hdmi_edid_manufacture_info *sink_manu_info)
128 {
129 hi_bool match = HI_FALSE;
130
131 match = (tmp_manu_info->mfrs_name[0] == sink_manu_info->mfrs_name[0]) &&
132 (tmp_manu_info->mfrs_name[1] == sink_manu_info->mfrs_name[1]) &&
133 (tmp_manu_info->mfrs_name[2] == sink_manu_info->mfrs_name[2]) &&
134 (tmp_manu_info->mfrs_name[3] == sink_manu_info->mfrs_name[3]) &&
135 (tmp_manu_info->product_code == sink_manu_info->product_code) &&
136 (tmp_manu_info->serial_number == sink_manu_info->serial_number) &&
137 (tmp_manu_info->week == sink_manu_info->week) &&
138 (tmp_manu_info->year == sink_manu_info->year);
139
140 return match;
141 }
142
drv_hdmi_compat_hdcp_ms_get(hdmi_device_id hdmi_id,hi_u64 * wait_ms)143 hi_s32 drv_hdmi_compat_hdcp_ms_get(hdmi_device_id hdmi_id, hi_u64 *wait_ms)
144 {
145 hi_u32 i;
146 hdmi_sink_capability *sink_cap = HI_NULL;
147 compat_hdcp_ms *hdcp_ms = HI_NULL;
148 compat_edid_manufacture_info *tmp_manu_info = HI_NULL;
149 hdmi_edid_manufacture_info *sink_manu_info = HI_NULL;
150 hdmi_device *hdmi_dev = HI_NULL;
151
152 hdmi_dev = get_hdmi_device(hdmi_id);
153 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
154 hdmi_if_null_return(wait_ms, HI_FAILURE);
155
156 /* default value */
157 *wait_ms = 500; /* default wait time 500 ms */
158
159 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
160 hdmi_warn("get sink capability fail\n");
161 return HI_FAILURE;
162 } else {
163 sink_manu_info = &sink_cap->mfrs_info;
164
165 for (i = 0, hdcp_ms = &g_sink_hdcp_ms[0];
166 i < hdmi_array_size(g_sink_hdcp_ms);
167 hdcp_ms++, i++) {
168 tmp_manu_info = &hdcp_ms->edid;
169
170 if (compat_edid_match_chk(tmp_manu_info, sink_manu_info)) {
171 *wait_ms = hdmi_dev->attr.vo_attr.hdmi_adapt_pix_clk >= FMT_PIX_CLK_340000 ? hdcp_ms->ms_over340_m :
172 hdcp_ms->ms_under340_m;
173 break;
174 }
175 }
176 }
177
178 return HI_SUCCESS;
179 }
180
drv_hdmi_compat_avmute_get(hdmi_device_id hdmi_id,hi_bool avmute,hdmi_avmute_cfg * avmute_cfg)181 hi_s32 drv_hdmi_compat_avmute_get(hdmi_device_id hdmi_id, hi_bool avmute, hdmi_avmute_cfg *avmute_cfg)
182 {
183 hi_u32 i;
184 hdmi_sink_capability *sink_cap = HI_NULL;
185 compat_sink_avmute *sink_avmute = HI_NULL;
186 compat_edid_manufacture_info *tmp_manu_info = HI_NULL;
187 hdmi_edid_manufacture_info *sink_manu_info = HI_NULL;
188 hdmi_device *hdmi_dev = HI_NULL;
189
190 hdmi_dev = get_hdmi_device(hdmi_id);
191 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
192 hdmi_if_null_return(avmute_cfg, HI_FAILURE);
193
194 /* default value */
195 sink_avmute = &g_sink_avmute[0];
196 avmute_cfg->mute_pkg_en = sink_avmute->avmute_cfg.mute_pkg_en;
197 avmute_cfg->mute_set = avmute;
198 avmute_cfg->mute_clr = (!avmute) && sink_avmute->avmute_cfg.mute_clr;
199 avmute_cfg->mute_rpt_en = (!avmute);
200 avmute_cfg->rpt_cnt = sink_avmute->avmute_cfg.rpt_cnt;
201
202 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
203 hdmi_warn("get sink capability fail\n");
204 return HI_FAILURE;
205 }
206
207 sink_manu_info = &sink_cap->mfrs_info;
208
209 for (i = 1, sink_avmute = &g_sink_avmute[1];
210 i < hdmi_array_size(g_sink_avmute);
211 sink_avmute++, i++) {
212 tmp_manu_info = &sink_avmute->edid;
213
214 if (compat_edid_match_chk(tmp_manu_info, sink_manu_info) == HI_FALSE) {
215 continue;
216 }
217 if ((hdmi_dev->attr.vo_attr.video_timing == sink_avmute->timing) ||
218 (sink_avmute->timing == HDMI_VIDEO_TIMING_BUTT)) {
219 /* HDMI_VIDEO_TIMING_BUTT means all timing use the same config to the TV. */
220 avmute_cfg->mute_pkg_en = sink_avmute->avmute_cfg.mute_pkg_en;
221 avmute_cfg->mute_set = avmute;
222 avmute_cfg->mute_clr = (!avmute) && sink_avmute->avmute_cfg.mute_clr;
223 avmute_cfg->mute_rpt_en = sink_avmute->avmute_cfg.mute_rpt_en;
224 avmute_cfg->rpt_cnt = sink_avmute->avmute_cfg.rpt_cnt;
225 break;
226 }
227 }
228
229 return HI_SUCCESS;
230 }
231
drv_hdmi_compat_scdc_in_start_get(hdmi_device_id hdmi_id)232 hi_bool drv_hdmi_compat_scdc_in_start_get(hdmi_device_id hdmi_id)
233 {
234 hi_u32 i;
235 hi_bool in_start = HI_FALSE;
236 hdmi_sink_capability *sink_cap = HI_NULL;
237 compat_edid_manufacture_info *tmp_manu_info = HI_NULL;
238 hdmi_edid_manufacture_info *sink_manu_info = HI_NULL;
239 hdmi_device *hdmi_dev = HI_NULL;
240
241 hdmi_dev = get_hdmi_device(hdmi_id);
242 hdmi_if_null_return(hdmi_dev, HI_FALSE);
243
244 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
245 hdmi_warn("get sink capability fail\n");
246 } else {
247 sink_manu_info = &sink_cap->mfrs_info;
248
249 for (i = 0, tmp_manu_info = &g_sink_scdc_pos[0];
250 i < hdmi_array_size(g_sink_scdc_pos);
251 tmp_manu_info++, i++) {
252 if (compat_edid_match_chk(tmp_manu_info, sink_manu_info)) {
253 in_start = HI_TRUE;
254 break;
255 }
256 }
257 }
258
259 return in_start;
260 }
261
drv_hdmi_compat_delay_get(hdmi_device_id hdmi_id,hdmi_delay * delay)262 hi_s32 drv_hdmi_compat_delay_get(hdmi_device_id hdmi_id, hdmi_delay *delay)
263 {
264 hi_u32 i;
265 hdmi_sink_capability *sink_cap = HI_NULL;
266 compat_sink_delay *sink_delay = HI_NULL;
267 compat_edid_manufacture_info *tmp_manu_info = HI_NULL;
268 hdmi_edid_manufacture_info *sink_manu_info = HI_NULL;
269 hdmi_device *hdmi_dev = HI_NULL;
270
271 hdmi_dev = get_hdmi_device(hdmi_id);
272 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
273 hdmi_if_null_return(delay, HI_FAILURE);
274
275 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
276 hdmi_warn("get sink capability fail\n");
277 return HI_FAILURE;
278 }
279 sink_manu_info = &sink_cap->mfrs_info;
280 for (i = 0, sink_delay = &g_sink_delay[0]; i < hdmi_array_size(g_sink_delay); sink_delay++, i++) {
281 tmp_manu_info = &sink_delay->edid;
282 if (compat_edid_match_chk(tmp_manu_info, sink_manu_info) == HI_FALSE) {
283 continue;
284 }
285 if ((hdmi_dev->attr.vo_attr.video_timing == sink_delay->timing) ||
286 (sink_delay->timing == HDMI_VIDEO_TIMING_BUTT)) {
287 /* HDMI_VIDEO_TIMING_BUTT means all timing use the same config to the TV. */
288 delay->fmt_delay = sink_delay->fmt_delay;
289 delay->mute_delay = sink_delay->mute_delay;
290 break;
291 }
292 }
293
294 return HI_SUCCESS;
295 }
296
drv_hdmi_compat_stop_delay(hdmi_device_id hdmi_id)297 hi_s32 drv_hdmi_compat_stop_delay(hdmi_device_id hdmi_id)
298 {
299 hi_u32 i;
300 hdmi_sink_capability *sink_cap = HI_NULL;
301 compat_sink_stop_delay *sink_stop_delay = HI_NULL;
302 compat_edid_manufacture_info *tmp_manu_info = HI_NULL;
303 hdmi_edid_manufacture_info *sink_manu_info = HI_NULL;
304 hdmi_device *hdmi_dev = HI_NULL;
305
306 hdmi_dev = get_hdmi_device(hdmi_id);
307 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
308
309 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_cap) == HDMI_EDID_DATA_INVALID) {
310 hdmi_warn("get sink capability fail\n");
311 return HI_FAILURE;
312 } else {
313 sink_manu_info = &sink_cap->mfrs_info;
314
315 for (i = 0, sink_stop_delay = &g_sink_stop_delay[0];
316 i < hdmi_array_size(g_sink_stop_delay);
317 sink_stop_delay++, i++) {
318 tmp_manu_info = &sink_stop_delay->edid;
319
320 if (compat_edid_match_chk(tmp_manu_info, sink_manu_info)) {
321 hdmi_info("set stop delay = %ums.\n", sink_stop_delay->stop_delay);
322 osal_msleep(sink_stop_delay->stop_delay);
323 break;
324 }
325 }
326 }
327
328 return HI_SUCCESS;
329 }
330
compat_avi_use_gen5(const hdmi_sink_capability * sink_caps)331 static hi_bool compat_avi_use_gen5(const hdmi_sink_capability *sink_caps)
332 {
333 hi_u32 i;
334 compat_edid_manufacture_info *tmp_manuinfo = HI_NULL;
335
336 hdmi_if_null_return(sink_caps, HI_FALSE);
337
338 for (i = 0, tmp_manuinfo = &g_avi_use_gen5[0];
339 i < hdmi_array_size(g_avi_use_gen5);
340 tmp_manuinfo++, i++) {
341 if (compat_edid_match_chk(tmp_manuinfo, &sink_caps->mfrs_info) ||
342 ((sink_caps->mfrs_info.mfrs_name[0] == 'S') &&
343 (sink_caps->mfrs_info.mfrs_name[1] == 'H') &&
344 (sink_caps->mfrs_info.mfrs_name[2] == 'P') &&
345 (tmp_manuinfo->product_code == sink_caps->mfrs_info.product_code))) {
346 return HI_TRUE;
347 }
348 }
349
350 return HI_FALSE;
351 }
352
compatibility_info_default_set(hdmi_device_id hdmi_id)353 hi_void compatibility_info_default_set(hdmi_device_id hdmi_id)
354 {
355 compatibility_info *compat_info = HI_NULL;
356
357 compat_info = compat_info_get(hdmi_id);
358 hdmi_if_null_return_void(compat_info);
359
360 compat_info->avi_use_gen5 = HI_FALSE;
361 compat_info->avi_use_gen5_debug = HI_FALSE;
362 compat_info->ctl_type_config = FRL_CTRL_TYPE_COMPRESS_HW;
363
364 return;
365 }
366
compatibility_info_update(hdmi_device_id hdmi_id)367 hi_s32 compatibility_info_update(hdmi_device_id hdmi_id)
368 {
369 hdmi_device *hdmi_dev = HI_NULL;
370 hdmi_sink_capability *sink_caps = HI_NULL;
371 compatibility_info *compat_info = HI_NULL;
372
373 hdmi_dev = get_hdmi_device(hdmi_id);
374 hdmi_if_null_return(hdmi_dev, HI_FAILURE);
375
376 compat_info = compat_info_get(hdmi_id);
377 hdmi_if_null_return(compat_info, HI_FAILURE);
378
379 if (drv_hdmi_edid_capability_get(&hdmi_dev->edid_info, &sink_caps) == HDMI_EDID_DATA_INVALID) {
380 hdmi_warn("get sink capability failed.\n");
381 compatibility_info_default_set(hdmi_id);
382 return HI_FAILURE;
383 } else {
384 if (compat_avi_use_gen5(sink_caps)) {
385 if (compat_info->avi_use_gen5_debug == HI_FALSE) {
386 hdmi_info("use gen5 send avi.\n");
387 compat_info->avi_use_gen5 = HI_TRUE;
388 }
389 if (!!(compat_info->ctl_type_config & HDMI_FRL_COMPRESS_DEBUG_MASK) == HI_FALSE) {
390 hdmi_info("frl not compress.\n");
391 compat_info->ctl_type_config = FRL_CTRL_TYPE_COMPRESS_NON;
392 }
393 } else {
394 compat_info->avi_use_gen5 = HI_FALSE;
395 compat_info->ctl_type_config = FRL_CTRL_TYPE_COMPRESS_HW;
396 }
397 }
398
399 return HI_SUCCESS;
400 }
401
402