blob: fde6debdfc29ad5ab9c2022d143b82ca88116690 [file] [log] [blame]
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <env.h>
9#include <malloc.h>
10#include <asm/byteorder.h>
11#include <amlogic/clk_measure.h>
12#include <amlogic/media/vout/hdmitx21/hdmitx.h>
Wenjie Qiao389d3ea2023-05-25 16:07:03 +080013#include <linux/delay.h>
Wenjie Qiao8a73a562023-02-23 18:37:14 +080014#include <amlogic/media/dv/dolby_vision.h>
15#include <linux/libfdt_env.h>
16
17static unsigned char edid_raw_buf[512] = {0};
Wenjie Qiao389d3ea2023-05-25 16:07:03 +080018/* there may be outputmode/2/3 when in multi-display case,
19 * sel_hdmimode is used to save the selected hdmi mode
20 */
21static char sel_hdmimode[MODE_LEN] = {0};
Wenjie Qiao8a73a562023-02-23 18:37:14 +080022
23static void dump_full_edid(const unsigned char *buf)
24{
25 int i;
26 int blk_no;
27
28 if (!buf)
29 return;
30 blk_no = buf[126] + 1;
31 if (blk_no > 4)
32 blk_no = 4;
Wenjie Qiao389d3ea2023-05-25 16:07:03 +080033
34 if (blk_no == 2)
35 if (buf[128 + 4] == 0xe2 && buf[128 + 5] == 0x78)
36 blk_no = buf[128 + 6] + 1;
37 if (blk_no > EDID_BLK_NO)
38 blk_no = EDID_BLK_NO;
39
Wenjie Qiao8a73a562023-02-23 18:37:14 +080040 printf("dump EDID rawdata\n");
41 printf(" ");
42 for (i = 0; i < blk_no * EDID_BLK_SIZE; i++)
43 printf("%02x", buf[i]);
44 printf("\n");
45}
46
47static int do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
48{
49 unsigned char st = 0;
50 struct hdmitx_dev *hdev = get_hdmitx21_device();
51
52 memset(edid_raw_buf, 0, ARRAY_SIZE(edid_raw_buf));
53
54 st = hdev->hwop.read_edid(edid_raw_buf);
55
56 if (!st)
57 printf("edid read failed\n");
58
59 return st;
60}
61
62static int do_rx_det(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
63{
64 unsigned char st = 0;
65 struct hdmitx_dev *hdev = get_hdmitx21_device();
66
67 memset(edid_raw_buf, 0, ARRAY_SIZE(edid_raw_buf));
68
69 // read edid raw data
70 // current only support read 1 byte edid data
71 st = hdev->hwop.read_edid(edid_raw_buf);
72
73 if (st) {
74 if (edid_raw_buf[250] == 0xfb && edid_raw_buf[251] == 0x0c) {
75 printf("RX is FBC\n");
76
77 // set outputmode ENV
78 switch (edid_raw_buf[252] & 0x0f) {
79 case 0x0:
80 run_command("setenv outputmode 1080p50hz", 0);
81 break;
82 case 0x1:
83 run_command("setenv outputmode 2160p50hz420", 0);
84 break;
85 case 0x2:
86 run_command("setenv outputmode 1080p50hz44410bit", 0);
87 break;
88 case 0x3:
89 run_command("setenv outputmode 2160p50hz42010bit", 0);
90 break;
91 case 0x4:
92 run_command("setenv outputmode 2160p50hz42210bit", 0);
93 break;
94 case 0x5:
95 run_command("setenv outputmode 2160p50hz", 0);
96 break;
97 default:
98 run_command("setenv outputmode 1080p50hz", 0);
99 break;
100 }
101
102 /*et RX 3D Info*/
103 switch ((edid_raw_buf[252] >> 4) & 0x0f) {
104 case 0x00:
105 run_command("setenv rx_3d_info 0", 0);
106 break;
107 case 0x01:
108 run_command("setenv rx_3d_info 1", 0);
109 break;
110 case 0x02:
111 run_command("setenv rx_3d_info 2", 0);
112 break;
113 case 0x03:
114 run_command("setenv rx_3d_info 3", 0);
115 break;
116 case 0x04:
117 run_command("setenv rx_3d_info 4", 0);
118 break;
119 default:
120 break;
121 }
122
123 switch (edid_raw_buf[253]) {
124 case 0x1:
125 /*TODO*/
126 break;
127 case 0x2:
128 /*TODO*/
129 break;
130 default:
131 break;
132 }
133 }
134 } else {
135 printf("edid read failed\n");
136 }
137
138 return st;
139}
140
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800141static void save_default_720p(void)
142{
143 memcpy(sel_hdmimode, DEFAULT_HDMI_MODE, sizeof(DEFAULT_HDMI_MODE));
144 if (is_hdmi_mode(env_get("outputmode")))
145 env_set("outputmode", DEFAULT_HDMI_MODE);
146 else if (is_hdmi_mode(env_get("outputmode2")))
147 env_set("outputmode2", DEFAULT_HDMI_MODE);
148 else if (is_hdmi_mode(env_get("outputmode3")))
149 env_set("outputmode3", DEFAULT_HDMI_MODE);
150 env_set("colorattribute", DEFAULT_COLOR_FORMAT);
151}
152
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800153static void hdmitx_mask_rx_info(struct hdmitx_dev *hdev)
154{
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800155 if (!hdev || !hdev->para)
156 return;
157
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800158 if (env_get("colorattribute"))
159 hdmitx21_get_fmtpara(sel_hdmimode, env_get("colorattribute"));
160
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800161 /* when current output color depth is 8bit, mask hdr capability */
162 /* refer to SWPL-44445 for more detail */
163 if (hdev->para->cd == COLORDEPTH_24B)
164 memset(&hdev->RXCap.hdr_info, 0, sizeof(struct hdr_info));
165}
166
167static int do_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
168{
169 const struct hdmi_timing *timing = NULL;
170 struct hdmitx_dev *hdev = get_hdmitx21_device();
171
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800172#ifdef CONFIG_PXP_EMULATOR
173 hdmitx21_pxp_init(1);
174#endif
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800175 if (argc < 1)
176 return cmd_usage(cmdtp);
177
178 if (strcmp(argv[1], "list") == 0) {
179 hdev->hwop.list_support_modes();
180 } else if (strcmp(argv[1], "bist") == 0) {
181 unsigned int mode = 0;
182
183 if (strcmp(argv[2], "off") == 0)
184 mode = 0;
185 else if (strcmp(argv[2], "line") == 0)
186 mode = 2;
187 else if (strcmp(argv[2], "dot") == 0)
188 mode = 3;
189 else if (strcmp(argv[2], "x") == 0)
190 mode = 'x';
191 else if (strcmp(argv[2], "X") == 0)
192 mode = 'X';
193 else
194 mode = simple_strtoul(argv[2], NULL, 10);
195 hdev->hwop.test_bist(mode);
196 } else if (strcmp(argv[1], "prbs") == 0) {
197 hdev->para->cs = HDMI_COLORSPACE_RGB;
198 hdev->para->cd = COLORDEPTH_24B;
199 hdev->vic = HDMI_16_1920x1080p60_16x9;
200 hdmitx21_set(hdev);
201 hdev->hwop.test_prbs();
202 } else if (strncmp(argv[1], "div40", 5) == 0) {
203 bool div40 = 0;
204
205 if (argv[1][5] == '1')
206 div40 = 1;
207 hdev->hwop.set_div40(div40);
208 } else { /* "output" */
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800209 if (!hdev->pxp_mode) {
210 if (!edid_parsing_ok(hdev)) {
211 /* in SWPL-34712: if EDID parsing error in kernel,
212 * only forcely output default mode(480p,RGB,8bit)
213 * in sysctl, not save the default mode to env.
214 * if uboot follow this rule, will cause issue OTT-19333:
215 * uboot read edid error and then output default mode,
216 * without save it mode env. if then kernel edid normal,
217 * sysctrl/kernel get mode from env, the actual output
218 * mode differs with outputmode env,it will
219 * cause display abnormal(such as stretch). so don't
220 * follow this rule in uboot, that's to say the actual
221 * output mode needs to stays with the outputmode env.
222 */
223 printf("edid parsing ng, forcely output 720p, rgb,8bit\n");
224 save_default_720p();
225 hdev->vic = HDMI_4_1280x720p60_16x9;
226 hdev->para =
227 hdmitx21_get_fmtpara("720p60hz", "rgb,8bit");
228 hdev->para->cs = HDMI_COLORSPACE_RGB;
229 hdev->para->cd = COLORDEPTH_24B;
230 hdmitx21_set(hdev);
231 return CMD_RET_SUCCESS;
232 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800233 }
234 if (!env_get("colorattribute"))
235 env_set("colorattribute", "444,8bit");
236 hdev->para = hdmitx21_get_fmtpara(argv[1], env_get("colorattribute"));
237 hdev->vic = hdev->para->timing.vic;
238 if (hdev->vic == HDMI_UNKNOWN) {
239 /* Not find VIC */
240 printf("Not find '%s' mapped VIC\n", argv[1]);
241 return CMD_RET_FAILURE;
242 }
243 if (strstr(argv[1], "hz420"))
244 hdev->para->cs = HDMI_COLORSPACE_YUV420;
245 /* S5 support over 6G, T7 not support */
246 switch (hdev->vic) {
247 case HDMI_96_3840x2160p50_16x9:
248 case HDMI_97_3840x2160p60_16x9:
249 case HDMI_101_4096x2160p50_256x135:
250 case HDMI_102_4096x2160p60_256x135:
251 case HDMI_106_3840x2160p50_64x27:
252 case HDMI_107_3840x2160p60_64x27:
253 if (hdev->chip_type == MESON_CPU_ID_T7) {
254 if (hdev->para->cs == HDMI_COLORSPACE_RGB ||
255 hdev->para->cs == HDMI_COLORSPACE_YUV444) {
256 if (hdev->para->cd != COLORDEPTH_24B) {
257 printf("vic %d cs %d has no cd %d\n",
258 hdev->vic,
259 hdev->para->cs,
260 hdev->para->cd);
261 hdev->para->cd = COLORDEPTH_24B;
262 printf("set cd as %d\n", COLORDEPTH_24B);
263 }
264 }
265 }
266 break;
267 default:
268 /* In Spec2.1 Table 7-34, greater than 2160p30hz will support y420 */
269 timing = hdmitx21_gettiming_from_vic(hdev->vic);
270 if (!timing)
271 break;
272 if (timing->v_active > 2160 && timing->v_freq > 30000)
273 break;
274 if (timing->v_active >= 4320)
275 break;
276 if (hdev->para->cs == HDMI_COLORSPACE_YUV420) {
277 printf("vic %d has no cs %d\n", hdev->vic,
278 hdev->para->cs);
279 hdev->para->cs = HDMI_COLORSPACE_YUV444;
280 printf("set cs as %d\n", HDMI_COLORSPACE_YUV444);
281 }
282 break;
283 }
284 printf("set hdmitx VIC = %d CS = %d CD = %d\n",
285 hdev->vic, hdev->para->cs, hdev->para->cd);
286 /* currently, hdmi mode is always set, if
287 * mode set abort/exit, need to add return
288 * result of mode setting, so that vout
289 * driver will pass it to kernel, and do
290 * mode setting again when vout init in kernel
291 */
292 hdmitx21_set(hdev);
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800293 if (hdev->frl_rate && !hdev->flt_train_st) {
294 /* FLT training failed, need go to tmds mode */
295 printf("hdmitx frl training failed, set tmds mode\n");
296 run_command("setenv hdmimode 1080p60hz", 0);
297 run_command("setenv colorattribute 422,12bit", 0);
298 run_command("run init_display_base", 0);
299 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800300 }
301 return CMD_RET_SUCCESS;
302}
303
304static int do_clkmsr(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
305{
306 clk_msr(51);
307 clk_msr(59);
308 clk_msr(61);
309 clk_msr(76);
310 clk_msr(77);
311 clk_msr(78);
312 clk_msr(80);
313 clk_msr(81);
314 clk_msr(82);
315 clk_msr(83);
316 clk_msr(219);
317 clk_msr(220);
318 clk_msr(221);
319 clk_msr(222);
320 return CMD_RET_SUCCESS;
321}
322
323static int do_blank(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
324{
325 struct hdmitx_dev *hdev = get_hdmitx21_device();
326
327 if (argc < 1)
328 return cmd_usage(cmdtp);
329
330 if (strcmp(argv[1], "1") == 0)
331 hdev->hwop.output_blank(1);
332 if (strcmp(argv[1], "0") == 0)
333 hdev->hwop.output_blank(0);
334
335 return CMD_RET_SUCCESS;
336}
337
338static int do_off(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
339{
340 struct hdmitx_dev *hdev = get_hdmitx21_device();
341
342 hdev->vic = HDMI_UNKNOWN;
343 hdev->hwop.turn_off();
344 printf("turn off hdmitx\n");
345 return 1;
346}
347
348static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
349{
350 struct hdmitx_dev *hdev = get_hdmitx21_device();
351
352 hdev->hwop.dump_regs();
353 return 1;
354}
355
356static int do_reg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
357{
358 unsigned long addr = 0;
359 unsigned int data = 0;
360
361 if (argc < 1)
362 return cmd_usage(cmdtp);
363
364 if (strncmp(argv[1], "rh", 2) == 0) {
365 addr = strtoul(argv[1] + 2, NULL, 16);
366 data = hdmitx21_rd_reg((unsigned int)addr);
367 printf("rd[0x%lx] 0x%x\n", addr, data);
368 }
369
370 if (strncmp(argv[1], "wh", 2) == 0) {
371 addr = strtoul(argv[1] + 2, NULL, 16);
372 data = strtoul(argv[2], NULL, 16);
373 hdmitx21_wr_reg(addr, data);
374 printf("wr[0x%lx] 0x%x\n", addr, data);
375 }
376
377 return 1;
378}
379
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800380static int do_pbist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
381{
382 struct hdmitx_dev *hdev = get_hdmitx21_device();
383
384 if (strcmp(argv[1], "1") == 0)
385 hdmitx21_pbist_config(hdev, hdev->vic, 1);
386 if (strcmp(argv[1], "0") == 0)
387 hdmitx21_pbist_config(hdev, hdev->vic, 0);
388 return 1;
389}
390
391static int do_debug(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
392{
393 unsigned int enable_all = 0;
394 int pkt_op = 0;
395 unsigned int mov_val = 0;
396 unsigned char pb[28] = {0x46, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x46, 0xD0,
397 0x00, 0x10, 0x21, 0xaa, 0x9b, 0x96, 0x19, 0xfc, 0x19, 0x75, 0xd5, 0x78,
398 0x10, 0x21, 0xaa, 0x9b, 0x96, 0x19, 0xfc, 0x19};
399 unsigned char hb[3] = {0x01, 0x02, 0x03};
400
401 if (argc < 1)
402 return cmd_usage(cmdtp);
403
404 if (strncmp(argv[1], "pkt", 3) == 0) {
405 enable_all = strtoul(argv[1] + 3, NULL, 16);
406 pkt_op = strtoul(argv[2], NULL, 16);
407 mov_val = strtoul(argv[3], NULL, 10);
408 pkt_send_position_change(enable_all, pkt_op, mov_val);
409 } else if (strncmp(argv[1], "w_dhdr", 6) == 0 ) {
410 hdmitx21_write_dhdr_sram();
411 } else if (strncmp(argv[1], "r_dhdr", 6) == 0 ) {
412 hdmitx21_read_dhdr_sram();
413 } else if (strncmp(argv[1], "t_avi", 4) == 0 ) {
414 printf("test send avi pkt\n");
415 hdmi_avi_infoframe_rawset(hb, pb);
416 } else if (strncmp(argv[1], "t_audio", 7) == 0 ) {
417 printf("test send audio pkt\n");
418 hdmi_audio_infoframe_rawset(hb, pb);
419 } else if (strncmp(argv[1], "t_sbtm", 6) == 0 ) {
420 printf("test send SBTM pkt\n");
421 hdmitx21_send_sbtm_pkt();
422 }
423
424 return 1;
425}
426
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800427static bool check_vic_exist(struct hdmitx_dev *hdev, enum hdmi_vic vic,
428 int count)
429{
430 struct rx_cap *rxcap = NULL;
431 int i;
432
433 rxcap = &hdev->RXCap;
434 for (i = 0; i < count; i++)
435 if (vic == rxcap->VIC[i])
436 return 1;
437
438 return 0;
439}
440
441static void disp_cap_show(struct hdmitx_dev *hdev)
442{
443 struct rx_cap *rxcap = NULL;
444 const struct hdmi_timing *timing = NULL;
445 enum hdmi_vic vic;
446 int i;
447
448 if (!hdev)
449 return;
450
451 rxcap = &hdev->RXCap;
452 printf("disp_cap\n");
453 for (i = 0; i < rxcap->VIC_count && i < VIC_MAX_NUM; i++) {
454 vic = rxcap->VIC[i];
455 if (check_vic_exist(hdev, vic, i))
456 continue;
457 timing = hdmitx21_gettiming_from_vic(vic);
458 if (timing && vic < HDMITX_VESA_OFFSET && !is_vic_over_limited_1080p(vic))
459 printf(" %s\n", timing->sname ? timing->sname : timing->name);
460 }
461}
462
463static void vesa_cap_show(struct hdmitx_dev *hdev)
464{
465}
466
467static void dc_cap_show(struct hdmitx_dev *hdev)
468{
469 enum hdmi_vic vic = HDMI_0_UNKNOWN;
470 struct rx_cap *prxcap = &hdev->RXCap;
471 const struct dv_info *dv = &hdev->RXCap.dv_info;
472
473 printf("dc_cap\n");
474 if (prxcap->dc_36bit_420)
475 printf("420,12bit\n");
476 if (prxcap->dc_30bit_420) {
477 printf("420,10bit\n");
478 printf("420,8bit\n");
479 } else {
480 vic = hdmitx_edid_get_VIC(hdev, "2160p60hz420", 0);
481 if (vic != HDMI_0_UNKNOWN) {
482 printf("420,8bit\n");
483 goto next444;
484 }
485 vic = hdmitx_edid_get_VIC(hdev, "2160p50hz420", 0);
486 if (vic != HDMI_0_UNKNOWN) {
487 printf("420,8bit\n");
488 goto next444;
489 }
490 vic = hdmitx_edid_get_VIC(hdev, "smpte60hz420", 0);
491 if (vic != HDMI_0_UNKNOWN) {
492 printf("420,8bit\n");
493 goto next444;
494 }
495 vic = hdmitx_edid_get_VIC(hdev, "smpte50hz420", 0);
496 if (vic != HDMI_0_UNKNOWN) {
497 printf("420,8bit\n");
498 goto next444;
499 }
500 }
501next444:
502 if (prxcap->native_Mode & (1 << 5)) {
503 if (prxcap->dc_y444) {
504 if (prxcap->dc_36bit || dv->sup_10b_12b_444 == 0x2)
505 printf("444,12bit\n");
506 if (prxcap->dc_30bit || dv->sup_10b_12b_444 == 0x1)
507 printf("444,10bit\n");
508 }
509 printf("444,8bit\n");
510 }
511 /* y422, not check dc */
512 if (prxcap->native_Mode & (1 << 4)) {
513 printf("422,12bit\n");
514 printf("422,10bit\n");
515 printf("422,8bit\n");
516 }
517
518 if (prxcap->dc_36bit || dv->sup_10b_12b_444 == 0x2)
519 printf("rgb,12bit\n");
520 if (prxcap->dc_30bit || dv->sup_10b_12b_444 == 0x1)
521 printf("rgb,10bit\n");
522 printf("rgb,8bit\n");
523}
524
525static void aud_cap_show(struct hdmitx_dev *hdev)
526{
527}
528
529static void hdr_cap_show(struct hdmitx_dev *hdev)
530{
531 int hdr10plugsupported = 0;
532 struct hdr_info *hdr = &hdev->RXCap.hdr_info;
533 const struct hdr10_plus_info *hdr10p = &hdev->RXCap.hdr10plus_info;
534
535 printf("\nhdr_cap\n");
536 if (hdr10p->ieeeoui == HDR10_PLUS_IEEE_OUI &&
537 hdr10p->application_version != 0xFF)
538 hdr10plugsupported = 1;
539 printf("HDR10Plus Supported: %d\n", hdr10plugsupported);
540 printf("HDR Static Metadata:\n");
541 printf(" Supported EOTF:\n");
542 printf(" Traditional SDR: %d\n", !!hdr->hdr_sup_eotf_sdr);
543 printf(" Traditional HDR: %d\n", !!hdr->hdr_sup_eotf_hdr);
544 printf(" SMPTE ST 2084: %d\n", !!hdr->hdr_sup_eotf_smpte_st_2084);
545 printf(" Hybrid Log-Gamma: %d\n", !!hdr->hdr_sup_eotf_hlg);
546 printf(" Supported SMD type1: %d\n", hdr->hdr_sup_SMD_type1);
547 printf(" Luminance Data\n");
548 printf(" Max: %d\n", hdr->hdr_lum_max);
549 printf(" Avg: %d\n", hdr->hdr_lum_avg);
550 printf(" Min: %d\n\n", hdr->hdr_lum_min);
551 printf("HDR Dynamic Metadata:");
552}
553
554static void _dv_cap_show(const struct dv_info *dv)
555{
556 int i;
557
558 if (dv->ieeeoui != DV_IEEE_OUI || dv->block_flag != CORRECT) {
559 printf("The Rx don't support DolbyVision\n");
560 return;
561 }
562 printf("DolbyVision RX support list:\n");
563
564 if (dv->ver == 0) {
565 printf("VSVDB Version: V%d\n", dv->ver);
566 printf("2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30");
567 printf("Support mode:\n");
568 printf(" DV_RGB_444_8BIT\n");
569 if (dv->sup_yuv422_12bit)
570 printf(" DV_YCbCr_422_12BIT\n");
571 }
572 if (dv->ver == 1) {
573 printf("VSVDB Version: V%d(%d-byte)\n", dv->ver, dv->length + 1);
574 if (dv->length == 0xB) {
575 printf("2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30");
576 printf("Support mode:\n");
577 printf(" DV_RGB_444_8BIT\n");
578 if (dv->sup_yuv422_12bit)
579 printf(" DV_YCbCr_422_12BIT\n");
580 if (dv->low_latency == 0x01)
581 printf(" LL_YCbCr_422_12BIT\n");
582 }
583
584 if (dv->length == 0xE) {
585 printf("2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30");
586 printf("Support mode:\n");
587 printf(" DV_RGB_444_8BIT\n");
588 if (dv->sup_yuv422_12bit)
589 printf(" DV_YCbCr_422_12BIT\n");
590 }
591 }
592 if (dv->ver == 2) {
593 printf("VSVDB Version: V%d\n", dv->ver);
594 printf("2160p%shz: 1\n", dv->sup_2160p60hz ? "60" : "30");
595 printf("Support mode:\n");
596 if (dv->Interface != 0x00 && dv->Interface != 0x01) {
597 printf(" DV_RGB_444_8BIT\n");
598 if (dv->sup_yuv422_12bit)
599 printf(" DV_YCbCr_422_12BIT\n");
600 }
601 printf(" LL_YCbCr_422_12BIT\n");
602 if (dv->Interface == 0x01 || dv->Interface == 0x03) {
603 if (dv->sup_10b_12b_444 == 0x1)
604 printf(" LL_RGB_444_10BIT\n");
605 if (dv->sup_10b_12b_444 == 0x2)
606 printf(" LL_RGB_444_12BIT\n");
607 }
608 }
609 printf("IEEEOUI: 0x%06x\n", dv->ieeeoui);
610 printf("VSVDB: ");
611 for (i = 0; i < (dv->length + 1); i++)
612 printf("%02x", dv->rawdata[i]);
613 printf("\n");
614}
615
616static void dv_cap_show(struct hdmitx_dev *hdev)
617{
618 const struct dv_info *dv = &hdev->RXCap.dv_info;
619
620 printf("dv_cap\n");
621 if (dv->ieeeoui != DV_IEEE_OUI) {
622 printf("The Rx don't support DolbyVision\n");
623 return;
624 }
625 _dv_cap_show(dv);
626}
627
628static void edid_cap_show(struct hdmitx_dev *hdev)
629{
630 int i;
631 struct rx_cap *prxcap = &hdev->RXCap;
632
633 printf("EDID Version: %d.%d\n", prxcap->edid_version, prxcap->edid_revision);
634
635 printf("EDID block number: 0x%x\n", hdev->rawedid[0x7e]);
636 printf("blk0 chksum: 0x%02x\n", prxcap->chksum);
637
638 printf("native Mode %x, VIC (native %d):\n",
639 prxcap->native_Mode, prxcap->native_VIC);
640
641 printf("ColorDeepSupport %x\n", prxcap->ColorDeepSupport);
642
643 for (i = 0 ; i < prxcap->VIC_count ; i++)
644 printf("%d ", prxcap->VIC[i]);
645 printf("\n");
646 printf("Vendor: 0x%x ( %s device)\n",
647 prxcap->IEEEOUI, (prxcap->IEEEOUI) ? "HDMI" : "DVI");
648
649 printf("MaxTMDSClock1 %d MHz\n", prxcap->Max_TMDS_Clock1 * 5);
650
651 if (prxcap->HF_IEEEOUI) {
652 printf("Vendor2: 0x%x\n", prxcap->HF_IEEEOUI);
653 printf("MaxTMDSClock2 %d MHz\n", prxcap->Max_TMDS_Clock2 * 5);
654 }
655
656 printf("Video_Latency: ");
657 if (prxcap->Video_Latency == 0)
658 printf(" Invalid/Unknown\n");
659 else if (prxcap->Video_Latency == 0xffff)
660 printf(" UnSupported\n");
661 else
662 printf(" %d\n", prxcap->Video_Latency);
663
664 printf("Audio_Latency: ");
665 if (prxcap->Audio_Latency == 0)
666 printf(" Invalid/Unknown\n");
667 else if (prxcap->Audio_Latency == 0xffff)
668 printf(" UnSupported\n");
669 else
670 printf(" %d\n", prxcap->Audio_Latency);
671
672 printf("Interlaced_Video_Latency: ");
673 if (prxcap->Interlaced_Video_Latency == 0)
674 printf(" Invalid/Unknown\n");
675 else if (prxcap->Interlaced_Video_Latency == 0xffff)
676 printf(" UnSupported\n");
677 else
678 printf(" %d\n", prxcap->Interlaced_Video_Latency);
679
680 printf("Interlaced_Audio_Latency: ");
681 if (prxcap->Interlaced_Audio_Latency == 0)
682 printf(" Invalid/Unknown\n");
683 else if (prxcap->Interlaced_Audio_Latency == 0xffff)
684 printf(" UnSupported\n");
685 else
686 printf(" %d\n", prxcap->Interlaced_Audio_Latency);
687
688 if (prxcap->colorimetry_data)
689 printf("ColorMetry: 0x%x\n", prxcap->colorimetry_data);
690 printf("SCDC: %x\n", prxcap->scdc_present);
691 printf("RR_Cap: %x\n", prxcap->scdc_rr_capable);
692 printf("LTE_340M_Scramble: %x\n", prxcap->lte_340mcsc_scramble);
693
694 if (prxcap->dv_info.ieeeoui == DV_IEEE_OUI)
695 printf(" DolbyVision%d", prxcap->dv_info.ver);
696 if (prxcap->hdr_info.hdr_sup_eotf_smpte_st_2084)
697 printf(" HDR/%d", prxcap->hdr_info.hdr_sup_eotf_smpte_st_2084);
698 if (prxcap->dc_y444 || prxcap->dc_30bit || prxcap->dc_30bit_420)
699 printf(" DeepColor");
700 printf("\n");
701}
702
703static int do_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
704{
705 struct hdmitx_dev *hdev = get_hdmitx21_device();
706 struct hdmi_format_para *para;
707
708 if (!hdev) {
709 pr_info("null hdmitx dev\n");
710 return CMD_RET_FAILURE;
711 }
712 if (!hdev->para) {
713 printf("null hdmitx para\n");
714 return CMD_RET_FAILURE;
715 }
716
717 para = hdev->para;
718 printf("current mode %s vic %d\n", para->timing.name, hdev->vic);
719 printf("cd%d cs%d cr%d\n", para->cd, para->cs, para->cr);
720 printf("enc_idx %d\n", hdev->enc_idx);
721 printf("frac_rate: %d\n", hdev->frac_rate_policy);
722 printf("Rx EDID info\n");
723 dump_full_edid(hdev->rawedid);
724 disp_cap_show(hdev);
725 vesa_cap_show(hdev);
726 aud_cap_show(hdev);
727 hdr_cap_show(hdev);
728 dv_cap_show(hdev);
729 dc_cap_show(hdev);
730 edid_cap_show(hdev);
731 return 1;
732}
733
734static int xtochar(int num, char *checksum)
735{
736 struct hdmitx_dev *hdev = get_hdmitx21_device();
737
738 if (((hdev->rawedid[num] >> 4) & 0xf) <= 9)
739 checksum[0] = ((hdev->rawedid[num] >> 4) & 0xf) + '0';
740 else
741 checksum[0] = ((hdev->rawedid[num] >> 4) & 0xf) - 10 + 'a';
742
743 if ((hdev->rawedid[num] & 0xf) <= 9)
744 checksum[1] = (hdev->rawedid[num] & 0xf) + '0';
745 else
746 checksum[1] = (hdev->rawedid[num] & 0xf) - 10 + 'a';
747
748 return 0;
749}
750
751static void get_parse_edid_data(struct hdmitx_dev *hdev)
752{
753 char *hdr_priority = env_get("hdr_priority");
754
755 hdev->hwop.read_edid(hdev->rawedid);
756
ruofei.zhao4a2ec0c2023-10-31 19:24:41 +0800757 /* dump edid raw data */
758 dump_full_edid(hdev->rawedid);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800759
760 /* parse edid data */
761 hdmi_edid_parsing(hdev->rawedid, &hdev->RXCap);
762
763 if (!hdr_priority)
764 return;
765 /* if hdr_priority is 2, then mark both dv_info and hdr_info */
766 if (strcmp(hdr_priority, "2") == 0) {
767 memset(&hdev->RXCap.dv_info, 0, sizeof(struct dv_info));
768 memset(&hdev->RXCap.hdr_info, 0, sizeof(struct hdr_info));
769 memset(&hdev->RXCap.hdr10plus_info, 0, sizeof(struct hdr10_plus_info));
770 pr_info("hdr_priority: %s and clear dv/hdr_info\n", hdr_priority);
771 return;
772 }
773 /* if hdr_priority is 1, then mark dv_info */
774 if (hdr_priority && (strcmp(hdr_priority, "1") == 0)) {
775 memset(&hdev->RXCap.dv_info, 0, sizeof(struct dv_info));
776 pr_info("hdr_priority: %s and clear dv_info\n", hdr_priority);
777 }
778}
779
780/* policy process: to find the output mode/attr/dv_type */
781void scene_process(struct hdmitx_dev *hdev,
782 struct scene_output_info *scene_output_info)
783{
784 struct input_hdmi_data hdmidata;
785
786 if (!hdev || !scene_output_info)
787 return;
788 /* 1.read dolby vision mode from prop(maybe need to env) */
789 memset(&hdmidata, 0, sizeof(struct input_hdmi_data));
790 get_hdmi_data(hdev, &hdmidata);
791
792 /* 2. dolby vision scene process */
793 /* only for tv support dv and box enable dv */
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800794 if (is_dv_preference(hdev)) {
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800795 dolbyvision_scene_process(&hdmidata, scene_output_info);
796 } else if (is_dolby_enabled()) {
797 /* for enable dolby vision core when
798 * first boot connecting non dv tv
799 * NOTE: let systemcontrol to enable DV core
800 */
801 /* scene_output_info->final_dv_type = DOLBY_VISION_ENABLE; */
802 } else {
803 /* for UI disable dolby vision core and boot keep the status
804 * NOTE: TBD if need to disable DV here
805 */
806 /* scene_output_info->final_dv_type = DOLBY_VISION_DISABLE; */
807 }
808 /* 3.sdr scene process */
809 /* decide final display mode and deepcolor */
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800810 if (is_dv_preference(hdev)) {
811 /* do nothing
812 * already done above, just sync with sysctrl
813 */
814 } else if (is_hdr_preference(hdev)) {
815 hdr_scene_process(&hdmidata, scene_output_info);
816 } else {
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800817 sdr_scene_process(&hdmidata, scene_output_info);
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800818 }
819 /* not find outputmode and use default mode */
820 if (strlen(scene_output_info->final_displaymode) == 0)
821 strcpy(scene_output_info->final_displaymode, DEFAULT_HDMI_MODE);
822 /* not find color space and use default mode */
823 if (!strstr(scene_output_info->final_deepcolor, "bit"))
824 strcpy(scene_output_info->final_deepcolor, DEFAULT_COLOR_FORMAT);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800825}
826
827static int do_get_parse_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
828{
829 struct hdmitx_dev *hdev = get_hdmitx21_device();
830 unsigned char *edid = hdev->rawedid;
831 unsigned char *store_checkvalue;
832
833 memset(edid, 0, EDID_BLK_SIZE * EDID_BLK_NO);
834 unsigned int i;
835 unsigned int checkvalue[4];
836 unsigned int checkvalue1;
837 unsigned int checkvalue2;
838 char checksum[11];
839 unsigned char def_cksum[] = {'0', 'x', '0', '0', '0', '0', '0', '0', '0', '0', '\0'};
840 char *hdmimode;
841 char *colorattribute;
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800842 int user_dv_mode;
843 char *last_output_mode;
844 char *last_colorattribute;
845 int last_dv_status;
846 bool over_write = false;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800847 char dv_type[2] = {0};
848 struct scene_output_info scene_output_info;
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800849 struct hdmi_format_para *para = NULL;
850 bool mode_support = false;
851 /* hdmi_mode / colorattribute may be null or "none".
852 * if either is null or "none", it means user not
853 * selected manually, and need to select the best
854 * mode or colorattribute by policy
855 */
856 bool no_manual_output = false;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800857
858 if (!hdev->hwop.get_hpd_state()) {
859 printf("HDMI HPD low, no need parse EDID\n");
860 return 1;
861 }
862 memset(&scene_output_info, 0, sizeof(struct scene_output_info));
863
864 get_parse_edid_data(hdev);
865
866 /* check if the tv has changed or anything wrong */
867 store_checkvalue = (unsigned char *)env_get("hdmichecksum");
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800868 /* get user selected output mode/color */
869 colorattribute = env_get("user_colorattribute");
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800870 hdmimode = env_get("hdmimode");
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800871 user_dv_mode = get_ubootenv_dv_type();
872
873 last_output_mode = env_get("outputmode");
874 last_colorattribute = env_get("colorattribute");
875 last_dv_status = get_ubootenv_dv_status();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800876 if (!store_checkvalue)
877 store_checkvalue = def_cksum;
878
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800879 printf("read hdmichecksum: %s, user hdmimode: %s, colorattribute: %s, dv_type: %d\n",
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800880 store_checkvalue, hdmimode ? hdmimode : "null",
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800881 colorattribute ? colorattribute : "null", user_dv_mode);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800882
883 for (i = 0; i < 4; i++) {
884 if (('0' <= store_checkvalue[i * 2 + 2]) && (store_checkvalue[i * 2 + 2] <= '9'))
885 checkvalue1 = store_checkvalue[i * 2 + 2] - '0';
886 else
887 checkvalue1 = store_checkvalue[i * 2 + 2] - 'W';
888 if (('0' <= store_checkvalue[i * 2 + 3]) && (store_checkvalue[i * 2 + 3] <= '9'))
889 checkvalue2 = store_checkvalue[i * 2 + 3] - '0';
890 else
891 checkvalue2 = store_checkvalue[i * 2 + 3] - 'W';
892 checkvalue[i] = checkvalue1 * 16 + checkvalue2;
893 }
894
895 if (checkvalue[0] != hdev->rawedid[0x7f] ||
896 checkvalue[1] != hdev->rawedid[0xff] ||
897 checkvalue[2] != hdev->rawedid[0x17f] ||
898 checkvalue[3] != hdev->rawedid[0x1ff]) {
899 hdev->RXCap.edid_changed = 1;
900
901 checksum[0] = '0';
902 checksum[1] = 'x';
903 for (i = 0; i < 4; i++)
904 xtochar(0x80 * i + 0x7f, &checksum[2 * i + 2]);
905 checksum[10] = '\0';
906 memcpy(hdev->RXCap.checksum, checksum, 10);
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800907 printf("TV has changed, now crc: %s\n", checksum);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800908 } else {
909 memcpy(hdev->RXCap.checksum, store_checkvalue, 10);
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800910 printf("TV is same, checksum: %s\n", hdev->RXCap.checksum);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800911 }
912
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800913 /* check user have selected both mode/color or not */
914 if (!hdmimode || !strcmp(hdmimode, "none") ||
915 !colorattribute || !strcmp(colorattribute, "none"))
916 no_manual_output = true;
917 else
918 no_manual_output = false;
919
920 if (!no_manual_output) {
921 /* check current user selected mode + color support or not */
922 para = hdmitx21_get_fmtpara(hdmimode, colorattribute);
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800923 if (hdmitx_edid_check_valid_mode(hdev, para)) {
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800924 mode_support = true;
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800925 } else {
926 printf("saved output mode not supported!\n");
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800927 mode_support = false;
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800928 }
929
930 /* if user selected mode/color/dv type which saved in ubootenv of
931 * hdmimode/user_colorattribute/user_prefer_dv_type are different
932 * with last actual output mode/color/dv type which saved in
933 * ubootenv of outputmode/colorattribute/dolby_status, then it means
934 * that the user selected format is over-writen by policy(for example:
935 * firstly user has selected HDR priority to HDR, and select color
936 * to rgb,12bit(now the "user_colorattribute" env will be "rgb,12bit"),
937 * but then it selected HDR priority to DV, the actual output color
938 * will be "444,8bit" or "422,12bit" according to dv type, and
939 * the ubootenv "colorattribute" will be "444,8bit" or "422,12bit"),
940 * then uboot should use the policy to select the output format,
941 * otherwise, uboot use hdmimode/user_colorattribute/user_prefer_dv_type
942 * env, while system use outputmode/colorattribute/dolby_status env,
943 * there will be always a mode change during bootup
944 */
945 if (mode_support) {
946 /* note that for T7 multi-display, it may store panel in
947 * "outputmode" env, and will always run uboot policy
948 */
949 if (!last_output_mode || strcmp(hdmimode, last_output_mode))
950 over_write = true;
951 else if (!last_colorattribute ||
952 strcmp(colorattribute, last_colorattribute))
953 over_write = true;
954 else if (user_dv_mode != last_dv_status)
955 over_write = true;
956 else
957 over_write = false;
958
959 if (over_write)
960 printf("last output_mode:%s, colorattribute:%s, dolby_status:%d\n",
961 last_output_mode ? last_output_mode : "null",
962 last_colorattribute ? last_colorattribute : "null",
963 last_dv_status);
964 }
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800965 }
966 /* three cases need to decide output by uboot mode select policy:
967 * 1.TV changed
968 * 2.either hdmimode or colorattribute is NULL or "none",
969 * which means that user have not selected mode or colorattribute,
970 * and need to select the auto best mode or best colorattribute.
971 * 3.user selected mode not supportted by uboot (probably
972 * means mode select policy or edid parse between sysctrl and
973 * uboot have some gap), then need to find proper output mode
974 * with uboot policy.
975 */
xiang.wu1a6d6f1d2023-08-04 14:13:00 +0800976 if (hdev->RXCap.edid_changed || no_manual_output || !mode_support || over_write) {
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800977 /* find proper mode if EDID changed */
978 scene_process(hdev, &scene_output_info);
979 env_set("hdmichecksum", hdev->RXCap.checksum);
980 if (edid_parsing_ok(hdev)) {
981 /* SWPL-34712: if EDID parsing error case, not save env,
982 * only output default mode(480p,RGB,8bit). after
983 * EDID read OK, systemcontrol will recover the hdmi
984 * mode from env, to avoid keep the default hdmi output
985 */
Wenjie Qiao389d3ea2023-05-25 16:07:03 +0800986 memcpy(sel_hdmimode, scene_output_info.final_displaymode,
987 sizeof(scene_output_info.final_displaymode));
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800988 if (is_hdmi_mode(env_get("outputmode"))) {
989 env_set("outputmode",
990 scene_output_info.final_displaymode);
991 } else if (is_hdmi_mode(env_get("outputmode2"))) {
992 env_set("outputmode2",
993 scene_output_info.final_displaymode);
994 } else if (is_hdmi_mode(env_get("outputmode3"))) {
995 env_set("outputmode3",
996 scene_output_info.final_displaymode);
997 }
998 env_set("colorattribute",
999 scene_output_info.final_deepcolor);
1000 /* if change from DV TV to HDR/SDR TV, don't change
1001 * DV status to disabled, as DV core need to be enabled.
xiang.wu1a6d6f1d2023-08-04 14:13:00 +08001002 * that's to say connect DV TV & output DV-> power down box ->
1003 * connect HDR/SDR TV -> power on box, the dolby_status
1004 * will keep the same as that when connect DV TV under follow sink.
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001005 */
xiang.wu1a6d6f1d2023-08-04 14:13:00 +08001006 if (scene_output_info.final_dv_type != get_ubootenv_dv_status() &&
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001007 scene_output_info.final_dv_type != DOLBY_VISION_DISABLE) {
1008 sprintf(dv_type, "%d", scene_output_info.final_dv_type);
1009 env_set("dolby_status", dv_type);
1010 /* according to the policy of systemcontrol,
1011 * if current DV mode is not supported by TV
1012 * EDID, DV type maybe changed to one witch
1013 * TV support, and need VPP/DV module to
1014 * update new DV output mode.
1015 */
xiang.wu1a6d6f1d2023-08-04 14:13:00 +08001016 printf("update dolby_status: %d\n",
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001017 scene_output_info.final_dv_type);
1018 }
Wenjie Qiao389d3ea2023-05-25 16:07:03 +08001019 } else {
1020 save_default_720p();
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001021 }
Wenjie Qiao389d3ea2023-05-25 16:07:03 +08001022 printf("update outputmode: %s\n", sel_hdmimode);
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001023 printf("update colorattribute: %s\n", env_get("colorattribute"));
1024 printf("update hdmichecksum: %s\n", env_get("hdmichecksum"));
Wenjie Qiao389d3ea2023-05-25 16:07:03 +08001025 } else {
1026 memset(sel_hdmimode, 0, sizeof(sel_hdmimode));
1027 memcpy(sel_hdmimode, hdmimode, strlen(hdmimode));
1028 if (is_hdmi_mode(env_get("outputmode")))
1029 env_set("outputmode", hdmimode);
1030 else if (is_hdmi_mode(env_get("outputmode2")))
1031 env_set("outputmode2", hdmimode);
1032 else if (is_hdmi_mode(env_get("outputmode3")))
1033 env_set("outputmode3", hdmimode);
1034 env_set("colorattribute", colorattribute);
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001035 }
xiang.wu1a6d6f1d2023-08-04 14:13:00 +08001036 env_set("save_outputmode", sel_hdmimode);
1037 /* ubootenv dolby_status is used for is_dv_preference() decision,
1038 * system_control save current dv output status in it.
1039 * it will be used by dv module later to decide DV output later.
1040 * if currently adaptive hdr, then we should set dolby_status to
1041 * 0, so that DV module won't enable DV.
1042 */
1043 if (get_hdr_policy() == 1)
1044 env_set("dolby_status", 0);
Wenjie Qiao389d3ea2023-05-25 16:07:03 +08001045 hdev->para = hdmitx21_get_fmtpara(sel_hdmimode, env_get("colorattribute"));
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001046 hdev->vic = hdev->para->timing.vic;
1047 hdmitx_mask_rx_info(hdev);
1048 return 0;
1049}
1050
Wenjie Qiao77833902023-12-18 19:01:59 +08001051#ifdef CONFIG_EFUSE_OBJ_API
1052static int do_efuse_show(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1053{
1054 struct hdmitx_dev *hdev = get_hdmitx21_device();
1055
1056 get_hdmi_efuse(hdev);
1057 pr_info("FEAT_DISABLE_HDMI_60HZ = %d\n", hdev->efuse_dis_hdmi_4k60);
1058 pr_info("FEAT_DISABLE_OUTPUT_4K = %d\n", hdev->efuse_dis_output_4k);
1059 pr_info("FEAT_DISABLE_HDCP_TX_22 = %d\n", hdev->efuse_dis_hdcp_tx22);
1060 pr_info("FEAT_DISABLE_HDMI_TX_3D = %d\n", hdev->efuse_dis_hdmi_tx3d);
1061 pr_info("FEAT_DISABLE_HDMI = %d\n", hdev->efuse_dis_hdcp_tx14);
1062
1063 return 0;
1064}
1065#endif
1066
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001067static cmd_tbl_t cmd_hdmi_sub[] = {
1068 U_BOOT_CMD_MKENT(hpd, 1, 1, do_hpd_detect, "", ""),
1069 U_BOOT_CMD_MKENT(edid, 3, 1, do_edid, "", ""),
1070 U_BOOT_CMD_MKENT(rx_det, 1, 1, do_rx_det, "", ""),
1071 U_BOOT_CMD_MKENT(output, 3, 1, do_output, "", ""),
1072 U_BOOT_CMD_MKENT(clkmsr, 3, 1, do_clkmsr, "", ""),
1073 U_BOOT_CMD_MKENT(blank, 3, 1, do_blank, "", ""),
1074 U_BOOT_CMD_MKENT(off, 1, 1, do_off, "", ""),
1075 U_BOOT_CMD_MKENT(dump, 1, 1, do_dump, "", ""),
1076 U_BOOT_CMD_MKENT(info, 1, 1, do_info, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001077 U_BOOT_CMD_MKENT(reg, 3, 1, do_reg, "", ""),
1078 U_BOOT_CMD_MKENT(get_parse_edid, 1, 1, do_get_parse_edid, "", ""),
Wenjie Qiao77833902023-12-18 19:01:59 +08001079#ifdef CONFIG_EFUSE_OBJ_API
1080 U_BOOT_CMD_MKENT(efuse, 1, 1, do_efuse_show, "", ""),
1081#endif
xiang.wu1a6d6f1d2023-08-04 14:13:00 +08001082 U_BOOT_CMD_MKENT(pbist, 3, 1, do_pbist, "", ""),
1083 U_BOOT_CMD_MKENT(debug, 3, 1, do_debug, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001084};
1085
1086static int do_hdmitx(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1087{
1088 cmd_tbl_t *c;
1089
1090 if (argc < 2)
1091 return cmd_usage(cmdtp);
1092
1093 argc--;
1094 argv++;
1095
1096 c = find_cmd_tbl(argv[0], &cmd_hdmi_sub[0], ARRAY_SIZE(cmd_hdmi_sub));
1097
1098 if (c)
1099 return c->cmd(cmdtp, flag, argc, argv);
1100 else
1101 return cmd_usage(cmdtp);
1102}
1103
1104U_BOOT_CMD(hdmitx, CONFIG_SYS_MAXARGS, 0, do_hdmitx,
1105 "HDMITX sub-system",
1106 "hdmitx version:20200618\n"
1107 "hdmitx hpd\n"
1108 " Detect hdmi rx plug-in\n"
Wenjie Qiao8a73a562023-02-23 18:37:14 +08001109 "hdmitx output [list | FORMAT | bist PATTERN]\n"
1110 " list: list support formats\n"
1111 " FORMAT can be 720p60/50hz, 1080i60/50hz, 1080p60hz, etc\n"
1112 " extend with 8bits/10bits, y444/y422/y420/rgb\n"
1113 " such as 2160p60hz,10bits,y420\n"
1114 " PATTERN: can be as: line, dot, off, or 1920(width)\n"
1115 "hdmitx blank [0|1]\n"
1116 " 1: output blank 0: output normal\n"
1117 "hdmitx clkmsr\n"
1118 " show hdmitx clocks\n"
1119 "hdmitx off\n"
1120 " Turn off hdmitx output\n"
1121 "hdmitx info\n"
1122 " current mode info\n"
1123 "hdmitx rx_det\n"
1124 " Auto detect if RX is FBC and set outputmode\n"
1125);
1126
1127struct hdr_info *hdmitx_get_rx_hdr_info(void)
1128{
1129 struct hdmitx_dev *hdev = get_hdmitx21_device();
1130
1131 return &hdev->RXCap.hdr_info;
1132}