• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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