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_edid.h"
19 #include "hdmi_product_define.h"
20 #include "drv_hdmi_intf.h"
21
22 /* private define */
23 #define BIT0_MASK 0x01
24 #define BIT1_MASK 0x02
25 #define BIT2_MASK 0x04
26 #define BIT3_MASK 0x08
27 #define BIT4_MASK 0x10
28 #define BIT5_MASK 0x20
29 #define BIT6_MASK 0x40
30 #define BIT7_MASK 0x80
31 #define EDID_EXTENSION_BLK_ADDR 0x7e
32 /* VENDOR INFO */
33 #define EDID_VEND_NAME_CHAR_MASK 0x1F
34 #define EDID_VEND_CHAR_LOW_INVALID 0
35 #define EDID_VEND_CHAR_HIGH_INVALID 27
36 #define EDID_VEND_YEAR_BASE 1990
37 /* STD TIMING */
38 #define EDID_STDTIMING_UNUSED_FLAG 0x01
39 #define EDID_STDTIMING_RATE_BASE 60
40 #define EDID_HORACTIVE_FACTOR 8
41 #define EDID_HORACTIVE_BASE 31
42 #define EDID_REFRESH_RATE_MASK 0x3F
43 #define EDID_ASPECT_RATIO_MASK 0xC0
44 #define EDID_ASPECT_RATIO_16_10 0
45 #define EDID_ASPECT_RATIO_4_3 1
46 #define EDID_ASPECT_RATIO_5_4 2
47 #define EDID_ASPECT_RATIO_16_9 3
48 /* detailed timing descriptor */
49 #define EDID_FST_BLK_DTD_OFFSET 0x36
50 #define EDID_DTD_SIZE 18
51 #define EDID_PIXCLK_KHZ_FACTOR 10
52 #define EDID_UPPER_NIBBLE_MASK 0xF0
53 #define EDID_LOWER_NIBBLE_MASK 0x0F
54 #define EDID_HSO_MASK 0xC0
55 #define EDID_HSPW_MASK 0x30
56 #define EDID_VSO_MASK 0x0C
57 #define EDID_VSPW_MASK 0x03
58 #define EDID_STEREO_MASK 0x60
59 #define EDID_STEREO_SEQUENTIAL_R 0x02
60 #define EDID_STEREO_SEQUENTIAL_L 0x04
61 #define EDID_STEREO_INTERLEAVED_2R 0x03
62 #define EDID_STEREO_INTERLEAVED_2L 0x05
63 #define EDID_STEREO_INTERLEAVED_4 0x06
64 #define EDID_STEREO_INTERLEAVED_SBS 0x07
65 #define EDID_SYNC_SIGNAL_TYPE_MASK 0x0E
66 #define EDID_SYNC_DCS_WS_0 0x00
67 #define EDID_SYNC_DCS_WS_1 0x01
68 #define EDID_SYNC_DCS_DS_2 0x02
69 #define EDID_SYNC_DCS_DS_3 0x03
70 #define EDID_SYNC_DSS_VN_HN_4 0x04
71 #define EDID_SYNC_DSS_VN_HP_5 0x05
72 #define EDID_SYNC_DSS_VP_HN_6 0x06
73 #define EDID_SYNC_DSS_VP_HP_7 0x07
74 /* monitor descriptor */
75 #define EDID_TYPE_MONITOR_SERNUM 0xFF
76 #define EDID_TYPE_MONITOR_ASIIC 0xFE
77 #define EDID_TYPE_MONITOR_RANGE 0xFD
78 #define EDID_TYPE_MONITOR_NAME 0xFC
79 /* EXTENSION BLOCK */
80 #define EDID_CEA_EXTVERSION3_TAG 0x02
81 #define EDID_CEA_EXTVERSION3_REVISION 0x03
82 #define EDID_DB_LEN_MASK 0x1F
83 #define EDID_DB_TAG_CODE_MASK 0xE0
84 /* tag code */
85 #define EDID_REVERSED_DATA_BLOCK 0x00
86 #define EDID_AUDIO_DATA_BLOCK 0x01
87 #define EDID_VIDEO_DATA_BLOCK 0x02
88 #define EDID_VENDOR_DATA_BLOCK 0x03
89 #define EDID_SPEAKER_DATA_BLOCK 0x04
90 #define EDID_VESA_DTC_DATA_BLOCK 0x05
91 #define EDID_USE_EXT_DATA_BLOCK 0x07
92 /* ext tag code */
93 #define EDID_VIDEO_CAPABILITY_DB 0x00
94 #define EDID_COLORIMETRY_DB 0x05
95 #ifdef HDMI_HDR_SUPPORT
96 #define EDID_DOLBY_VENDOR_SPECIFIC_VIDEO_DB 0x01 // dolby mode
97 #define EDID_HDR_STATIC_METADATA_DB 0x06 // HDR
98 #endif
99 #define EDID_VIDEO_FMT_PREFER_DB 0x0d
100 #define EDID_Y420_VIDEO_DB 0x0e
101 #define EDID_Y420_CAPABILITY_MAP_DB 0x0f
102 #define EDID_RESERVED_HDMI_AUDIO_DB 0x12
103 #define EDID_INFOFRAME_DB 0x20
104 /* AUDIO DATA BLOCK */
105 #define EDID_AUDIO_FORMAT_MASK 0x78
106 #define EDID_AUDIO_CHANNEL_MASK 0x07
107 #define EDID_AUDIO_EXT_TYPE_CODE 0xf8
108 #define EDID_AUDIO_BITRATE_FACTOR 8
109 /* VIDEO DATA BLOCK */
110 #define EDID_VIC_NATIVE_MAX 64
111 #define EDID_VIC_LOWER7_MASK 0x7F
112 #define EDID_VIC_INVALID_LOW 128
113 #define EDID_VIC_INVALID_HIGH 192
114 #define EDID_VIC_INVALID_ZERO 0
115 /* HFVSDB */
116 #define EDID_HFVSDB_VERSION 1
117 #define EDID_MAX_HDMI14_TMDS_RATE 340
118 #define EDID_TMDS_FACTOR 5
119 #define EDID_IEEE_VSDB_1ST 0x03
120 #define EDID_IEEE_VSDB_2ND 0x0c
121 #define EDID_IEEE_VSDB_3RD 0x00
122 #define EDID_IEEE_HFVSDB_1ST 0xd8
123 #define EDID_IEEE_HFVSDB_2ND 0x5d
124 #define EDID_IEEE_HFVSDB_3RD 0xc4
125 /* VSDB */
126 #define EDID_CEC_INVALID_ADDR 0xF
127 #define EDID_IMG_SIZE_MASK 0x18
128 #define EDID_HDMI_3D_LEN_MASK 0x1F
129 #define EDID_HDMI_VIC_LEN_MASK 0xE0
130 #define EDID_3DMULTI_PRESENT_LOWER8 0x01
131 #define EDID_3DMULTI_PRESENT_UPPER8 0x02
132 #ifdef HDMI_HDR_SUPPORT
133 /* dolby VSVDB */
134 #define EDID_DOLBY_VSVDB_VERSION_0 0x00
135 #define EDID_DOLBY_VSVDB_VERSION_1 0x01
136 #define EDID_DOLBY_VSVDB_VERSION_0_LEN 0x19
137 #define EDID_DOLBY_VSVDB_VERSION_1_LEN 0x0E
138 #define EDID_DOLBY_LOWER_2BIT_MASK 0x03
139 #define EDID_DOLBY_LOWER_3BIT_MASK 0x07
140 #define EDID_DOLBY_LOWER_NIBBLE_MASK 0x0F
141 #define EDID_DOLBY_LOWER_7BIT_MASK 0x7F
142 #endif
143 #define EDID_COLOR_OFFSET_NUM_1 2
144 #define EDID_COLOR_OFFSET_NUM_2 4
145 #define EDID_COLOR_OFFSET_NUM_3 6
146 #define EDID_COLOR_LOW_BIT_MASK 0x03
147 #define EDID_SHORT_AUDIO_DESCRIPTOR_SIZE 3
148 #define EDID_HEAD_BLOCK_SIZE 8
149 #define EDID_DOLBY_CAP_OFFSET_1 1
150 #define EDID_DOLBY_CAP_OFFSET_2 2
151 #define EDID_DOLBY_CAP_OFFSET_3 4
152 #define EDID_DOLBY_CAP_OFFSET_4 5
153 #define EDID_ESTABLISH_TIMING 3
154 #define EDID_AUDIO_DESCRIPTOR_SIZE 3
155 #define EDID_EXT_BLOCK_OFFSET 4
156 #define EDID_VENDOR_BLOCK_LEN 3
157
158 typedef struct {
159 hi_u8 pixel_clk[2];
160 hi_u8 h_active;
161 hi_u8 h_blank;
162 hi_u8 h_active_blank;
163 hi_u8 v_active;
164 hi_u8 v_blank;
165 hi_u8 v_active_blank;
166 hi_u8 h_sync_offset;
167 hi_u8 h_sync_pulse_width;
168 hi_u8 vs_offset_pulse_width;
169 hi_u8 hs_offset_vs_offset;
170 hi_u8 h_image_size;
171 hi_u8 v_image_size;
172 hi_u8 h_v_image_size;
173 hi_u8 h_border;
174 hi_u8 v_border;
175 hi_u8 flags;
176 } __attribute__((packed)) edid_dtd_timing_block;
177
178 typedef struct {
179 hi_u8 flags[3];
180 hi_u8 data_tag;
181 hi_u8 flag;
182 hi_u8 des_data[13];
183 } __attribute__((packed)) edid_monitor_des_block;
184
185 typedef struct {
186 hi_u8 header[8];
187 /* vendor & product info */
188 hi_u8 mfg_id[2];
189 hi_u8 prod_code[2];
190 /* byte order */
191 hi_u8 serial[4];
192 hi_u8 mfg_week;
193 hi_u8 mfg_year;
194 /* EDID version */
195 hi_u8 version;
196 hi_u8 revision;
197 /* display info: */
198 hi_u8 input;
199 hi_u8 width_cm;
200 hi_u8 height_cm;
201 hi_u8 gamma;
202 hi_u8 features;
203 /* color characteristics */
204 hi_u8 red_green_low;
205 hi_u8 black_white_low;
206 hi_u8 red_x;
207 hi_u8 red_y;
208 hi_u8 green_x;
209 hi_u8 green_y;
210 hi_u8 blue_x;
211 hi_u8 blue_y;
212 hi_u8 white_x;
213 hi_u8 white_y;
214 hi_u8 est_timing[3];
215 hi_u8 std_timing[16];
216 hi_u8 detailed_timing1[18];
217 hi_u8 detailed_timing2[18];
218 hi_u8 detailed_timing3[18];
219 hi_u8 detailed_timing4[18];
220 /* number of 128 byte ext. blocks */
221 hi_u8 ext_blocks;
222 /* checksum */
223 hi_u8 chk_sum;
224 } __attribute__((packed)) edid_first_block_info;
225
226 static const hi_char *g_establish_timing_str[] = {
227 "720x400p_70Hz 9:5",
228 "720x400p_88Hz 9:5",
229 "640x480p_60Hz 4:3",
230 "(VESA) 640x480p_72Hz 4:3",
231 "(VESA) 640x480p_75Hz 4:3",
232 "(VESA) 800x600p_56Hz 4:3",
233 "(VESA) 800x600p_60Hz 4:3",
234 "(VESA) 800x600p_72Hz 4:3",
235 "(VESA) 800x600p_75Hz 4:3",
236 "(VESA) 1024x768i_87Hz 4:3",
237 "(VESA) 1024x768p_60Hz 4:3",
238 "(VESA) 1024x768p_70Hz 4:3",
239 "(VESA) 1024x768p_75Hz 4:3",
240 "(VESA) 1280x1024p_75Hz 5:4",
241 "640x480p_67Hz 4:3",
242 "832x624p_75Hz 4:3",
243 "1152x870p_75Hz 4:3"
244 };
245
edid_block_check_sum(hi_u8 * data,hdmi_edid_status * status)246 static hi_s32 edid_block_check_sum(hi_u8 *data, hdmi_edid_status *status)
247 {
248 hi_u8 i;
249 hi_u32 check_sum = 0;
250
251 for (i = 0; i < HDMI_EDID_BLOCK_SIZE; i++) {
252 check_sum += data[i];
253 }
254
255 /* EDID header */
256 edid_info(" %-20s : %02X\n", "check sum", data[127]);
257
258 if ((check_sum & 0xff) != 0x00) {
259 if (data[32] != 0x00) {
260 status->parse_err = EDID_PARSE_ERR_CHECKSUM;
261 edid_err("check sum fail\n");
262 return HI_FAILURE;
263 } else {
264 /*
265 * if the data is 0x00 at 0x20 in block0, which is modified by clear scramble in boot.
266 * but the real EDID is correct.
267 */
268 edid_info("EDID data maybe changed by clr scramble.\n");
269 }
270 }
271
272 return HI_SUCCESS;
273 }
274
edid_header_check(const hi_u8 * data,hdmi_edid_status * status)275 static hi_s32 edid_header_check(const hi_u8 *data, hdmi_edid_status *status)
276 {
277 hi_u32 i;
278 const hi_u8 blkheader[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
279
280 edid_info("EDID header...\n");
281 for (i = 0; i < EDID_HEAD_BLOCK_SIZE; i++) {
282 if (data[i] != blkheader[i]) {
283 status->parse_err = EDID_PARSE_ERR_HEADER;
284 edid_err("header chk: DATA[%u]=0x%x\n", i, data[i]);
285 }
286 }
287
288 return HI_SUCCESS;
289 }
290
edid_vendor_info(hdmi_edid_info * edid_info)291 static hi_s32 edid_vendor_info(hdmi_edid_info *edid_info)
292 {
293 hi_u16 i;
294 hi_u16 data;
295 hdmi_sink_capability *cap = HI_NULL;
296 hdmi_edid_manufacture_info *vendor = HI_NULL;
297 edid_first_block_info *fst_blk = HI_NULL;
298 hdmi_edid_status *status = HI_NULL;
299
300 edid_info("vendor / product identification...\n");
301 fst_blk = (edid_first_block_info *)edid_info->edid_raw;
302 hdmi_if_null_return(fst_blk, HI_FAILURE);
303 cap = &edid_info->capability;
304 status = &edid_info->status;
305 vendor = &cap->mfrs_info;
306
307 data = (fst_blk->mfg_id[0] << 8) | (fst_blk->mfg_id[1]); /* offset 8, express dada 15-8 bits */
308
309 /* 2_bytes(16bits) width */
310 for (i = 0; i <= 2; i++) {
311 vendor->mfrs_name[2 - i] = ((data & (EDID_VEND_NAME_CHAR_MASK << (5 * i))) >> (5 * i)); /* 5bit a character */
312
313 /* 'A'~'Z' is referred to 1~26 */
314 if ((vendor->mfrs_name[2 - i] > EDID_VEND_CHAR_LOW_INVALID) &&
315 (vendor->mfrs_name[2 - i] < EDID_VEND_CHAR_HIGH_INVALID)) {
316 vendor->mfrs_name[2 - i] += 'A' - 1;
317 } else {
318 status->parse_warn |= 1 << EDID_PARSE_WARN_VENDOR_INVALID;
319 }
320 }
321 /* offset 8, express product code 15-8 bits */
322 vendor->product_code = (fst_blk->prod_code[1] << 8) | fst_blk->prod_code[0];
323 /* 24, 16, is serial number 3 and 4 byte */
324 vendor->serial_number = (fst_blk->serial[3] << 24) | (fst_blk->serial[2] << 16) |
325 (fst_blk->serial[1] << 8) | (fst_blk->serial[0]); /* 8, 0, is serial number 1 and 0 byte */
326 vendor->week = fst_blk->mfg_week;
327 vendor->year = fst_blk->mfg_year + EDID_VEND_YEAR_BASE;
328
329 edid_info(" %-20s : %s\n", "ID manufacturer name", vendor->mfrs_name);
330 edid_info(" %-20s : 0x%0.4X\n", "ID product code", vendor->product_code);
331 edid_info(" %-20s : 0x%0.8l_x\n", "ID serial number", vendor->serial_number);
332 edid_info(" %-20s : %02u\n", "week of manufacture", vendor->week);
333 edid_info(" %-20s : %u\n", "year of manufacture", vendor->year);
334
335 return HI_SUCCESS;
336 }
337
edid_version(hdmi_edid_info * edid_info)338 static hi_s32 edid_version(hdmi_edid_info *edid_info)
339 {
340 hdmi_sink_capability *cap = HI_NULL;
341 edid_first_block_info *edid_fst_info = HI_NULL;
342 hdmi_edid_status *status = HI_NULL;
343
344 cap = &edid_info->capability;
345 edid_fst_info = (edid_first_block_info *)edid_info->edid_raw;
346 hdmi_if_null_return(edid_fst_info, HI_FAILURE);
347 status = &edid_info->status;
348 cap->version = edid_fst_info->version;
349 cap->revision = edid_fst_info->revision;
350 edid_info(" EDID version...\n");
351 /* 1, is info sink version, 3 is reversion count */
352 if ((cap->version != 1) || (cap->revision != 3)) {
353 edid_err("EDID first blk is not version1.3:%u.%u\n!", cap->version, cap->revision);
354 status->parse_err = EDID_PARSE_ERR_FST_BLK_VER;
355 }
356 edid_info(" %-20s : %02u\n", "version no.", cap->version);
357 edid_info(" %-20s : %02u\n", "revision no.", cap->revision);
358
359 return HI_SUCCESS;
360 }
361
edid_basic_disp_para(hdmi_edid_info * edid_info)362 static hi_s32 edid_basic_disp_para(hdmi_edid_info *edid_info)
363 {
364 hdmi_sink_capability *cap = HI_NULL;
365 edid_first_block_info *fst_blk = HI_NULL;
366
367 cap = &edid_info->capability;
368 hdmi_if_null_return(cap, HI_FAILURE);
369
370 fst_blk = (edid_first_block_info *)edid_info->edid_raw;
371 cap->basic_disp_para.max_image_width = fst_blk->width_cm;
372 cap->basic_disp_para.max_image_height = fst_blk->height_cm;
373
374 return HI_SUCCESS;
375 }
376
edid_phosphor(hdmi_edid_info * edid_info)377 static hi_s32 edid_phosphor(hdmi_edid_info *edid_info)
378 {
379 hdmi_sink_capability *cap = HI_NULL;
380 edid_first_block_info *fst_blk = HI_NULL;
381
382 edid_info(" phosphor or filter chromaticity...\n");
383 cap = &edid_info->capability;
384 hdmi_if_null_return(cap, HI_FAILURE);
385
386 fst_blk = (edid_first_block_info *)edid_info->edid_raw;
387 cap->phos_or_chrom_cap.red_x = (fst_blk->red_x << EDID_COLOR_OFFSET_NUM_1) |
388 ((fst_blk->red_green_low >> EDID_COLOR_OFFSET_NUM_3) & EDID_COLOR_LOW_BIT_MASK);
389 cap->phos_or_chrom_cap.red_y = (fst_blk->red_y << EDID_COLOR_OFFSET_NUM_1) |
390 ((fst_blk->red_green_low >> EDID_COLOR_OFFSET_NUM_2) & EDID_COLOR_LOW_BIT_MASK);
391 cap->phos_or_chrom_cap.green_x = (fst_blk->green_x << EDID_COLOR_OFFSET_NUM_1) |
392 ((fst_blk->red_green_low >> EDID_COLOR_OFFSET_NUM_1) & EDID_COLOR_LOW_BIT_MASK);
393 cap->phos_or_chrom_cap.green_y = (fst_blk->green_y << EDID_COLOR_OFFSET_NUM_1) |
394 (fst_blk->red_green_low & EDID_COLOR_LOW_BIT_MASK);
395 cap->phos_or_chrom_cap.blue_x = (fst_blk->blue_x << EDID_COLOR_OFFSET_NUM_1) |
396 ((fst_blk->black_white_low >> EDID_COLOR_OFFSET_NUM_3) & EDID_COLOR_LOW_BIT_MASK);
397 cap->phos_or_chrom_cap.blue_y = (fst_blk->blue_y << EDID_COLOR_OFFSET_NUM_1) |
398 ((fst_blk->black_white_low >> EDID_COLOR_OFFSET_NUM_2) & EDID_COLOR_LOW_BIT_MASK);
399 cap->phos_or_chrom_cap.white_x = (fst_blk->white_x << EDID_COLOR_OFFSET_NUM_1) |
400 ((fst_blk->black_white_low >> EDID_COLOR_OFFSET_NUM_1) & EDID_COLOR_LOW_BIT_MASK);
401 cap->phos_or_chrom_cap.white_y = (fst_blk->white_y << EDID_COLOR_OFFSET_NUM_1) |
402 (fst_blk->black_white_low & EDID_COLOR_LOW_BIT_MASK);
403
404 return HI_SUCCESS;
405 }
406
edid_std_timing(hdmi_edid_info * edid_info)407 static hi_s32 edid_std_timing(hdmi_edid_info *edid_info)
408 {
409 hi_u8 i;
410 hi_u8 asp_ratio;
411 hi_u8 *data = HI_NULL;
412 hdmi_sink_capability *cap = HI_NULL;
413 edid_first_block_info *fst_blk = HI_NULL;
414
415 cap = &edid_info->capability;
416 fst_blk = (edid_first_block_info *)edid_info->edid_raw;
417 hdmi_if_null_return(fst_blk, HI_FAILURE);
418 data = fst_blk->std_timing;
419 hdmi_if_null_return(data, HI_FAILURE);
420
421 (hi_void)memset_s(cap->std_timing, sizeof(cap->std_timing), 0, sizeof(cap->std_timing));
422 edid_info(" standard VESA timing identifications...\n");
423 for (i = 0; i < HDMI_EDID_MAX_STDTIMNG_COUNT; i++, data += 2) { /* std_timing data length is 2 */
424 if ((data[0] != EDID_STDTIMING_UNUSED_FLAG) || (data[1] != EDID_STDTIMING_UNUSED_FLAG)) {
425 cap->std_timing[i].hor_active = (data[0] + EDID_HORACTIVE_BASE) * EDID_HORACTIVE_FACTOR;
426 cap->std_timing[i].refresh_rate = (data[1] & EDID_REFRESH_RATE_MASK) + EDID_STDTIMING_RATE_BASE;
427 asp_ratio = (data[1] & EDID_ASPECT_RATIO_MASK) >> 6; /* asp_ratio offset is 6 */
428
429 switch (asp_ratio) {
430 case EDID_ASPECT_RATIO_16_10:
431 cap->std_timing[i].ver_active = cap->std_timing[i].hor_active * 10 / 16; /* aspect ratio, 16 : 10 */
432 break;
433 case EDID_ASPECT_RATIO_5_4:
434 cap->std_timing[i].ver_active = cap->std_timing[i].hor_active * 4 / 5; /* aspect ratio, 5 : 4 */
435 break;
436 case EDID_ASPECT_RATIO_4_3:
437 cap->std_timing[i].ver_active = cap->std_timing[i].hor_active * 3 / 4; /* aspect ratio, 4 : 3 */
438 break;
439 case EDID_ASPECT_RATIO_16_9:
440 cap->std_timing[i].ver_active = cap->std_timing[i].hor_active * 9 / 16; /* aspect ratio, 16 : 9 */
441 break;
442 default:
443 break;
444 }
445 edid_info("STDTIMNG field[%u] hor_active:%u\n", i, cap->std_timing[i].hor_active);
446 edid_info("STDTIMNG field[%u] ver_active:%u\n", i, cap->std_timing[i].ver_active);
447 edid_info("STDTIMNG field[%u] refresh_rate:%u\n", i, cap->std_timing[i].refresh_rate);
448 }
449 }
450
451 return HI_SUCCESS;
452 }
453
edid_establish_timing(hdmi_edid_info * edid_info)454 static hi_s32 edid_establish_timing(hdmi_edid_info *edid_info)
455 {
456 hi_u32 i;
457 hi_u32 dat32 = 0;
458 hdmi_sink_capability *cap = HI_NULL;
459 edid_first_block_info *fst_blk = HI_NULL;
460
461 cap = &edid_info->capability;
462 fst_blk = (edid_first_block_info *)edid_info->edid_raw;
463 hdmi_if_null_return(fst_blk, HI_FAILURE);
464
465 for (i = 0; i <= HDMI_EDID_ESTABTIMG_BUTT; i++) {
466 if (cap->estab_num >= HDMI_EDID_ESTABTIMG_BUTT) {
467 edid_warn("establish_timing estab_num over:%u!\n", cap->estab_num);
468 break;
469 }
470 /* if BYTE(i/8), BIT[i%8] is 1 */
471 if (fst_blk->est_timing[i / 8] & (0x01 << (i % 8))) {
472 cap->estab_timing[cap->estab_num++] = i;
473 }
474 }
475
476 edid_info(" established VESA timings...\n");
477 for (i = 0; i < EDID_ESTABLISH_TIMING; i++) {
478 /* 8'b, 16'b, 24'b, is data bit[16:9], bit[24:17], bit[32~25] */
479 dat32 |= ((hi_u32)fst_blk->est_timing[i]) << (8 * (EDID_ESTABLISH_TIMING - i));
480 }
481 i = 0;
482 while (dat32) {
483 if ((dat32 & 0x80000000) && (i < hdmi_array_size(g_establish_timing_str))) {
484 edid_info(" Established Timing: %s\n", g_establish_timing_str[i]);
485 }
486 dat32 <<= 1;
487 i++;
488 }
489
490 return HI_SUCCESS;
491 }
492
edid_digital_sync_signal_def(const edid_dtd_timing_block * dtd,hdmi_edid_pre_timing * cap_pre_timing)493 static hi_void edid_digital_sync_signal_def(const edid_dtd_timing_block *dtd, hdmi_edid_pre_timing *cap_pre_timing)
494 {
495 switch ((dtd->flags & EDID_SYNC_SIGNAL_TYPE_MASK) >> 1) { /* 1, sync_signal flags offset */
496 /* DCS: digital composite sync */
497 case EDID_SYNC_DCS_WS_0:
498 case EDID_SYNC_DCS_WS_1:
499 cap_pre_timing->ihs = HI_FALSE;
500 cap_pre_timing->ivs = HI_FALSE;
501 break;
502 case EDID_SYNC_DCS_DS_2:
503 case EDID_SYNC_DCS_DS_3:
504 break;
505 /* DSS: digital separate sync */
506 case EDID_SYNC_DSS_VN_HN_4:
507 cap_pre_timing->ihs = HI_FALSE;
508 cap_pre_timing->ivs = HI_FALSE;
509 break;
510 case EDID_SYNC_DSS_VN_HP_5:
511 cap_pre_timing->ihs = HI_TRUE;
512 cap_pre_timing->ivs = HI_FALSE;
513 break;
514 case EDID_SYNC_DSS_VP_HN_6:
515 cap_pre_timing->ihs = HI_FALSE;
516 cap_pre_timing->ivs = HI_TRUE;
517 break;
518 case EDID_SYNC_DSS_VP_HP_7:
519 cap_pre_timing->ihs = HI_TRUE;
520 cap_pre_timing->ivs = HI_TRUE;
521 break;
522 default:
523 break;
524 }
525
526 return;
527 }
528
edid_timing_param(const edid_dtd_timing_block * dtd,hdmi_edid_pre_timing * pre_timing)529 static hi_void edid_timing_param(const edid_dtd_timing_block *dtd, hdmi_edid_pre_timing *pre_timing)
530 {
531 hi_u32 temp;
532
533 /* VFB, 2+4 bits */
534 temp = dtd->hs_offset_vs_offset & EDID_VSO_MASK;
535 temp <<= 2; /* 2'b, bit[6:5] */
536 temp |= (dtd->vs_offset_pulse_width & EDID_UPPER_NIBBLE_MASK) >> 4; /* 4'b, bit[4:1] */
537 pre_timing->vfb = temp;
538
539 /* VBB, 4+8 bits */
540 temp = dtd->v_active_blank & EDID_LOWER_NIBBLE_MASK;
541 temp <<= 8; /* 8'b, bit[12:9] */
542 temp |= dtd->v_blank;
543 pre_timing->vbb = temp - pre_timing->vfb;
544
545 /* VACT, 4+8 bits */
546 temp = dtd->v_active_blank & EDID_UPPER_NIBBLE_MASK;
547 temp <<= 4; /* 4'b, bit[12:9] */
548 temp |= dtd->v_active;
549 pre_timing->vact = temp;
550
551 /* HFB, 2+8 bits */
552 temp = dtd->hs_offset_vs_offset & EDID_HSO_MASK;
553 temp <<= 2; /* 2'b, bit[12:9] */
554 temp |= dtd->h_sync_offset;
555 pre_timing->hfb = temp;
556
557 /* HBB, 4+8 bits */
558 temp = (dtd->h_active_blank & EDID_LOWER_NIBBLE_MASK);
559 temp <<= 8; /* 8'b, bit[12:9] */
560 temp |= dtd->h_blank;
561 pre_timing->hbb = temp - pre_timing->hfb;
562
563 /* HACT, 4+8 bits */
564 temp = dtd->h_active_blank & EDID_UPPER_NIBBLE_MASK;
565 temp <<= 4; /* 4'b, bit[12:9] */
566 temp |= dtd->h_active;
567 pre_timing->hact = temp;
568
569 /* VPW, 2+4 bits */
570 temp = dtd->hs_offset_vs_offset & EDID_VSPW_MASK;
571 temp <<= 4; /* 4'b, bit[6:5] */
572 temp |= (dtd->vs_offset_pulse_width & EDID_LOWER_NIBBLE_MASK);
573 pre_timing->vpw = temp;
574
575 /* HPW, 2+8 bits */
576 temp = dtd->hs_offset_vs_offset & EDID_HSPW_MASK;
577 temp <<= 4; /* 4'b, bit[10:9] */
578 temp |= dtd->h_sync_pulse_width;
579 pre_timing->hpw = temp;
580
581 /* H image size(mm), 4+8 bits */
582 temp = dtd->h_v_image_size & EDID_UPPER_NIBBLE_MASK;
583 temp <<= 4; /* 4'b, bit[12:9] */
584 temp |= dtd->h_image_size;
585 pre_timing->image_width = temp;
586
587 /* V image size(mm), 4+8 bits */
588 temp = dtd->h_v_image_size & EDID_LOWER_NIBBLE_MASK;
589 temp <<= 8; /* 8'b, bit[12:9] */
590 temp |= dtd->v_image_size;
591 pre_timing->image_height = temp;
592
593 /* interlaced flag */
594 pre_timing->interlace = (dtd->flags & BIT7_MASK) ? HI_TRUE : HI_FALSE;
595
596 /* digital sync signal definitions */
597 if ((dtd->flags & BIT4_MASK) != 0) {
598 edid_digital_sync_signal_def(dtd, pre_timing);
599 }
600 pre_timing->idv = HI_FALSE;
601
602 return;
603 }
604
edid_detail_timing(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)605 static hi_s32 edid_detail_timing(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
606 {
607 errno_t ret;
608 hi_u32 temp;
609 hi_u8 monitor_flag[3] = { 0x00, 0x00, 0x00 };
610 hdmi_edid_pre_timing *cap_pre_timing = HI_NULL;
611 edid_dtd_timing_block *dtd = HI_NULL;
612 edid_monitor_des_block *monitor_desc = HI_NULL;
613
614 if (cap->perfer_timing_num >= HDMI_EDID_MAX_DETAIL_TIMING_COUNT ||
615 len < EDID_DTD_SIZE) {
616 status->parse_warn |= 1 << EDID_PARSE_WARN_DTD_OVER;
617 edid_warn("dt_ds over max dt_ds cnt or less len:%u!\n", len);
618 return HI_SUCCESS;
619 }
620
621 /* case1: monitor descriptor */
622 if (osal_memcmp(data, monitor_flag, sizeof(monitor_flag)) == 0) {
623 /* case 1 */
624 if (data[3] == EDID_TYPE_MONITOR_NAME) { /* display product name */
625 monitor_desc = (edid_monitor_des_block *)data;
626 ret = memcpy_s(cap->mfrs_info.sink_name, HDMI_EDID_MAX_SINKNAME_COUNT,
627 monitor_desc->des_data, HDMI_EDID_MAX_SINKNAME_COUNT - 1);
628 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
629 cap->mfrs_info.sink_name[HDMI_EDID_MAX_SINKNAME_COUNT - 1] = '\0';
630 }
631
632 return HI_SUCCESS;
633 }
634
635 /* case2: detailed timing description */
636 dtd = (edid_dtd_timing_block *)data;
637 cap_pre_timing = &cap->perfer_timing[cap->perfer_timing_num];
638
639 /* pixel clock, k_hz */
640 temp = dtd->pixel_clk[1];
641 temp <<= 8; /* 8'b, BIT[32:9] */
642 temp |= dtd->pixel_clk[0];
643 temp *= EDID_PIXCLK_KHZ_FACTOR;
644 cap_pre_timing->pixel_clk = temp;
645
646 if (temp > 0) {
647 cap->perfer_timing_num++;
648 } else {
649 edid_info("dt_ds empty dt_ds, cur_num:%u\n", cap->perfer_timing_num);
650 return HI_SUCCESS;
651 }
652 edid_timing_param(dtd, cap_pre_timing);
653
654 return HI_SUCCESS;
655 }
656
edid_ext_num(hdmi_edid_info * edid_info)657 static hi_s32 edid_ext_num(hdmi_edid_info *edid_info)
658 {
659 hdmi_edid_status *status = HI_NULL;
660 hi_u8 *data = HI_NULL;
661 hdmi_sink_capability *cap = HI_NULL;
662
663 status = &edid_info->status;
664 data = edid_info->edid_raw;
665 cap = &edid_info->capability;
666
667 cap->ext_block_num = (hi_u8)data[EDID_EXTENSION_BLK_ADDR];
668 cap->support_hdmi = HI_FALSE;
669 edid_info(" extension flag...\n");
670 edid_info(" %-20s : %02u\n", "extensions", cap->ext_block_num);
671
672 if (cap->ext_block_num == 0) {
673 status->parse_warn |= 1 << EDID_PARSE_WARN_EXT_BLK_ZERO;
674 edid_warn("ext-BLK zero: 0x%02x \n", cap->ext_block_num);
675 } else if (cap->ext_block_num > (HDMI_EDID_MAX_BLOCK_NUM - 1)) {
676 status->parse_warn |= 1 << EDID_PARSE_WARN_EXT_BLK_OVER;
677 cap->ext_block_num = HDMI_EDID_MAX_BLOCK_NUM - 1;
678 edid_warn("ext-BLK cnt over: 0x%02x \n", cap->ext_block_num);
679 }
680
681 return HI_SUCCESS;
682 }
683
edid_first_blk_parse(hdmi_edid_info * edid_info)684 static hi_s32 edid_first_blk_parse(hdmi_edid_info *edid_info)
685 {
686 hi_s32 ret;
687 hi_u8 *data = HI_NULL;
688 hdmi_edid_status *status = HI_NULL;
689 hdmi_sink_capability *cap = HI_NULL;
690 edid_first_block_info *fst_info = HI_NULL;
691
692 edid_info(" first block parse...\n");
693 status = &edid_info->status;
694 data = edid_info->edid_raw;
695 cap = &edid_info->capability;
696 fst_info = (edid_first_block_info *)data;
697 hdmi_if_null_return(data, HI_FAILURE);
698
699 ret = edid_block_check_sum(data, status);
700 hdmi_if_failure_return(ret, HI_FAILURE);
701 /* 00h-07h header */
702 ret = edid_header_check(data, status);
703 hdmi_if_failure_return(ret, HI_FAILURE);
704 /* 08h-11h vendor info */
705 ret = edid_vendor_info(edid_info);
706 hdmi_if_failure_return(ret, HI_FAILURE);
707 /* 12h-13h version */
708 ret = edid_version(edid_info);
709 hdmi_if_failure_return(ret, HI_FAILURE);
710 /* 14h-18h basic display parameters/features */
711 ret = edid_basic_disp_para(edid_info);
712 hdmi_if_failure_return(ret, HI_FAILURE);
713 /* 19h-22h color characteristics */
714 ret = edid_phosphor(edid_info);
715 hdmi_if_failure_return(ret, HI_FAILURE);
716 /* 23h-25h established timings */
717 ret = edid_establish_timing(edid_info);
718 hdmi_if_failure_return(ret, HI_FAILURE);
719 /* 26h-35h standard timing identification */
720 ret = edid_std_timing(edid_info);
721 hdmi_if_failure_return(ret, HI_FAILURE);
722 /* 36h-47h first detailed timing descriptions */
723 ret = edid_detail_timing(cap, status, fst_info->detailed_timing1, EDID_DTD_SIZE);
724 hdmi_if_failure_return(ret, HI_FAILURE);
725 ret = edid_detail_timing(cap, status, fst_info->detailed_timing2, EDID_DTD_SIZE);
726 hdmi_if_failure_return(ret, HI_FAILURE);
727 ret = edid_detail_timing(cap, status, fst_info->detailed_timing3, EDID_DTD_SIZE);
728 hdmi_if_failure_return(ret, HI_FAILURE);
729 ret = edid_detail_timing(cap, status, fst_info->detailed_timing4, EDID_DTD_SIZE);
730 hdmi_if_failure_return(ret, HI_FAILURE);
731 ret = edid_ext_num(edid_info);
732 hdmi_if_failure_return(ret, HI_FAILURE);
733
734 return ret;
735 }
736
737 #if (!defined(CONFIG_HDMI_DEBUG_DISABLE) && !defined(HDMI_LOG_SUPPORT))
738 #ifndef HI_ADVCA_FUNCTION_RELEASE
739 static hi_char *g_audio_code_str[] = {
740 "reserved",
741 "linear PCM",
742 "AC3",
743 "MPEG1 (layers 1 & 2)",
744 "MP3 (MPEG1 layer 2)",
745 "MPEG2 (multichannel)",
746 "AAC",
747 "DTS",
748 "ATREC",
749 "one bit audio",
750 "dolby digital+",
751 "DTS-HD",
752 "MAT (MLP)",
753 "DST",
754 "WMA pro",
755 "reserved"
756 };
757 #else
758 static hi_char *g_audio_code_str[] = {};
759 static hi_char *g_video_code_str[] = {};
760 static hi_char *g_video_code_4k_str[] = {};
761 #endif
762 #endif
763
edid_audio_rate(hi_u8 byte,hi_u8 frm_code,hdmi_edid_audio_info * audio_info)764 static hi_void edid_audio_rate(hi_u8 byte, hi_u8 frm_code, hdmi_edid_audio_info *audio_info)
765 {
766 hi_u32 count = 0;
767
768 if (byte & BIT0_MASK) {
769 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_32K;
770 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
771 count++;
772 }
773 if (byte & BIT1_MASK) {
774 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_44K;
775 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
776 count++;
777 }
778 if (byte & BIT2_MASK) {
779 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_48K;
780 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
781 count++;
782 }
783 if (byte & BIT3_MASK) {
784 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_88K;
785 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
786 count++;
787 }
788 if (byte & BIT4_MASK) {
789 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_96K;
790 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
791 count++;
792 }
793 /* CEA-861-F add for HDMI2.0 */
794 if (frm_code >= 1 && frm_code <= 14) { /* frm_code size extent 1~14 */
795 if (byte & BIT5_MASK) {
796 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_176K;
797 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
798 count++;
799 }
800 if (byte & BIT6_MASK) {
801 audio_info->support_sample_rate[count] = HDMI_SAMPLE_RATE_192K;
802 edid_info(" %-20s : %u hz\n", "sample frequencies", audio_info->support_sample_rate[count]);
803 count++;
804 }
805 }
806 audio_info->support_sample_rate_num = count;
807
808 return;
809 }
810
edid_audio_depth_and_max_rate(hi_u8 byte,hi_u8 frm_code,hdmi_edid_audio_info * audio_info)811 static hi_void edid_audio_depth_and_max_rate(hi_u8 byte, hi_u8 frm_code, hdmi_edid_audio_info *audio_info)
812 {
813 hi_u32 count = 0;
814
815 if (frm_code == 1) {
816 if (byte & BIT0_MASK) {
817 audio_info->support_bit_depth[count] = HDMI_AUDIO_BIT_DEPTH_16;
818 edid_info(" %-20s : %u bit\n", "bit depth", audio_info->support_bit_depth[count]);
819 count++;
820 }
821 if (byte & BIT1_MASK) {
822 audio_info->support_bit_depth[count] = HDMI_AUDIO_BIT_DEPTH_20;
823 edid_info(" %-20s : %u bit\n", "bit depth", audio_info->support_bit_depth[count]);
824 count++;
825 }
826 if (byte & BIT2_MASK) {
827 audio_info->support_bit_depth[count] = HDMI_AUDIO_BIT_DEPTH_24;
828 edid_info(" %-20s : %u bit\n", "bit depth", audio_info->support_bit_depth[count]);
829 count++;
830 }
831 audio_info->support_bit_depth_num = count;
832 } else if ((frm_code > 1) && (frm_code < 9)) { /* audio format type 2~8 */
833 audio_info->max_bit_rate = byte * EDID_AUDIO_BITRATE_FACTOR;
834 edid_info(" %-20s : %u k_hz\n", "maximum bit rate", audio_info->max_bit_rate);
835 } else {
836 edid_info(" EDID audio format type %u byte3 reserved!\n", frm_code);
837 }
838
839 return;
840 }
841
edid_audio_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)842 static hi_s32 edid_audio_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
843 {
844 hi_u8 i;
845 hi_u8 frm_code;
846 hi_u8 cur_num;
847 hdmi_edid_audio_info *audio_info = HI_NULL;
848 #if (!defined(CONFIG_HDMI_DEBUG_DISABLE) && !defined(HDMI_LOG_SUPPORT))
849 hi_char *audio_code_str = HI_NULL;
850 #endif
851
852 audio_info = cap->audio_info;
853 edid_info(" audio data block (length=%02u)...\n", len);
854 /* each short audio descriptor is 3-bytes long */
855 if ((len / EDID_AUDIO_DESCRIPTOR_SIZE) > 10) { /* 10, audio capability count */
856 edid_err(" audio capability count(%u) is error!\n", len);
857 status->parse_warn |= (1 << EDID_PARSE_WARN_AUDIO_CNT_OVER);
858 return HI_FAILURE;
859 }
860
861 for (i = 0; i < (len / EDID_AUDIO_DESCRIPTOR_SIZE); i++) {
862 cur_num = cap->audio_info_num;
863
864 if (cur_num >= HDMI_EDID_MAX_AUDIO_CAP_COUNT) {
865 status->parse_warn |= 1 << EDID_PARSE_WARN_AUDIO_CNT_OVER;
866 edid_warn(" audio capability count over max-num:%u \n", HDMI_EDID_MAX_AUDIO_CAP_COUNT);
867 break;
868 }
869 /* byte-0 */
870 edid_info(" %-20s : 0x%02X, 0x%02X, 0x%02X\n", "short audio descriptor",
871 data[i * EDID_AUDIO_DESCRIPTOR_SIZE], data[i * EDID_AUDIO_DESCRIPTOR_SIZE + 1],
872 data[i * EDID_AUDIO_DESCRIPTOR_SIZE + 2]);
873
874 frm_code = (data[i * EDID_AUDIO_DESCRIPTOR_SIZE] & EDID_AUDIO_FORMAT_MASK) >> 3; /* 3'b, bit[4:1] */
875 audio_info[cur_num].aud_channel = (data[i * EDID_AUDIO_DESCRIPTOR_SIZE] & EDID_AUDIO_CHANNEL_MASK) + 1;
876 audio_info[cur_num].aud_fmt_code = (hdmi_audio_format_code)frm_code;
877
878 #if (!defined(CONFIG_HDMI_DEBUG_DISABLE) && !defined(HDMI_LOG_SUPPORT))
879 audio_code_str = g_audio_code_str[frm_code];
880 edid_info(" %-20s : %02u\n", "max. number of channels", audio_info[cur_num].aud_channel);
881 edid_info(" %-20s : %s\n", "audio format code", audio_code_str);
882 #endif
883 if (frm_code > HDMI_AUDIO_CODING_TYPE_STREAM && frm_code < HDMI_AUDIO_CODING_TYPE_BUTT) {
884 cap->audio_info_num++;
885 } else {
886 status->parse_warn |= 1 << EDID_PARSE_WARN_AUDIO_FMT_INVALID;
887 edid_warn(" CEA-861-F not support audio frm:%u \n", frm_code);
888 break;
889 }
890 /* byte-1 */
891 edid_audio_rate(data[i * EDID_AUDIO_DESCRIPTOR_SIZE + 1], frm_code, &audio_info[cur_num]);
892 /* byte-2 */
893 edid_audio_depth_and_max_rate(data[i * EDID_AUDIO_DESCRIPTOR_SIZE + 2], frm_code, &audio_info[cur_num]);
894 }
895
896 return HI_SUCCESS;
897 }
898
edid_video_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)899 static hi_s32 edid_video_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
900 {
901 hi_u8 i;
902 hi_u32 inplicit_native = EDID_VIC_INVALID_ZERO;
903 hi_u32 vic_all = EDID_VIC_INVALID_ZERO;
904 hi_u32 vic_lower = EDID_VIC_INVALID_ZERO;
905
906 edid_info(" video data block (length=%02u)...\n", len);
907 for (i = 0; i < len; i++) {
908 vic_all = data[i];
909 vic_lower = data[i] & EDID_VIC_LOWER7_MASK;
910
911 /* avoid full over */
912 if (cap->support_vic_num >= HDMI_EDID_MAX_VIC_COUNT) {
913 status->parse_warn |= 1 << EDID_PARSE_WARN_VIC_CNT_OVER;
914 edid_warn("VDB vic count over:%u !\n", HDMI_EDID_MAX_VIC_COUNT);
915 break;
916 }
917
918 /* avoid invalid vic */
919 if (vic_all == EDID_VIC_INVALID_ZERO) {
920 status->parse_warn |= 1 << EDID_PARSE_WARN_VIC_INVALID;
921 edid_warn("VDB the %u vic: %u ! \n", i, vic_all);
922 continue;
923 }
924
925 /* explicit native */
926 if ((cap->native_format == EDID_VIC_INVALID_ZERO) &&
927 (vic_all & BIT7_MASK) && (vic_lower <= EDID_VIC_NATIVE_MAX)) {
928 cap->native_format = vic_lower;
929 }
930
931 /* set the first valid VIC as implicit native */
932 if (inplicit_native == EDID_VIC_INVALID_ZERO) {
933 inplicit_native = vic_all;
934 }
935
936 if ((vic_all & BIT7_MASK) && (vic_lower <= EDID_VIC_NATIVE_MAX)) {
937 cap->support_format[cap->support_vic_num] = vic_lower;
938 } else {
939 cap->support_format[cap->support_vic_num] = vic_all;
940 }
941 cap->support_vic_num++;
942 }
943
944 if (cap->native_format == EDID_VIC_INVALID_ZERO) {
945 cap->native_format = inplicit_native;
946 }
947
948 return HI_SUCCESS;
949 }
950
edid_hfvs21_db(hdmi_sink_capability * cap,const hi_u8 * data)951 static hi_void edid_hfvs21_db(hdmi_sink_capability *cap, const hi_u8 *data)
952 {
953 cap->fapa_start_location = (data[0] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
954 cap->allm = (data[0] & BIT1_MASK) ? HI_TRUE : HI_FALSE;
955 cap->fva = (data[0] & BIT2_MASK) ? HI_TRUE : HI_FALSE;
956 cap->cnm_vrr = (data[0] & BIT3_MASK) ? HI_TRUE : HI_FALSE;
957 cap->cinema_vrr = (data[0] & BIT4_MASK) ? HI_TRUE : HI_FALSE;
958 cap->m_delta = (data[0] & BIT5_MASK) ? HI_TRUE : HI_FALSE;
959 cap->vrr_min = data[1] & 0x3F;
960 cap->vrr_max = data[1] & 0xC0;
961 cap->vrr_max = (cap->vrr_max << 2) | data[2]; /* 2'b, bit[6:5] */
962 cap->dsc_info.dsc_1p2 = (data[3] & BIT7_MASK) ? HI_TRUE : HI_FALSE;
963 cap->dsc_info.dsc_native_420 = (data[3] & BIT6_MASK) ? HI_TRUE : HI_FALSE;
964 cap->dsc_info.dsc_all_bpp = (data[3] & BIT3_MASK) ? HI_TRUE : HI_FALSE;
965 cap->dsc_info.dsc_16bpc = (data[3] & BIT2_MASK) ? HI_TRUE : HI_FALSE;
966 cap->dsc_info.dsc_12bpc = (data[3] & BIT1_MASK) ? HI_TRUE : HI_FALSE;
967 cap->dsc_info.dsc_10bpc = (data[3] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
968 cap->dsc_info.dsc_max_slices = (data[4] & EDID_LOWER_NIBBLE_MASK);
969 cap->dsc_info.dsc_max_frl_rate = (data[4] & EDID_UPPER_NIBBLE_MASK);
970 cap->dsc_info.dsc_total_chunk_k_bytes = (data[5] & 0x3F);
971
972 return;
973 }
974
edid_hfvs_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)975 static hi_s32 edid_hfvs_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
976 {
977 if (len < 7 || len > 31) { /* hfvs db length extent 7~31 */
978 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
979 edid_warn("HFVSDB len:%u\n", len);
980 return HI_SUCCESS;
981 }
982
983 /* byte-3 ,version */
984 if (data[3] != EDID_HFVSDB_VERSION) {
985 status->parse_warn |= 1 << EDID_PARSE_WARN_HFVSDB_INVALID;
986 edid_warn(" HFVSDB version:%u\n", data[3]);
987 }
988 edid_info(" HDMI forum vendor specific data block %-36s : %02u\n", "version", data[3]);
989 /* byte-4 */
990 cap->max_tmds_clock = data[4];
991 cap->max_tmds_clock *= EDID_TMDS_FACTOR;
992 cap->support_hdmi_20 = (cap->max_tmds_clock >= EDID_MAX_HDMI14_TMDS_RATE) ? HI_TRUE : HI_FALSE;
993 edid_info(" %-20s : %u m_hz\n", "max_tmds_character_rate", cap->max_tmds_clock);
994 /* byte-5 */
995 cap->support3d_osd_disparity = (data[5] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
996 cap->support3d_dual_view = (data[5] & BIT1_MASK) ? HI_TRUE : HI_FALSE;
997 cap->support3d_independent_view = (data[5] & BIT2_MASK) ? HI_TRUE : HI_FALSE;
998 cap->support_lte340_mcsc_scrameble = (data[5] & BIT3_MASK) ? HI_TRUE : HI_FALSE;
999 cap->ccbpci = (data[5] & BIT4_MASK) ? HI_TRUE : HI_FALSE;
1000 cap->support_rr_capable = (data[5] & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1001 cap->support_scdc = (data[5] & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1002
1003 edid_info(" %-20s : %s\n", "scdc_present", cap->support_scdc ? "yes" : "no");
1004 edid_info(" %-20s : %s\n", "rr_capable", cap->support_rr_capable ? "yes" : "no");
1005 edid_info(" %-20s : %s\n", "lte_340_mcsc_scramble", cap->support_lte340_mcsc_scrameble ? "yes" : "no");
1006 edid_info(" %-20s : %s\n", "independent_view", cap->support3d_independent_view ? "yes" : "no");
1007 edid_info(" %-20s : %s\n", "dual_view", cap->support3d_dual_view ? "yes" : "no");
1008 edid_info(" %-20s : %s\n", "3_d_osd_disparity", cap->support3d_osd_disparity ? "yes" : "no");
1009 /* byte-6 */
1010 cap->deep_color_y420.deep_color30_bit = (data[6] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1011 cap->deep_color_y420.deep_color36_bit = (data[6] & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1012 cap->deep_color_y420.deep_color48_bit = (data[6] & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1013 edid_info(" %-20s : %s\n", "dc_48bit_420", cap->deep_color_y420.deep_color48_bit ? "yes" : "no");
1014 edid_info(" %-20s : %s\n", "dc_36bit_420", cap->deep_color_y420.deep_color36_bit ? "yes" : "no");
1015 edid_info(" %-20s : %s\n", "dc_30bit_420", cap->deep_color_y420.deep_color30_bit ? "yes" : "no");
1016 cap->max_frl_rate = (data[6] & EDID_UPPER_NIBBLE_MASK) >> 4; /* 4'b, bit[4:1] */
1017
1018 if (len > 7) { /* hfvs db length extent 7~31 */
1019 edid_hfvs21_db(cap, &data[7]);
1020 }
1021
1022 return HI_SUCCESS;
1023 }
1024
1025 static hi_u32 g_common_4k_vic[] = {
1026 0,
1027 HDMI_3840X2160P30_16_9,
1028 HDMI_3840X2160P25_16_9,
1029 HDMI_3840X2160P24_16_9,
1030 HDMI_4096X2160P24_256_135
1031 };
1032
edid_latency_parse(hdmi_sink_capability * cap,hi_u8 * data,hi_u8 * offset)1033 static hi_void edid_latency_parse(hdmi_sink_capability *cap, hi_u8 *data, hi_u8 *offset)
1034 {
1035 if (cap->latency_fields_present) {
1036 cap->video_latency = data[(*offset)++];
1037 cap->audio_latency = data[(*offset)++];
1038 edid_info(" %-20s : 0x%02X\n", "video latency", cap->video_latency);
1039 edid_info(" %-20s : 0x%02X\n", "audio latency", cap->audio_latency);
1040 }
1041 if (cap->i_latency_fields_present) {
1042 cap->interlaced_video_latency = data[(*offset)++];
1043 cap->interlaced_audio_latency = data[(*offset)++];
1044 edid_info(" %-20s : 0x%02X\n", "interlaced video latency", cap->interlaced_video_latency);
1045 edid_info(" %-20s : 0x%02X\n", "interlaced audio latency", cap->interlaced_audio_latency);
1046 }
1047
1048 return;
1049 }
1050
edid_vic_parse(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 hdmi_vic_len,hi_u8 * offset,hi_u8 * data)1051 static hi_void edid_vic_parse(hdmi_sink_capability *cap, hdmi_edid_status *status,
1052 hi_u8 hdmi_vic_len, hi_u8 *offset, hi_u8 *data)
1053 {
1054 hi_u32 i;
1055 hi_u8 byte;
1056
1057 for (i = 0; i < hdmi_vic_len; i++) {
1058 byte = data[(*offset)++];
1059 if (cap->support_vic_num < HDMI_EDID_MAX_VIC_COUNT) {
1060 if (byte < hdmi_array_size(g_common_4k_vic)) {
1061 cap->support_format[cap->support_vic_num++] = g_common_4k_vic[byte];
1062 }
1063 } else {
1064 status->parse_warn |= 1 << EDID_PARSE_WARN_VIC_CNT_OVER;
1065 break;
1066 }
1067 }
1068
1069 return;
1070 }
1071
edid_3d_parse(hdmi_sink_capability * cap,hi_u8 * data,hi_u8 * offset)1072 static hi_void edid_3d_parse(hdmi_sink_capability *cap, hi_u8 *data, hi_u8 *offset)
1073 {
1074 hi_u8 byte;
1075
1076 /* 3d structure_all_15...8 reserved */
1077 byte = data[(*offset)++] & 0xFF;
1078 cap->_3d_info.support_3d_type[HDMI_EDID_3D_SIDE_BY_SIDE_HALF] = (byte & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1079 byte = data[(*offset)++] & 0xFF;
1080 cap->_3d_info.support_3d_type[HDMI_EDID_3D_FRAME_PACKETING] = (byte & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1081 cap->_3d_info.support_3d_type[HDMI_EDID_3D_FIELD_ALTERNATIVE] = (byte & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1082 cap->_3d_info.support_3d_type[HDMI_EDID_3D_LINE_ALTERNATIVE] = (byte & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1083 cap->_3d_info.support_3d_type[HDMI_EDID_3D_SIDE_BY_SIDE_FULL] = (byte & BIT3_MASK) ? HI_TRUE : HI_FALSE;
1084 cap->_3d_info.support_3d_type[HDMI_EDID_3D_L_DEPTH] = (byte & BIT4_MASK) ? HI_TRUE : HI_FALSE;
1085 cap->_3d_info.support_3d_type[HDMI_EDID_3D_L_DEPTH_GRAPHICS_GRAPHICS_DEPTH] =
1086 (byte & BIT5_MASK) ? HI_TRUE : HI_FALSE;
1087 cap->_3d_info.support_3d_type[HDMI_EDID_3D_TOP_AND_BOTTOM] = (byte & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1088
1089 return;
1090 }
1091
edid_cec_phy_addr_prase(hdmi_sink_capability * cap,const hi_u8 * data)1092 static hi_void edid_cec_phy_addr_prase(hdmi_sink_capability *cap, const hi_u8 *data)
1093 {
1094 cap->cec_addr.phy_addr_a = (data[0] & EDID_UPPER_NIBBLE_MASK) >> 4;
1095 cap->cec_addr.phy_addr_b = (data[0] & EDID_LOWER_NIBBLE_MASK);
1096 cap->cec_addr.phy_addr_c = (data[1] & EDID_UPPER_NIBBLE_MASK) >> 4;
1097 cap->cec_addr.phy_addr_d = (data[1] & EDID_LOWER_NIBBLE_MASK);
1098
1099 cap->cec_addr.phy_addr_valid = ((cap->cec_addr.phy_addr_a != EDID_CEC_INVALID_ADDR) &&
1100 (cap->cec_addr.phy_addr_b != EDID_CEC_INVALID_ADDR) &&
1101 (cap->cec_addr.phy_addr_c != EDID_CEC_INVALID_ADDR) &&
1102 (cap->cec_addr.phy_addr_d != EDID_CEC_INVALID_ADDR));
1103
1104 edid_info(" %-20s : %02d.%02d.%02d.%02d\n", "CEC Address",
1105 cap->cec_addr.phy_addr_a, cap->cec_addr.phy_addr_b, cap->cec_addr.phy_addr_c, cap->cec_addr.phy_addr_d);
1106
1107 return;
1108 }
1109
edid_deep_color_prase(hdmi_sink_capability * cap,hi_u8 data)1110 static hi_void edid_deep_color_prase(hdmi_sink_capability *cap, hi_u8 data)
1111 {
1112 edid_info(" %-20s : 0x%02X\n", "color depth flags", data);
1113
1114 cap->support_dvi_dual = (data & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1115 cap->deep_color.deep_color_y444 = (data & BIT3_MASK) ? HI_TRUE : HI_FALSE;
1116 cap->deep_color.deep_color30_bit = (data & BIT4_MASK) ? HI_TRUE : HI_FALSE;
1117 cap->deep_color.deep_color36_bit = (data & BIT5_MASK) ? HI_TRUE : HI_FALSE;
1118 cap->deep_color.deep_color48_bit = (data & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1119 cap->supports_ai = (data & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1120
1121 return;
1122 }
1123
edid_vsdb_prase_step9(hdmi_sink_capability * cap,hi_u8 * data,hdmi_edid_status * status,hi_u8 len)1124 static hi_void edid_vsdb_prase_step9(hdmi_sink_capability *cap, hi_u8 *data, hdmi_edid_status *status, hi_u8 len)
1125 {
1126 hi_u8 offset, byte;
1127 hi_u8 hdmi_vic_len, hdmi_3d_len;
1128 hi_bool _3d_parse = HI_FALSE;
1129 hi_bool _3d_present = HI_FALSE;
1130 hi_u8 _3d_multi_present = 0;
1131
1132 offset = 8; /* offset 8 bit, data byte count + 1 */
1133 edid_latency_parse(cap, data, &offset);
1134
1135 byte = data[offset++]; /* data[8] */
1136 if (cap->hdmi_video_present) {
1137 _3d_multi_present = (byte & (BIT6_MASK | BIT5_MASK)) >> 5; /* 5'b, BIT[3:2] */
1138 _3d_present = (byte & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1139 cap->_3d_info.support_3d = (byte & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1140 edid_info(" %-20s : %s\n", "3D-support", _3d_present ? "yes" : "no");
1141 edid_info(" %-20s : %02u\n", "3_d_multi_present", _3d_multi_present);
1142 edid_info(" %-20s : %02u\n", "image_size", (byte & (BIT4_MASK | BIT3_MASK)) >> 3); /* 3'b, BIT[1] */
1143 }
1144
1145 if (len < 10) { /* 10 offset for 3D */
1146 return;
1147 }
1148 /* 10, byte-13, VIC & 3D len */
1149 byte = data[offset];
1150 hdmi_3d_len = (byte & EDID_HDMI_3D_LEN_MASK);
1151 hdmi_vic_len = (byte & EDID_HDMI_VIC_LEN_MASK) >> 5; /* 5'b, BIT[3:1] */
1152 edid_info(" %-20s : %02u\n", "HDMI_VIC_LEN", hdmi_vic_len);
1153 edid_info(" %-20s : %02u\n", "HDMI_3D_LEN", hdmi_3d_len);
1154 /* byte-14 & following,VIC */
1155 offset++;
1156 if (hdmi_vic_len + offset <= len) {
1157 edid_vic_parse(cap, status, hdmi_vic_len, &offset, data);
1158 }
1159
1160 /* byte-following, 3D */
1161 _3d_parse = ((_3d_present == HI_TRUE) && (hdmi_3d_len > 0) && (len >= (hdmi_3d_len + offset)) &&
1162 ((_3d_multi_present == EDID_3DMULTI_PRESENT_LOWER8) || (_3d_multi_present == EDID_3DMULTI_PRESENT_UPPER8)));
1163 if (_3d_parse == HI_TRUE) {
1164 edid_3d_parse(cap, data, &offset);
1165 }
1166
1167 return;
1168 }
1169
edid_vsdb(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1170 static hi_s32 edid_vsdb(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1171 {
1172 /* byte-0~2, IEEE have been parsed outside the func */
1173 edid_info(" HDMI-LLC vendor specific data block...\n");
1174
1175 if (len < 5) { /* 5, byte-3~4, CEC addr */
1176 edid_warn("VSDB len:%u\n", len);
1177 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
1178 return HI_SUCCESS;
1179 } else {
1180 edid_cec_phy_addr_prase(cap, &data[3]);
1181 }
1182
1183 if (len >= 6) { /* 6, byte-5, color depth flags */
1184 edid_deep_color_prase(cap, data[5]);
1185 }
1186
1187 if (len >= 7) { /* 7, byte-6, max tmds clock */
1188 cap->max_tmds_clock = data[6];
1189 cap->max_tmds_clock *= EDID_TMDS_FACTOR;
1190 cap->support_hdmi_20 = (cap->max_tmds_clock >= EDID_MAX_HDMI14_TMDS_RATE) ? HI_TRUE : HI_FALSE;
1191 edid_info(" %-20s : %u m_hz\n", "max TMDS clock", cap->max_tmds_clock);
1192 }
1193
1194 if (len >= 8) { /* 8, byte-7, sink present */
1195 cap->hdmi_video_present = (data[7] & BIT5_MASK) ? HI_TRUE : HI_FALSE;
1196 cap->i_latency_fields_present = (data[7] & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1197 cap->latency_fields_present = (data[7] & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1198 }
1199
1200 if (len >= 9) { /* 9 offset for 3D */
1201 edid_vsdb_prase_step9(cap, data, status, len);
1202 }
1203
1204 return HI_SUCCESS;
1205 }
1206
edid_speaker_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1207 static hi_s32 edid_speaker_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1208 {
1209 hi_u8 byte;
1210
1211 if (len < 2) { /* 2, speaker_db min length */
1212 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
1213 status->parse_warn |= 1 << EDID_PARSE_WARN_SPKDB_INVALID;
1214 edid_warn("SPKDB len:%u\n", len);
1215 return HI_SUCCESS;
1216 }
1217 edid_info(" speaker alloc data block (length=%02u)...\n", len);
1218 /* byte-0 */
1219 byte = data[0];
1220 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FL_FR] = (byte & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1221 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_LFE] = (byte & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1222 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FC] = (byte & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1223 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_RL_RR] = (byte & BIT3_MASK) ? HI_TRUE : HI_FALSE;
1224 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_RC] = (byte & BIT4_MASK) ? HI_TRUE : HI_FALSE;
1225 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FLC_FRC] = (byte & BIT5_MASK) ? HI_TRUE : HI_FALSE;
1226 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_RLC_RRC] = (byte & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1227 /* NOTE: the following is CEA-861-F add for HDMI2.0 */
1228 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FLW_FRW] = (byte & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1229 /* byte-1 */
1230 byte = data[1];
1231 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FLH_FRH] = (byte & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1232 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_TC] = (byte & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1233 cap->support_audio_speaker[HDMI_EDID_AUDIO_SPEAKER_FCH] = (byte & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1234
1235 return HI_SUCCESS;
1236 }
1237
edid_colorimetry_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1238 static hi_s32 edid_colorimetry_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1239 {
1240 hi_u8 byte;
1241
1242 if (len < 3) { /* 3, is colorimetry db 1 ext tag code + 2 bytes payload */
1243 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
1244 edid_err("colormetry_db len!\n");
1245 return HI_SUCCESS;
1246 }
1247
1248 /* byte-0 */
1249 byte = data[0];
1250 cap->color_metry.xvycc601 = (byte & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1251 cap->color_metry.xvycc709 = (byte & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1252 cap->color_metry.sycc601 = (byte & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1253 cap->color_metry.adoble_ycc601 = (byte & BIT3_MASK) ? HI_TRUE : HI_FALSE;
1254 cap->color_metry.adoble_rgb = (byte & BIT4_MASK) ? HI_TRUE : HI_FALSE;
1255 cap->color_metry.bt2020c_ycc = (byte & BIT5_MASK) ? HI_TRUE : HI_FALSE;
1256 cap->color_metry.bt2020_ycc = (byte & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1257 cap->color_metry.bt2020_rgb = (byte & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1258
1259 /* byte-1 */
1260 cap->md_bit = data[1];
1261
1262 return HI_SUCCESS;
1263 }
1264
edid_y420_video_db(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1265 static hi_s32 edid_y420_video_db(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1266 {
1267 hi_u8 i;
1268 hi_u32 vic;
1269
1270 for (i = 0; i < len - 1; i++) {
1271 vic = data[i];
1272 if (cap->only_support_y420_vic_num >= HDMI_EDID_MAX_VIC_COUNT) {
1273 status->parse_warn |= 1 << EDID_PARSE_WARN_Y420VDB_VIC_OVER;
1274 edid_warn("y420_video_db vic count over:%u !\n", HDMI_EDID_MAX_VIC_COUNT);
1275 break;
1276 }
1277
1278 if ((vic == EDID_VIC_INVALID_ZERO) || ((vic >= EDID_VIC_INVALID_LOW) && (vic <= EDID_VIC_INVALID_HIGH))) {
1279 status->parse_warn |= 1 << EDID_PARSE_WARN_VIC_INVALID;
1280 edid_warn("y420_video_db the %u is invalid vic: %u ! \n", i, vic);
1281 continue;
1282 }
1283
1284 cap->only_support_y420_format[cap->only_support_y420_vic_num++] = vic;
1285 cap->color_space.ycbcr420 = HI_TRUE;
1286 }
1287
1288 return HI_SUCCESS;
1289 }
1290
edid_y420_cap_map_db(hdmi_sink_capability * cap,hi_u8 * data,hi_u8 len)1291 static hi_s32 edid_y420_cap_map_db(hdmi_sink_capability *cap, hi_u8 *data, hi_u8 len)
1292 {
1293 hi_u32 i;
1294 hi_u32 loop;
1295
1296 /*
1297 * cap->support_y420_format is sv_ds parsed from video data block(s) in order.
1298 * when the length field is 1, indicates that all the sv_ds support YUV420.
1299 */
1300 if (len == 1) {
1301 for (i = 0; (i < cap->support_vic_num) && (i < HDMI_EDID_MAX_VIC_COUNT); i++) {
1302 if ((cap->support_format[i] <= HDMI_EDID_MAX_REAL_VIC) &&
1303 (cap->support_y420_vic_num < HDMI_EDID_MAX_VIC_COUNT)) {
1304 cap->support_y420_format[cap->support_y420_vic_num++] = cap->support_format[i];
1305 cap->color_space.ycbcr420 = HI_TRUE;
1306 }
1307 }
1308 } else { /* or, for sv_ds which support YUV420, the corresponding bit shall be set to 1 here. */
1309 loop = len * 8; /* 8bit eq 1 byte */
1310 for (i = 0; (i < loop) && (i < cap->support_vic_num) && (i < HDMI_EDID_MAX_VIC_COUNT); i++) {
1311 /* BYTE n(i/8), BIT x(i%8) */
1312 if ((data[i / 8] & (0x01 << (i % 8))) &&
1313 (cap->support_y420_vic_num < HDMI_EDID_MAX_VIC_COUNT)) {
1314 cap->support_y420_format[cap->support_y420_vic_num++] = cap->support_format[i];
1315 cap->color_space.ycbcr420 = HI_TRUE;
1316 }
1317 }
1318 }
1319 return HI_SUCCESS;
1320 }
1321
1322 #ifdef HDMI_HDR_SUPPORT
edid_dolby_version_parse(hdmi_edid_dolby_cap * dolby_cap,const hi_u8 * data)1323 static hi_void edid_dolby_version_parse(hdmi_edid_dolby_cap *dolby_cap, const hi_u8 *data)
1324 {
1325 switch (dolby_cap->vsvdb_version) {
1326 case EDID_DOLBY_VSVDB_VERSION_0:
1327 dolby_cap->global_dimming = (data[3] & BIT2_MASK) ? HI_TRUE : HI_FALSE;
1328 dolby_cap->red_x = (data[5] << EDID_DOLBY_CAP_OFFSET_3) |
1329 ((data[4] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1330 dolby_cap->red_y = (data[6] << EDID_DOLBY_CAP_OFFSET_3) |
1331 ((data[4]) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1332 dolby_cap->green_x = (data[8] << EDID_DOLBY_CAP_OFFSET_3) |
1333 ((data[7] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1334 dolby_cap->green_y = (data[9] << EDID_DOLBY_CAP_OFFSET_3) | (data[7] & EDID_DOLBY_LOWER_NIBBLE_MASK);
1335 dolby_cap->blue_x = (data[11] << EDID_DOLBY_CAP_OFFSET_3) |
1336 ((data[10] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1337 dolby_cap->blue_y = (data[12] << EDID_DOLBY_CAP_OFFSET_3) | (data[10] & EDID_DOLBY_LOWER_NIBBLE_MASK);
1338 dolby_cap->un_other_caps.dolby_caps_ver0.white_x = (data[14] << EDID_DOLBY_CAP_OFFSET_3) |
1339 ((data[13] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1340 dolby_cap->un_other_caps.dolby_caps_ver0.white_y = (data[15] << EDID_DOLBY_CAP_OFFSET_3) |
1341 (data[13] & EDID_DOLBY_LOWER_NIBBLE_MASK);
1342 dolby_cap->min_luminance = (data[17] << EDID_DOLBY_CAP_OFFSET_3) |
1343 ((data[16] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1344 dolby_cap->max_luminance = (data[18] << EDID_DOLBY_CAP_OFFSET_3) |
1345 (data[16] & EDID_DOLBY_LOWER_NIBBLE_MASK);
1346 dolby_cap->un_other_caps.dolby_caps_ver0.d_mminor_version = (data[19] & EDID_DOLBY_LOWER_NIBBLE_MASK);
1347 dolby_cap->un_other_caps.dolby_caps_ver0.d_mmajor_version =
1348 ((data[19] >> EDID_DOLBY_CAP_OFFSET_3) & EDID_DOLBY_LOWER_NIBBLE_MASK);
1349 break;
1350 case EDID_DOLBY_VSVDB_VERSION_1:
1351 dolby_cap->un_other_caps.dolby_caps_ver1.dm_version = ((data[3] >> EDID_DOLBY_CAP_OFFSET_2) &
1352 EDID_DOLBY_LOWER_3BIT_MASK);
1353 dolby_cap->global_dimming = (data[4] & BIT0_MASK);
1354 dolby_cap->max_luminance = ((data[4] >> EDID_DOLBY_CAP_OFFSET_1) & EDID_DOLBY_LOWER_7BIT_MASK);
1355 dolby_cap->un_other_caps.dolby_caps_ver1.colorimetry = (data[5] & BIT0_MASK);
1356 dolby_cap->min_luminance = ((data[5] >> EDID_DOLBY_CAP_OFFSET_1) & EDID_DOLBY_LOWER_7BIT_MASK);
1357 dolby_cap->red_x = data[7];
1358 dolby_cap->red_y = data[8];
1359 dolby_cap->green_x = data[9];
1360 dolby_cap->green_y = data[10];
1361 dolby_cap->blue_x = data[11];
1362 dolby_cap->blue_y = data[12];
1363 break;
1364 default:
1365 break;
1366 }
1367
1368 return;
1369 }
1370
edid_dolby_vsvdb(hdmi_sink_capability * cap,hdmi_edid_status * status,const hi_u8 * data,hi_u8 len)1371 static hi_u32 edid_dolby_vsvdb(hdmi_sink_capability *cap, hdmi_edid_status *status, const hi_u8 *data, hi_u8 len)
1372 {
1373 hdmi_edid_dolby_cap *dolby_cap = HI_NULL;
1374 hi_u32 dolby_ieeeoui;
1375
1376 if ((len != EDID_DOLBY_VSVDB_VERSION_0_LEN) && (len != EDID_DOLBY_VSVDB_VERSION_1_LEN)) {
1377 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
1378 edid_warn("dolby VSVDB len:%u\n", len);
1379 return HI_SUCCESS;
1380 }
1381
1382 dolby_cap = &cap->dolby_cap;
1383 hdmi_if_null_return(dolby_cap, HI_FAILURE);
1384
1385 dolby_ieeeoui = data[0] | (data[1] << 8) | (data[2] << 16); /* 8'b, bit[16:9]; 16'b, bit[24:17] */
1386 if (dolby_ieeeoui != DOLBY_IEEE_OUI) {
1387 return HI_FAILURE;
1388 }
1389
1390 dolby_cap->dolby_oui = dolby_ieeeoui;
1391 dolby_cap->yuv422_12_bit = (data[3] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1392 dolby_cap->b2160_p60 = (data[3] & BIT1_MASK) ? HI_TRUE : HI_FALSE;
1393 dolby_cap->vsvdb_version = (data[3] >> EDID_DOLBY_CAP_OFFSET_4);
1394 edid_dolby_version_parse(dolby_cap, data);
1395
1396 return HI_SUCCESS;
1397 }
1398
edid_hdr_meta_db(hdmi_sink_capability * cap,hi_u8 * data,hi_u8 len)1399 static hi_s32 edid_hdr_meta_db(hdmi_sink_capability *cap, hi_u8 *data, hi_u8 len)
1400 {
1401 hdmi_edid_hdr_cap *hdr_cap = HI_NULL;
1402
1403 hdr_cap = &cap->hdr_cap;
1404 hdmi_if_null_return(hdr_cap, HI_FAILURE);
1405
1406 /* BYTE 3 */
1407 hdr_cap->eotf.eotf_sdr = (data[0] & BIT0_MASK) ? HI_TRUE : HI_FALSE; /* ET_0 */
1408 hdr_cap->eotf.eotf_hdr = (data[0] & BIT1_MASK) ? HI_TRUE : HI_FALSE; /* ET_1 */
1409 hdr_cap->eotf.eotf_smpte_st2084 = (data[0] & BIT2_MASK) ? HI_TRUE : HI_FALSE; /* ET_2 */
1410 hdr_cap->eotf.eotf_hlg = (data[0] & BIT3_MASK) ? HI_TRUE : HI_FALSE; /* ET_3 */
1411 hdr_cap->eotf.eotf_future = HI_FALSE; /* ET_4 to ET_5 */
1412 /* BYTE 4 supported static metadata descriptor */
1413 hdr_cap->metadata.descriptor_type1 = (data[1] & BIT0_MASK) ? HI_TRUE : HI_FALSE;
1414 /* BYTE 5-7 */
1415 hdr_cap->max_luminance_cv = (len >= 4) ? (data[2]) : 0; /* 4, means the byte 5, max_luminance_cv */
1416 hdr_cap->min_luminance_cv = (len >= 5) ? (data[3]) : 0; /* 5, means the byte 6, min_luminance_cv */
1417 hdr_cap->average_lumin_cv = (len >= 6) ? (data[4]) : 0; /* 6, means the byte 7, average_lumin_cv */
1418
1419 return HI_SUCCESS;
1420 }
1421 #endif
1422
edid_video_cap_db(hdmi_sink_capability * cap,hi_u8 * data,hi_u8 len)1423 static hi_s32 edid_video_cap_db(hdmi_sink_capability *cap, hi_u8 *data, hi_u8 len)
1424 {
1425 if (len == 0) {
1426 return HI_FAILURE;
1427 }
1428
1429 cap->ycc_qrange_selectable = (data[0] & BIT7_MASK) ? HI_TRUE : HI_FALSE;
1430 cap->rgb_qrange_selectable = (data[0] & BIT6_MASK) ? HI_TRUE : HI_FALSE;
1431
1432 return HI_SUCCESS;
1433 }
1434
edid_ext_data_block_parse(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1435 static hi_s32 edid_ext_data_block_parse(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1436 {
1437 hi_s32 ret;
1438 hi_u8 ext_tag_code;
1439
1440 ext_tag_code = data[0];
1441 data++;
1442
1443 switch (ext_tag_code) {
1444 #ifdef HDMI_HDR_SUPPORT
1445 case EDID_DOLBY_VENDOR_SPECIFIC_VIDEO_DB:
1446 ret = edid_dolby_vsvdb(cap, status, data, len);
1447 hdmi_if_failure_return(ret, HI_FAILURE);
1448 break;
1449 #endif
1450 case EDID_COLORIMETRY_DB:
1451 ret = edid_colorimetry_db(cap, status, data, len);
1452 hdmi_if_failure_return(ret, HI_FAILURE);
1453 break;
1454 case EDID_Y420_VIDEO_DB:
1455 ret = edid_y420_video_db(cap, status, data, len);
1456 hdmi_if_failure_return(ret, HI_FAILURE);
1457 break;
1458 case EDID_Y420_CAPABILITY_MAP_DB:
1459 ret = edid_y420_cap_map_db(cap, data, len);
1460 hdmi_if_failure_return(ret, HI_FAILURE);
1461 break;
1462 #ifdef HDMI_HDR_SUPPORT
1463 case EDID_HDR_STATIC_METADATA_DB:
1464 ret = edid_hdr_meta_db(cap, data, len);
1465 hdmi_if_failure_return(ret, HI_FAILURE);
1466 break;
1467 #endif
1468 case EDID_VIDEO_CAPABILITY_DB:
1469 ret = edid_video_cap_db(cap, data, len);
1470 hdmi_if_failure_return(ret, HI_FAILURE);
1471 break;
1472 default:
1473 edid_warn("EXT-BLK un-parse ext data block!ext-tag code:%u!\n", ext_tag_code);
1474 break;
1475 }
1476
1477 return HI_SUCCESS;
1478 }
1479
edid_vendor_data_block_parse(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data,hi_u8 blk_len)1480 static hi_s32 edid_vendor_data_block_parse(hdmi_sink_capability *cap,
1481 hdmi_edid_status *status, hi_u8 *data, hi_u8 blk_len)
1482 {
1483 hi_s32 ret = HI_SUCCESS;
1484 hi_bool is_vsdb = HI_FALSE;
1485 hi_bool is_hfvsdb = HI_FALSE;
1486
1487 is_vsdb = ((blk_len >= EDID_VENDOR_BLOCK_LEN) && (data[0] == EDID_IEEE_VSDB_1ST) &&
1488 (data[1] == EDID_IEEE_VSDB_2ND) && (data[2] == EDID_IEEE_VSDB_3RD));
1489
1490 is_hfvsdb = ((blk_len >= EDID_VENDOR_BLOCK_LEN) && (data[0] == EDID_IEEE_HFVSDB_1ST) &&
1491 (data[1] == EDID_IEEE_HFVSDB_2ND) && (data[2] == EDID_IEEE_HFVSDB_3RD));
1492
1493 if (is_vsdb == HI_TRUE) {
1494 /* IEEE code indicate whether it is HDMI1.4b or HDMI2.0 */
1495 cap->support_hdmi = HI_TRUE;
1496 ret = edid_vsdb(cap, status, data, blk_len);
1497 hdmi_if_failure_return(ret, HI_FAILURE);
1498 } else if (is_hfvsdb == HI_TRUE) {
1499 ret = edid_hfvs_db(cap, status, data, blk_len);
1500 hdmi_if_failure_return(ret, HI_FAILURE);
1501 } else {
1502 if (blk_len >= EDID_VENDOR_BLOCK_LEN) {
1503 status->parse_warn |= 1 << EDID_PARSE_WARN_VSDB_INVALID;
1504 edid_warn("(HF)VSDB IEEE:0x%02x, 0x%02x, 0x%02x\n", data[0], data[1], data[2]);
1505 } else {
1506 status->parse_warn |= 1 << EDID_PARSE_WARN_BLOCKLEN_INVALID;
1507 edid_warn("(HF)VSDB blk_len:%u\n", blk_len);
1508 }
1509 }
1510
1511 return ret;
1512 }
1513
edid_db_parse(hdmi_sink_capability * cap,hi_u8 db_tag,hdmi_edid_status * status,hi_u8 * data,hi_u8 len)1514 static hi_s32 edid_db_parse(hdmi_sink_capability *cap, hi_u8 db_tag, hdmi_edid_status *status, hi_u8 *data, hi_u8 len)
1515 {
1516 hi_s32 ret = HI_SUCCESS;
1517
1518 switch (db_tag) {
1519 case EDID_AUDIO_DATA_BLOCK:
1520 ret = edid_audio_db(cap, status, data, len);
1521 break;
1522 case EDID_VIDEO_DATA_BLOCK:
1523 ret = edid_video_db(cap, status, data, len);
1524 break;
1525 case EDID_VENDOR_DATA_BLOCK:
1526 ret = edid_vendor_data_block_parse(cap, status, data, len);
1527 break;
1528 case EDID_SPEAKER_DATA_BLOCK:
1529 ret = edid_speaker_db(cap, status, data, len);
1530 break;
1531 case EDID_USE_EXT_DATA_BLOCK:
1532 /* ext tag code */
1533 ret = edid_ext_data_block_parse(cap, status, data, len);
1534 break;
1535 default:
1536 edid_warn("EXT_BLK resvered/un-parse block tag code!\n");
1537 break;
1538 }
1539
1540 return ret;
1541 }
1542
edid_extention_info_print(hi_u8 * data)1543 static hi_void edid_extention_info_print(hi_u8 *data)
1544 {
1545 edid_info(" %-20s : %02X\n", "CEA EDID timing extension tag", data[0]);
1546 edid_info(" %-20s : %02X\n", "CEA 861B version", data[1]);
1547 edid_info(" %-20s : %02u\n", "number of native DTD's", data[3] & 0x0F);
1548 edid_info(" %-20s : %s\n", "basic audio support", (data[3] & 0x40) ? "yes" : "no");
1549 edid_info(" %-20s : RGB444 %s %s\n", "pixel format",
1550 (data[3] & 0x20) ? "ycbcr444" : "", (data[3] & 0x10) ? "ycbcr422" : "");
1551
1552 hi_unused(data);
1553 return;
1554 }
1555
edid_ext_several_block_parse(hdmi_sink_capability * cap,hdmi_edid_status * status,hi_u8 * data)1556 static hi_void edid_ext_several_block_parse(hdmi_sink_capability *cap, hdmi_edid_status *status, hi_u8 *data)
1557 {
1558 hi_s32 ret;
1559 hi_u8 *tmp = HI_NULL;
1560 hi_u8 blk_offset = EDID_EXT_BLOCK_OFFSET;
1561 hi_u8 db_tag_code, blk_len;
1562 hi_u8 dtd_offset = data[2];
1563
1564 tmp = data + blk_offset;
1565
1566 /* several data block */
1567 for (blk_len = 0;
1568 (blk_offset < dtd_offset) && (tmp != HI_NULL);
1569 blk_offset += blk_len + 1) {
1570 tmp += blk_len;
1571 blk_len = (*tmp) & EDID_DB_LEN_MASK;
1572 db_tag_code = ((*tmp) & EDID_DB_TAG_CODE_MASK) >> 5; /* 5'b, bit[3:1] */
1573 tmp++;
1574 /* tag code */
1575 ret = edid_db_parse(cap, db_tag_code, status, tmp, blk_len);
1576 hdmi_if_failure_return_void(ret);
1577 }
1578 /* dt_ds */
1579 tmp += blk_len;
1580 while (((HDMI_EDID_BLOCK_SIZE - 1) - blk_offset) >= EDID_DTD_SIZE) {
1581 ret = edid_detail_timing(cap, status, tmp, EDID_DTD_SIZE);
1582 hdmi_if_failure_return_void(ret);
1583 blk_offset += EDID_DTD_SIZE;
1584 tmp += EDID_DTD_SIZE;
1585 }
1586
1587 return;
1588 }
1589
edid_extention_block_parse(hdmi_edid_info * edid_info,hi_u8 blk_num)1590 static hi_s32 edid_extention_block_parse(hdmi_edid_info *edid_info, hi_u8 blk_num)
1591 {
1592 hi_s32 ret;
1593 hi_u8 dtd_offset;
1594 hi_u8 *data = HI_NULL;
1595 hdmi_edid_status *status = HI_NULL;
1596 hdmi_sink_capability *cap = HI_NULL;
1597 hdmi_edid_color_space *clr_space = HI_NULL;
1598
1599 if (blk_num > (HDMI_EDID_TOTAL_BLOCKS - 1)) {
1600 edid_err("EXT-BLK = %u\n", blk_num);
1601 return HI_FAILURE;
1602 }
1603 status = &edid_info->status;
1604 data = edid_info->edid_raw + (blk_num * HDMI_EDID_BLOCK_SIZE);
1605 cap = &edid_info->capability;
1606
1607 ret = edid_block_check_sum(data, status);
1608 hdmi_if_failure_return(ret, HI_FAILURE);
1609 edid_info(" basic audio support_check for 861B (block %i)...\n", blk_num);
1610
1611 /* byte-0 :TAG */
1612 if (data[0] != EDID_CEA_EXTVERSION3_TAG) {
1613 status->parse_err = EDID_PARSE_ERR_TAG_UNKNOWN;
1614 edid_err("EXT_BLK CEA TAG:0x%02x\n", data[0]);
1615 }
1616
1617 /* byte-1: REVISION */
1618 if (data[1] != EDID_CEA_EXTVERSION3_REVISION) {
1619 status->parse_err = EDID_PARSE_ERR_CEA_REVERION;
1620 edid_err("EXT_BLK CEA861 REVISION: 0x%02x\n", data[1]);
1621 }
1622 /* byte-2: dt_ds offset */
1623 dtd_offset = data[2];
1624 if (dtd_offset < EDID_EXT_BLOCK_OFFSET) {
1625 edid_info("EXT_BLK NO dt_ds & reserved data blks :d=%u\n", dtd_offset);
1626 return HI_SUCCESS;
1627 }
1628
1629 edid_extention_info_print(data);
1630
1631 /* byte-3: basic audio, color space, dt_ds cnt */
1632 clr_space = &cap->color_space;
1633 clr_space->rgb444 = HI_TRUE;
1634 clr_space->ycbcr422 = ((data[3] & BIT4_MASK) ? HI_TRUE : HI_FALSE);
1635 clr_space->ycbcr444 = ((data[3] & BIT5_MASK) ? HI_TRUE : HI_FALSE);
1636
1637 edid_ext_several_block_parse(cap, status, data);
1638
1639 return HI_SUCCESS;
1640 }
1641
edid_raw_parse(hdmi_edid_info * edid_info)1642 static hi_s32 edid_raw_parse(hdmi_edid_info *edid_info)
1643 {
1644 hi_u8 blk_num;
1645 hi_s32 ret;
1646 hdmi_edid_status *status = HI_NULL;
1647 hi_u8 *data = HI_NULL;
1648 hdmi_sink_capability *cap = HI_NULL;
1649
1650 status = &edid_info->status;
1651 data = edid_info->edid_raw;
1652 cap = &edid_info->capability;
1653 hdmi_if_null_return(status, HI_FAILURE);
1654 hdmi_if_null_return(data, HI_FAILURE);
1655
1656 ret = edid_first_blk_parse(edid_info);
1657 hdmi_if_failure_return(ret, HI_FAILURE);
1658 for (blk_num = 1; blk_num <= cap->ext_block_num; blk_num++) {
1659 ret = edid_extention_block_parse(edid_info, blk_num);
1660 hdmi_if_failure_return(ret, HI_FAILURE);
1661 }
1662
1663 return HI_SUCCESS;
1664 }
1665
drv_hdmi_edid_reset(hdmi_edid_info * edid_info)1666 hi_s32 drv_hdmi_edid_reset(hdmi_edid_info *edid_info)
1667 {
1668 hi_u8 *data = HI_NULL;
1669 hdmi_edid_status *status = HI_NULL;
1670 hdmi_sink_capability *cap = HI_NULL;
1671
1672 hdmi_if_null_return(edid_info, HI_FAILURE);
1673 status = &edid_info->status;
1674 cap = &edid_info->capability;
1675 data = edid_info->edid_raw;
1676 hdmi_if_null_return(data, HI_FAILURE);
1677
1678 (hi_void)memset_s(cap, sizeof(edid_info->capability), 0, sizeof(hdmi_sink_capability));
1679 (hi_void)memset_s(data, sizeof(edid_info->edid_raw), 0, sizeof(edid_info->edid_raw));
1680
1681 status->cap_sink = HI_FALSE;
1682 status->cap_valid = HI_FALSE;
1683 status->raw_valid = HI_FALSE;
1684 status->raw_len = 0;
1685 status->parse_err = EDID_PARSE_ERR_NONE;
1686 status->parse_warn = EDID_PARSE_WARN_NONE;
1687
1688 return HI_SUCCESS;
1689 }
1690
drv_hdmi_edid_update(hdmi_edid_info * edid_info,hdmi_edid_updata_mode mode)1691 hi_s32 drv_hdmi_edid_update(hdmi_edid_info *edid_info, hdmi_edid_updata_mode mode)
1692 {
1693 hi_s32 ret = HI_SUCCESS;
1694 hi_u8 *data = HI_NULL;
1695 hdmi_edid_status *status = HI_NULL;
1696 hdmi_sink_capability *cap = HI_NULL;
1697 hdmi_device *hdmi_dev = HI_NULL;
1698 hi_bool hotplug = HI_FALSE;
1699
1700 hdmi_if_null_return(edid_info, HI_FAILURE);
1701 status = &edid_info->status;
1702 cap = &edid_info->capability;
1703 data = edid_info->edid_raw;
1704 hdmi_if_null_return(data, HI_FAILURE);
1705
1706 (hi_void)memset_s(cap, sizeof(edid_info->capability), 0, sizeof(hdmi_sink_capability));
1707 (hi_void)memset_s(data, HDMI_EDID_TOTAL_SIZE, 0, sizeof(edid_info->edid_raw));
1708
1709 status->cap_sink = HI_FALSE;
1710 status->cap_valid = HI_FALSE;
1711 status->raw_valid = HI_FALSE;
1712 status->raw_len = 0;
1713 status->parse_err = EDID_PARSE_ERR_NONE;
1714 status->parse_warn = EDID_PARSE_WARN_NONE;
1715
1716 if (mode == HDMI_EDID_UPDATE_SINK) {
1717 hdmi_dev = osal_container_of(edid_info, __typeof__(*hdmi_dev), edid_info);
1718 hal_call_void(hal_hdmi_hot_plug_status_get, hdmi_dev->hal, &hotplug);
1719 if (hotplug) {
1720 hal_call_ret(ret, hal_hdmi_edid_raw_data_read, hdmi_dev->hal, HDMI_EDID_TOTAL_SIZE, data);
1721 status->cap_sink = HI_TRUE;
1722 } else {
1723 status->cap_sink = HI_FALSE;
1724 edid_warn("sink do not connect, forbid to read edid\n");
1725 return HI_ERR_HDMI_DEV_NOT_CONNECT;
1726 }
1727 }
1728
1729 if ((ret == 0) || (ret % HDMI_EDID_BLOCK_SIZE)) {
1730 status->raw_update_err_cnt++;
1731 edid_err("\n_read EDID raw data fail(0x%x)!\n", ret);
1732 return HI_ERR_HDMI_READ_EDID_FAILED;
1733 }
1734
1735 status->raw_len = (hi_u32)ret;
1736 status->raw_valid = HI_TRUE;
1737
1738 ret = edid_raw_parse(edid_info);
1739 if (ret != HI_SUCCESS) {
1740 edid_err("\n_edid raw parse fail(0x%x)!\n", ret);
1741 return HI_ERR_HDMI_READ_EDID_FAILED;
1742 }
1743 status->cap_valid = HI_TRUE;
1744
1745 return HI_SUCCESS;
1746 }
1747
drv_hdmi_edid_capability_get(hdmi_edid_info * edid_info,hdmi_sink_capability ** cap_dest)1748 hdmi_edid_data drv_hdmi_edid_capability_get(hdmi_edid_info *edid_info, hdmi_sink_capability **cap_dest)
1749 {
1750 hdmi_edid_status *status = HI_NULL;
1751 hdmi_edid_data edid_status;
1752
1753 hdmi_if_null_return(cap_dest, HI_FAILURE);
1754 hdmi_if_null_return(edid_info, HI_FAILURE);
1755
1756 status = &edid_info->status;
1757 *cap_dest = &edid_info->capability;
1758
1759 if (status->cap_valid) {
1760 edid_status = (status->cap_sink) ? HDMI_EDID_DATA_VALIDSINK : HDMI_EDID_DATA_VALIDTEST;
1761 } else {
1762 status->cap_get_err_cnt++;
1763 edid_status = HDMI_EDID_DATA_INVALID;
1764 }
1765
1766 return edid_status;
1767 }
1768
drv_hdmi_edid_raw_get(hdmi_edid_info * edid_info,hi_u8 * raw_data_dest,hi_u32 len)1769 hi_s32 drv_hdmi_edid_raw_get(hdmi_edid_info *edid_info, hi_u8 *raw_data_dest, hi_u32 len)
1770 {
1771 errno_t ret;
1772 hdmi_edid_status *status = HI_NULL;
1773 hi_u8 *data_src = HI_NULL;
1774 hi_u32 tmp_len;
1775
1776 hdmi_if_null_return(raw_data_dest, HI_FAILURE);
1777 hdmi_if_null_return(edid_info, HI_FAILURE);
1778
1779 status = &edid_info->status;
1780 data_src = edid_info->edid_raw;
1781 hdmi_if_null_return(data_src, HI_FAILURE);
1782
1783 if ((len > HDMI_EDID_TOTAL_SIZE) || (status->raw_valid == HI_FALSE)) {
1784 status->raw_get_err_cnt++;
1785 return HI_FAILURE;
1786 }
1787
1788 tmp_len = (len <= status->raw_len) ? len : status->raw_len;
1789
1790 ret = memcpy_s(raw_data_dest, len, data_src, tmp_len);
1791 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
1792
1793 return (hi_s32)tmp_len;
1794 }
1795
dfrv_hdmi_edid_status_get(hdmi_edid_info * edid_info,hdmi_edid_status * status)1796 hi_s32 dfrv_hdmi_edid_status_get(hdmi_edid_info *edid_info, hdmi_edid_status *status)
1797 {
1798 errno_t ret;
1799
1800 hdmi_if_null_return(edid_info, HI_FAILURE);
1801 hdmi_if_null_return(status, HI_FAILURE);
1802
1803 ret = memcpy_s(status, sizeof(*status), &edid_info->status, sizeof(hdmi_edid_status));
1804 hdmi_unequal_eok_return(ret, HI_ERR_HDMI_INVALID_PARA);
1805
1806 return HI_SUCCESS;
1807 }
1808
1809