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 "hdmi_hal_ddc.h"
19 #include "hdmi_osal.h"
20 #include "hdmi_reg_aon.h"
21 #include "hdmi_reg_ctrl.h"
22 #include "hdmi_hal_intf.h"
23 #include "hdmi_hal_ctrl.h"
24 #include "hdmi_product_define.h"
25
26 #define DDC_EDID_SALVE_ADDR 0xa0
27 #define DDC_HDCP_SALVE_ADDR 0x74
28 #define DDC_SCDC_SALVE_ADDR 0xa8
29 #define DDC_MAX_FIFO_SIZE 16
30 #define DDC_EXT_BLOCK_OFFSET 0x7e
31 #define DDC_MAX_EDID_EXT_NUM 3 /* 3: 4(max block num) - 1(base block) */
32 #define DDC_DEFAULT_DELAY 8 /* 8us */
33
34 static ddc_info g_ddc_info[HDMI_DEVICE_ID_BUTT];
35
36 typedef enum {
37 DDC_CMD_READ_SINGLE_NO_ACK,
38 DDC_CMD_READ_SINGLE_ACK,
39 DDC_CMD_READ_MUTI_NO_ACK,
40 DDC_CMD_READ_MUTI_ACK,
41 DDC_CMD_READ_SEGMENT_NO_ACK,
42 DDC_CMD_READ_SEGMENT_ACK,
43 DDC_CMD_WRITE_MUTI_NO_ACK,
44 DDC_CMD_WRITE_MUTI_ACK,
45 DDC_CMD_FIFO_CLR = 0x09,
46 DDC_CMD_SCL_DRV,
47 DDC_CMD_MASTER_ABORT = 0x0f
48 } ddc_issue_cmd;
49
ddc_info_ptr_get(hdmi_device_id hdmi)50 static ddc_info *ddc_info_ptr_get(hdmi_device_id hdmi)
51 {
52 if (hdmi < HDMI_DEVICE_ID_BUTT) {
53 return &g_ddc_info[hdmi];
54 }
55 return HI_NULL;
56 }
57
ddc_access_enable_wait(hi_u32 timeout)58 static hi_s32 ddc_access_enable_wait(hi_u32 timeout)
59 {
60 hi_s32 ret = HI_SUCCESS;
61 hi_u32 tmp_time = 0;
62
63 hdmi_reg_cpu_ddc_req_set(HI_TRUE);
64
65 while (!hdmi_reg_cpu_ddc_req_ack_get()) {
66 osal_msleep(1);
67 tmp_time++;
68 if (tmp_time > timeout) {
69 ret = HI_FAILURE;
70 break;
71 }
72 }
73 return ret;
74 }
75
ddc_access_disable_wait(hi_u32 timeout)76 static hi_s32 ddc_access_disable_wait(hi_u32 timeout)
77 {
78 hi_s32 ret = HI_SUCCESS;
79 hi_u32 tmp_time = 0;
80
81 hdmi_reg_cpu_ddc_req_set(HI_FALSE);
82
83 while (hdmi_reg_cpu_ddc_req_ack_get()) {
84 osal_msleep(1);
85 tmp_time += 1;
86 if (tmp_time > timeout) {
87 ret = HI_FAILURE;
88 break;
89 }
90 }
91 return ret;
92 }
93
ddc_scl_wait(hi_u32 timeout)94 static hi_s32 ddc_scl_wait(hi_u32 timeout)
95 {
96 hi_s32 ret = HI_SUCCESS;
97 hi_u32 tmp_time = 0;
98
99 while (!hdmi_reg_ddc_scl_st_get()) {
100 osal_msleep(1);
101 tmp_time += 1;
102 if (tmp_time > timeout) {
103 ret = HI_FAILURE;
104 break;
105 }
106 }
107 return ret;
108 }
109
ddc_sda_wait(hi_u32 timeout)110 static hi_s32 ddc_sda_wait(hi_u32 timeout)
111 {
112 hi_u32 tmp_timeout = 0;
113 hi_s32 ret = HI_SUCCESS;
114
115 if (!hdmi_reg_ddc_sda_st_get()) {
116 hdmi_reg_dcc_man_en_set(HI_TRUE);
117 while ((!hdmi_reg_ddc_sda_st_get()) && tmp_timeout++ < timeout) {
118 /* pull scl high */
119 hdmi_reg_ddc_scl_oen_set(HI_TRUE);
120 osal_udelay(DDC_DEFAULT_DELAY);
121 /* pull scl low */
122 hdmi_reg_ddc_scl_oen_set(HI_FALSE);
123 osal_udelay(DDC_DEFAULT_DELAY);
124 }
125
126 /* STOP contition */
127 if (tmp_timeout < timeout && (hdmi_reg_ddc_sda_st_get())) {
128 /* pull sda low */
129 hdmi_reg_ddc_sda_oen_set(HI_FALSE);
130 osal_udelay(DDC_DEFAULT_DELAY);
131 /* pull scl high */
132 hdmi_reg_ddc_scl_oen_set(HI_TRUE);
133 osal_udelay(DDC_DEFAULT_DELAY);
134 /* pull sda high */
135 hdmi_reg_ddc_sda_oen_set(HI_TRUE);
136 osal_udelay(DDC_DEFAULT_DELAY);
137 hdmi_info("deadlock clear success\n");
138 ret = HI_SUCCESS;
139 } else {
140 hdmi_warn("deadlock clear fail\n");
141 ret = HI_FAILURE;
142 }
143 hdmi_reg_dcc_man_en_set(HI_FALSE);
144 }
145
146 return ret;
147 }
148
ddc_in_prog_wait(hi_u32 timeout)149 static hi_s32 ddc_in_prog_wait(hi_u32 timeout)
150 {
151 hi_s32 ret = HI_SUCCESS;
152 hi_u32 tmp_time = 0;
153
154 while (hdmi_reg_pwd_i2c_in_prog_get()) {
155 osal_msleep(1);
156 tmp_time += 1;
157 if (tmp_time > timeout) {
158 ret = HI_FAILURE;
159 break;
160 }
161 }
162
163 return ret;
164 }
165
ddc_cmd_issue(const ddc_cfg * cfg)166 static hi_s32 ddc_cmd_issue(const ddc_cfg *cfg)
167 {
168 hi_u32 slave_addr = 0;
169 hi_u32 segment, offset, data_size;
170
171 segment = cfg->segment;
172 offset = cfg->offset;
173 data_size = cfg->data_size;
174
175 switch (cfg->func_type) {
176 case DDC_FUNC_TYPE_EDID:
177 slave_addr = DDC_EDID_SALVE_ADDR;
178 break;
179 case DDC_FUNC_TYPE_HDCP:
180 slave_addr = DDC_HDCP_SALVE_ADDR;
181 break;
182 case DDC_FUNC_TYPE_SCDC:
183 slave_addr = DDC_SCDC_SALVE_ADDR;
184 break;
185 default:
186 hdmi_warn("un-known DDC function type, wrong slaveaddr!\n");
187 break;
188 }
189
190 if (cfg->master_mode == DDC_MASTER_MODE_PWD) {
191 hdmi_reg_pwd_mst_cmd_set(DDC_CMD_FIFO_CLR);
192 hdmi_reg_pwd_slave_addr_set(slave_addr);
193 hdmi_reg_pwd_slave_seg_set(segment);
194 hdmi_reg_pwd_slave_offset_set(offset);
195 hdmi_reg_pwd_data_out_cnt_set(data_size);
196 osal_udelay(DDC_DEFAULT_DELAY);
197 hdmi_reg_pwd_mst_cmd_set(cfg->issue_mode);
198 } else {
199 hdmi_err("unknown master_mode=%u\n", cfg->master_mode);
200 }
201
202 return HI_SUCCESS;
203 }
204
ddc_read(ddc_cfg * cfg)205 static hi_s32 ddc_read(ddc_cfg *cfg)
206 {
207 hi_u32 len;
208 ddc_func_type type;
209 hi_u8 *data = HI_NULL;
210 hi_u32 i, retry, data_size;
211 hi_u32 time_start, time_curr;
212
213 data = cfg->data;
214 type = cfg->func_type;
215 len = cfg->data_size;
216 retry = cfg->issue_timeout < DDC_DEFAULT_TIMEOUT_ISSUE ? DDC_DEFAULT_TIMEOUT_ISSUE : cfg->sda_timeout;
217
218 for (data_size = 0; data_size < len; data_size++, data++) {
219 /* maybe msleep(1) cost 20ms, 30 times, total 600ms. */
220 time_start = hdmi_osal_get_time_in_ms();
221 time_curr = time_start;
222 /* when read-fifo empty, every byte wait a max timeout */
223 for (i = 0;
224 ((i < retry) && (hdmi_reg_pwd_fifo_empty_get() || (hdmi_reg_pwd_fifo_data_out_get() == 0))) &&
225 ((time_curr - time_start) <= DDC_DEFAULT_RETRY_TIMEOUT_ISSUE);
226 i++) {
227 /* wait ddc status update after DDC cmd set. */
228 osal_msleep(1);
229 if (hdmi_reg_ddc_i2c_no_ack_get() || hdmi_reg_ddc_i2c_bus_low_get()) {
230 hdmi_reg_pwd_mst_cmd_set(DDC_CMD_MASTER_ABORT);
231 hdmi_warn("DDC status error!\n");
232 return HI_FAILURE;
233 }
234 time_curr = hdmi_osal_get_time_in_ms();
235 }
236 if ((i >= retry) || ((time_curr - time_start) > DDC_DEFAULT_RETRY_TIMEOUT_ISSUE)) {
237 if (type != DDC_FUNC_TYPE_SCDC) {
238 hdmi_warn("read fifo retry=%u ms, size=%u, timeout:%u!\n",
239 retry, len, (time_curr - time_start));
240 } else {
241 hdmi_info("read fifo retry=%u ms, size=%u, timeout:%u!\n",
242 retry, len, (time_curr - time_start));
243 }
244 return HI_FAILURE;
245 }
246 if (data != HI_NULL) {
247 *data = hdmi_reg_rdata_pwd_fifo_data_out_get();
248 /*
249 * the fifo status is not refresh promptly,
250 * so re-read the fifo status and delay 1us if the fifo is empty,
251 * wait the data ready. it must delay 1us after read fifo data.
252 */
253 osal_udelay(1);
254 } else {
255 hdmi_err("edid &data[%u]=null\n", data_size);
256 return HI_FAILURE;
257 }
258 }
259
260 return data_size;
261 }
262
ddc_write(ddc_cfg * cfg)263 static hi_s32 ddc_write(ddc_cfg *cfg)
264 {
265 hi_u32 len;
266 ddc_func_type type;
267 hi_u8 *data = HI_NULL;
268 hi_u32 i, retry, data_size;
269 hi_u32 time_start, time_curr;
270
271 data = cfg->data;
272 type = cfg->func_type;
273 len = cfg->data_size;
274 retry = cfg->issue_timeout < DDC_DEFAULT_TIMEOUT_ISSUE ? DDC_DEFAULT_TIMEOUT_ISSUE : cfg->sda_timeout;
275
276 for (data_size = 0; data_size < len; data_size++, data++) {
277 /* maybe msleep(1) cost 20ms, every byte wait a max timeout 60ms. */
278 time_start = hdmi_osal_get_time_in_ms();
279 time_curr = time_start;
280 /* when write-fifo full, every byte wait a max timeout and retry times */
281 for (i = 0;
282 (((i < retry) && (hdmi_reg_pwd_fifo_data_out_get() >= DDC_MAX_FIFO_SIZE)) &&
283 ((time_curr - time_start) <= DDC_DEFAULT_RETRY_TIMEOUT_ISSUE));
284 i++) {
285 /* wait ddc status update after DDC cmd set. */
286 osal_msleep(1);
287 if (hdmi_reg_ddc_i2c_no_ack_get() || hdmi_reg_ddc_i2c_bus_low_get()) {
288 hdmi_reg_pwd_mst_cmd_set(DDC_CMD_MASTER_ABORT);
289 hdmi_warn("DDC status error!\n");
290 return HI_FAILURE;
291 }
292 time_curr = hdmi_osal_get_time_in_ms();
293 }
294 if (i >= retry || ((time_curr - time_start) > DDC_DEFAULT_RETRY_TIMEOUT_ISSUE)) {
295 if (type != DDC_FUNC_TYPE_SCDC) {
296 hdmi_err("write fifo retry=%u ms, size=%u, timeout:%u!\n",
297 retry, len, (time_curr - time_start));
298 } else {
299 hdmi_info("write fifo retry=%u ms, size=%u, timeout:%u!\n",
300 retry, len, (time_curr - time_start));
301 }
302 return HI_FAILURE;
303 }
304
305 if (data != HI_NULL) {
306 hdmi_reg_pwd_fifo_data_in_set(*data);
307 osal_udelay(1);
308 } else {
309 hdmi_err("edid &data[%u]=null\n", data_size);
310 return HI_FAILURE;
311 }
312 }
313
314 return data_size;
315 }
316
ddc_data_pwd_issue(ddc_cfg * cfg,hi_bool read_issue)317 static hi_s32 ddc_data_pwd_issue(ddc_cfg *cfg, hi_bool read_issue)
318 {
319 hi_s32 data_size;
320
321 if (read_issue) {
322 /* read issue */
323 data_size = ddc_read(cfg);
324 } else {
325 /* write issue */
326 data_size = ddc_write(cfg);
327 }
328
329 return data_size;
330 }
331
ddc_data_issue(ddc_cfg * cfg,hi_bool read_issue)332 static hi_s32 ddc_data_issue(ddc_cfg *cfg, hi_bool read_issue)
333 {
334 if (cfg->master_mode == DDC_MASTER_MODE_PWD) {
335 return ddc_data_pwd_issue(cfg, read_issue);
336 } else {
337 hdmi_err("unknown master_mode=%u,fail!\n", cfg->master_mode);
338 return HI_FAILURE;
339 }
340 }
341
ddc_err_clean_check(hdmi_device_id hdmi)342 static hi_s32 ddc_err_clean_check(hdmi_device_id hdmi)
343 {
344 hi_s32 ret = HI_SUCCESS;
345 ddc_info *tmp = ddc_info_ptr_get(hdmi);
346
347 hdmi_if_null_warn_return(tmp, HI_FAILURE);
348 hdmi_if_false_warn_return(tmp->run.init, HI_FAILURE);
349
350 /* in prog check */
351 if (ddc_in_prog_wait(DDC_DEFAULT_TIMEOUT_IN_PROG) != HI_SUCCESS) {
352 hdmi_warn("error clr, wait in prog timeout!\n");
353 ret = HI_FAILURE;
354 }
355 /* scl check */
356 if (ddc_scl_wait(DDC_DEFAULT_TIMEOUT_SCL) != HI_SUCCESS) {
357 hdmi_warn("error clr, wait scl timeout!\n");
358 ret = HI_FAILURE;
359 }
360 /* sda check */
361 if (ddc_sda_wait(DDC_DEFAULT_TIMEOUT_SDA) != HI_SUCCESS) {
362 hdmi_warn("error clr, wait sda timeout!\n");
363 ret = HI_FAILURE;
364 }
365 if (ret == HI_SUCCESS) {
366 hdmi_info("error clr success!\n");
367 }
368
369 return ret;
370 }
371
ddc_reset(hdmi_device_id hdmi)372 static hi_s32 ddc_reset(hdmi_device_id hdmi)
373 {
374 hi_u32 i;
375 ddc_record_elem *tmp_elem = HI_NULL;
376 ddc_info *tmp = ddc_info_ptr_get(hdmi);
377
378 hdmi_if_null_warn_return(tmp, HI_FAILURE);
379 hdmi_if_false_warn_return(tmp->run.init, HI_FAILURE);
380
381 for (i = 0; i < DDC_MAX_RECORD_NUM; i++) {
382 tmp_elem = &tmp->ddc_record[i];
383 if (tmp_elem->data != HI_NULL) {
384 osal_vfree(tmp_elem->data);
385 }
386 (hi_void)memset_s(tmp_elem, sizeof(tmp->ddc_record[i]), 0, sizeof(ddc_record_elem));
387 }
388
389 tmp->run.elem_ptr = 0;
390 tmp->run.total_num = 0;
391
392 return ddc_err_clean_check(hdmi);
393 }
394
ddc_issue(ddc_cfg * cfg,ddc_record_elem * tmp_elem)395 static hi_s32 ddc_issue(ddc_cfg *cfg, ddc_record_elem *tmp_elem)
396 {
397 hi_s32 ret = HI_SUCCESS;
398 hi_bool read_issue = HI_FALSE;
399
400 /* access check */
401 if (cfg->master_mode == DDC_MASTER_MODE_PWD) {
402 if (ddc_access_enable_wait(cfg->access_timeout) != HI_SUCCESS) {
403 hdmi_err("wait access bus timeout!\n");
404 tmp_elem->un_err.u32.access_wait_timeout = HI_TRUE;
405 return ret;
406 }
407 }
408 /* scl check */
409 if (ddc_scl_wait(cfg->scl_timeout) != HI_SUCCESS) {
410 hdmi_err("wait scl timeout!\n");
411 tmp_elem->un_err.u32.bus_low_scl = HI_TRUE;
412 return ret;
413 }
414 /* sda check */
415 if (ddc_sda_wait(cfg->sda_timeout) != HI_SUCCESS) {
416 hdmi_err("wait sda timeout!\n");
417 tmp_elem->un_err.u32.bus_low_sda = HI_TRUE;
418 return ret;
419 }
420 /* jude read/write issue */
421 if (cfg->issue_mode <= DDC_MODE_READ_SEGMENT_ACK) {
422 read_issue = HI_TRUE;
423 } else if (cfg->issue_mode < DDC_MODE_BUTT) {
424 read_issue = HI_FALSE;
425 } else {
426 hdmi_err("un-known ddc issue mode!\n");
427 tmp_elem->un_err.u32.err_isseu_mode = HI_TRUE;
428 return ret;
429 }
430 /* issue command */
431 if (ddc_cmd_issue(cfg) != HI_SUCCESS) {
432 hdmi_err("command issue fail!\n");
433 return ret;
434 }
435 /* issue data */
436 ret = ddc_data_issue(cfg, read_issue);
437 if (ret <= 0) {
438 hdmi_info("data issue fail!\n");
439 tmp_elem->un_err.u32.issue_timeout = HI_TRUE;
440 return ret;
441 }
442
443 return ret;
444 }
445
hal_hdmi_ddc_init(hdmi_device_id hdmi)446 hi_s32 hal_hdmi_ddc_init(hdmi_device_id hdmi)
447 {
448 ddc_info *tmp = ddc_info_ptr_get(hdmi);
449
450 hdmi_if_null_warn_return(tmp, HI_FAILURE);
451
452 if (!tmp->run.init) {
453 osal_sema_init(&tmp->ddc_wr_mutex, 1);
454 (hi_void)memset_s(tmp->ddc_record, sizeof(tmp->ddc_record), 0, sizeof(tmp->ddc_record));
455 tmp->run.init = HI_TRUE;
456 tmp->run.elem_ptr = 0;
457 tmp->run.total_num = 0;
458 }
459
460 return HI_SUCCESS;
461 }
462
hal_hdmi_ddc_deinit(hdmi_device_id hdmi)463 hi_s32 hal_hdmi_ddc_deinit(hdmi_device_id hdmi)
464 {
465 ddc_info *tmp = ddc_info_ptr_get(hdmi);
466
467 hdmi_if_null_warn_return(tmp, HI_FAILURE);
468 hdmi_if_false_warn_return(tmp->run.init, HI_FAILURE);
469
470 ddc_reset(hdmi);
471 osal_sema_destroy(&tmp->ddc_wr_mutex);
472 tmp->run.init = HI_FALSE;
473
474 return HI_SUCCESS;
475 }
476
hal_hdmi_ddc_issue(hdmi_device_id hdmi,ddc_cfg * cfg)477 hi_s32 hal_hdmi_ddc_issue(hdmi_device_id hdmi, ddc_cfg *cfg)
478 {
479 errno_t errnumber;
480 hi_s32 ret;
481 ddc_record_elem *tmp_elem = HI_NULL;
482 ddc_info *tmp = ddc_info_ptr_get(hdmi);
483
484 hdmi_if_null_warn_return(cfg, HI_FAILURE);
485 hdmi_if_null_warn_return(tmp, HI_FAILURE);
486 hdmi_if_false_warn_return(tmp->run.init, HI_FAILURE);
487
488 tmp->run.elem_ptr = (1 + tmp->run.elem_ptr) % DDC_MAX_RECORD_NUM;
489 if (tmp->run.total_num <= DDC_MAX_RECORD_NUM) {
490 tmp->run.total_num++;
491 }
492 tmp_elem = &tmp->ddc_record[tmp->run.elem_ptr];
493 (hi_void)memset_s(tmp_elem, sizeof(tmp->ddc_record[tmp->run.elem_ptr]), 0, sizeof(ddc_record_elem));
494 errnumber = memcpy_s(&tmp_elem->cfg, sizeof(tmp_elem->cfg), cfg, sizeof(ddc_cfg));
495 hdmi_unequal_eok_return(errnumber, HI_ERR_HDMI_INVALID_PARA);
496 tmp_elem->start_time = hal_hdmi_mach_ms_get();
497
498 hdmi_mutex_lock(tmp->ddc_wr_mutex);
499 ret = ddc_issue(cfg, tmp_elem);
500 /* in prog check */
501 if (ddc_in_prog_wait(cfg->in_prog_timeout) != HI_SUCCESS) {
502 hdmi_warn("wait in prog timeout!\n");
503 tmp_elem->un_err.u32.in_prog_timeout = HI_TRUE;
504 }
505 if (tmp_elem->un_err.word) {
506 hdmi_hpd_rsen hpd = {0};
507 hal_hdmi_ctrl_hpd_rsen_get(hdmi, &hpd);
508 if (!hpd.hpd_on) {
509 hdmi_warn("hpd no exist!\n");
510 tmp_elem->un_err.u32.hpd_no_exist = HI_TRUE;
511 } else if (ddc_err_clean_check(hdmi) != HI_SUCCESS) {
512 hdmi_warn("error clear fail!\n");
513 tmp_elem->un_err.u32.clr_err_fail = 1;
514 }
515 }
516 if (cfg->master_mode == DDC_MASTER_MODE_PWD) {
517 if (ddc_access_disable_wait(cfg->access_timeout) != HI_SUCCESS) {
518 hdmi_warn("wait access disable timeout!\n");
519 }
520 }
521 tmp_elem->time_len = hal_hdmi_mach_ms_get() - tmp_elem->start_time;
522 hdmi_mutex_unlock(tmp->ddc_wr_mutex);
523
524 return ret;
525 }
526
hal_hdmi_ddc_default_cfg_get(hdmi_device_id hdmi,ddc_cfg * cfg)527 hi_void hal_hdmi_ddc_default_cfg_get(hdmi_device_id hdmi, ddc_cfg *cfg)
528 {
529 ddc_info *tmp = ddc_info_ptr_get(hdmi);
530
531 hdmi_if_null_warn_return_void(tmp);
532 hdmi_if_null_warn_return_void(cfg);
533 hdmi_if_false_warn_return_void(tmp->run.init);
534
535 cfg->segment = 0;
536 cfg->offset = 0;
537 cfg->func_type = DDC_FUNC_TYPE_EDID;
538 cfg->issue_mode = DDC_MODE_READ_MUTIL_NO_ACK;
539 cfg->speed = 0;
540 cfg->master_mode = DDC_MASTER_MODE_PWD;
541 cfg->access_timeout = DDC_DEFAULT_TIMEOUT_ACCESS;
542 cfg->hpd_timeout = DDC_DEFAULT_TIMEOUT_HPD;
543 cfg->in_prog_timeout = DDC_DEFAULT_TIMEOUT_IN_PROG;
544 cfg->scl_timeout = DDC_DEFAULT_TIMEOUT_SCL;
545 cfg->sda_timeout = DDC_DEFAULT_TIMEOUT_SDA;
546 cfg->issue_timeout = DDC_DEFAULT_TIMEOUT_ISSUE;
547 cfg->data_size = 0;
548 cfg->data = HI_NULL;
549
550 return;
551 }
552
edid_get_extern_blk(hdmi_device_id hdmi,const hi_u8 ext_blk_num,const hi_s32 raw_len,ddc_cfg * cfg)553 static hi_s32 edid_get_extern_blk(hdmi_device_id hdmi, const hi_u8 ext_blk_num, const hi_s32 raw_len, ddc_cfg *cfg)
554 {
555 hi_s32 ret = raw_len;
556
557 cfg->data += cfg->data_size;
558 cfg->offset = 0;
559 cfg->issue_mode = DDC_MODE_READ_SEGMENT_NO_ACK;
560 cfg->segment = 1;
561 cfg->data_size = HDMI_EDID_BLOCK_SIZE * ext_blk_num;
562 ret += hal_hdmi_ddc_issue(hdmi, cfg);
563 if (ret > 0) {
564 hdmi_info("EDID read EXT-block 2~%u success!\n", ext_blk_num + 1);
565 } else {
566 hdmi_warn("EDID read EXT-block 2~%u fail!\n", ext_blk_num + 1);
567 }
568
569 return ret;
570 }
571
hal_hdmi_ddc_edid_raw_get(hdmi_device_id hdmi,hi_s32 size,hi_u8 * data)572 hi_s32 hal_hdmi_ddc_edid_raw_get(hdmi_device_id hdmi, hi_s32 size, hi_u8 *data)
573 {
574 hi_u8 ext_block_num, des_block_num;
575 hi_s32 ret;
576 ddc_cfg cfg = {0};
577
578 hdmi_if_null_warn_return(data, HI_FAILURE);
579
580 hal_hdmi_ddc_default_cfg_get(hdmi, &cfg);
581 cfg.segment = 0;
582 cfg.func_type = DDC_FUNC_TYPE_EDID;
583 cfg.issue_mode = DDC_MODE_READ_MUTIL_NO_ACK;
584 cfg.data_size = HDMI_EDID_BLOCK_SIZE;
585 cfg.data = &data[0];
586 ret = hal_hdmi_ddc_issue(hdmi, &cfg);
587 /* block 0 */
588 if (ret <= 0) {
589 hdmi_warn("edid block 0 read fail!\n");
590 return ret;
591 }
592 hdmi_info("EDID block 0 read success!\n");
593
594 ext_block_num = data[DDC_EXT_BLOCK_OFFSET];
595 if (ext_block_num > DDC_MAX_EDID_EXT_NUM) {
596 hdmi_warn("sink edid blocks num=%u, but we only support %u\n", ext_block_num, DDC_MAX_EDID_EXT_NUM);
597 ext_block_num = DDC_MAX_EDID_EXT_NUM;
598 }
599
600 des_block_num = (size / HDMI_EDID_BLOCK_SIZE) - 1;
601 if (ext_block_num > des_block_num) {
602 hdmi_warn("scr block num > des block num, adapt ext_block_num to %u\n", des_block_num);
603 ext_block_num = des_block_num;
604 }
605 if (ext_block_num == 0) {
606 hdmi_warn("edid block 0 read fail!\n");
607 return ret;
608 }
609 /* block 1 */
610 cfg.data += cfg.data_size;
611 cfg.offset = HDMI_EDID_BLOCK_SIZE;
612 ret += hal_hdmi_ddc_issue(hdmi, &cfg);
613 if (ret > 0) {
614 hdmi_info("EDID EXT-block 1 read success!\n");
615 ext_block_num--;
616 if (ext_block_num) {
617 /* block 2&3 */
618 ret = edid_get_extern_blk(hdmi, ext_block_num, ret, &cfg);
619 }
620 } else {
621 hdmi_warn("EDID EXT-block 1 read fail!\n");
622 }
623
624 return ret;
625 }
626
627