• 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_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