blob: d749431f9026717020a82f12e74e2e2e6b159ceb [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#ifdef CONFIG_AML_VPP
12#include <amlogic/media/vpp/vpp.h>
lizhi.hu506ddfa2024-07-10 21:35:41 +080013#else
14#define VPP_CM_RGB 0
15#define VPP_CM_YUV 2
16#define VPP_CM_INVALID 0xff
17__weak void vpp_matrix_update(int cfmt) {}
18__weak void vpp_viu2_matrix_update(int cfmt) {}
19__weak void vpp_viu3_matrix_update(int cfmt) {}
Wenjie Qiao8a73a562023-02-23 18:37:14 +080020#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +080021
Wenjie Qiao8a73a562023-02-23 18:37:14 +080022#include <amlogic/media/vout/aml_vout.h>
23#ifdef CONFIG_AML_HDMITX
24#ifdef CONFIG_AML_HDMITX20
25#include <amlogic/media/vout/hdmitx/hdmitx.h>
26#else
27#include <amlogic/media/vout/hdmitx21/hdmitx.h>
28#endif
29#endif
Wenjie Qiao8a73a562023-02-23 18:37:14 +080030#ifdef CONFIG_AML_CVBS
31#include <amlogic/media/vout/aml_cvbs.h>
32#endif
33#ifdef CONFIG_AML_LCD
34#include <amlogic/media/vout/lcd/aml_lcd.h>
35#endif
36
lizhi.hu506ddfa2024-07-10 21:35:41 +080037#ifdef CONFIG_AML_HDMITX
38static int vout_hdmi_hpd(struct hdmitx_dev *hdev, int hpd_st)
39{
Wenjie Qiao8a73a562023-02-23 18:37:14 +080040 char *hdmimode;
41 char *cvbsmode;
42 char *colorattribute;
lizhi.hu506ddfa2024-07-10 21:35:41 +080043 char *connector0_type;
44 int hdmi_enc_idx;
Wenjie Qiao8a73a562023-02-23 18:37:14 +080045
lizhi.hu506ddfa2024-07-10 21:35:41 +080046 /* get hdmi mode and colorattribute from env */
Wenjie Qiao8a73a562023-02-23 18:37:14 +080047 hdmimode = env_get("hdmimode");
48 if (hdmimode)
49 printf("%s: hdmimode=%s\n", __func__, hdmimode);
50
51 colorattribute = env_get("colorattribute");
52 if (colorattribute)
53 printf("%s: colorattribute=%s\n", __func__, colorattribute);
54
lizhi.hu506ddfa2024-07-10 21:35:41 +080055 connector0_type = env_get("connector0_type");
zhou.han57d1d212024-08-15 11:03:54 +080056 if (!connector0_type || !strcmp(connector0_type, "none")) {
57 env_set("connector0_type", "HDMI-A-A");
58 connector0_type = env_get("connector0_type");
59 printf("add default connector for HDMI-A-A\n");
60 } else {
61 printf("%s: connector0_type: %s\n", __func__, connector0_type);
62 }
lizhi.hu506ddfa2024-07-10 21:35:41 +080063
64 /* check whether the current connector is HDMI */
65 hdmi_enc_idx = is_valid_hdmi(connector0_type);
66
67 /*
68 * Check whether the current connector is HDMI or CVBS,
69 * and set a new value for the outputmode based on the HPD status.
70 * In this way, the LCD will not be processed.
71 * if hpd_st high, outputmode and connector0_type will be saved on hdmi side
72 * if hpd_st low, outputmode and connector0_type will be saved on cvbs side
73 */
74 if (hdmi_enc_idx || strcmp(connector0_type, "TV-1") == 0) {
75 if (!hpd_st) {
76 cvbsmode = env_get("cvbsmode");
77 if (cvbsmode)
78 env_set("outputmode", cvbsmode);
79 env_set("hdmichecksum", "0x00000000");
80 env_set("connector0_type", "TV-1");
81 } else {
82 if (!strstr(env_get("outputmode"), "hz"))
83 env_set("outputmode", "1080p60hz");
84 switch (hdev->enc_idx) {
85 case 0:
86 env_set("connector0_type", "HDMI-A-A");
87 break;
88 case 1:
89 env_set("connector0_type", "HDMI-A-B");
90 break;
91 case 2:
92 env_set("connector0_type", "HDMI-A-C");
93 break;
94 }
95 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +080096 }
97
98 return 1;
99}
100
lizhi.hu506ddfa2024-07-10 21:35:41 +0800101static int vout2_hdmi_hpd(struct hdmitx_dev *hdev, int hpd_st)
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800102{
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800103 char *hdmimode;
104 char *cvbsmode;
105 char *colorattribute;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800106 char *connector1_type;
107 int hdmi_enc_idx;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800108
lizhi.hu506ddfa2024-07-10 21:35:41 +0800109 /* get hdmi mode and colorattribute from env */
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800110 hdmimode = env_get("hdmimode");
111 if (hdmimode)
112 printf("%s: hdmimode=%s\n", __func__, hdmimode);
113 colorattribute = env_get("colorattribute");
114 if (colorattribute)
115 printf("%s: colorattribute=%s\n", __func__, colorattribute);
lizhi.hu506ddfa2024-07-10 21:35:41 +0800116
117 connector1_type = env_get("connector1_type");
zhou.han57d1d212024-08-15 11:03:54 +0800118 if (!connector1_type || !strcmp(connector1_type, "none")) {
119 env_set("connector1_type", "HDMI-A-A");
120 connector1_type = env_get("connector1_type");
121 printf("add default connector for HDMI-A-A\n");
122 } else {
123 printf("%s: connector1_type: %s\n", __func__, connector1_type);
124 }
lizhi.hu506ddfa2024-07-10 21:35:41 +0800125
126 /* check whether the current connector is HDMI */
127 hdmi_enc_idx = is_valid_hdmi(connector1_type);
128
129 /*
130 * Check whether the current connector is HDMI or CVBS,
131 * and set a new value for the outputmode2 based on the HPD status.
132 * In this way, the LCD will not be processed.
133 * if hpd_st high, outputmode2 and connector1_type will be saved on hdmi side
134 * if hpd_st low, outputmode2 and connector1_type will be saved on cvbs side
135 */
136 if (hdmi_enc_idx || strcmp(connector1_type, "TV-1") == 0) {
137 if (!hpd_st) {
138 cvbsmode = env_get("cvbsmode");
139 if (cvbsmode)
140 env_set("outputmode2", cvbsmode);
141 env_set("hdmichecksum", "0x00000000");
142 } else {
143 if (!strstr(env_get("outputmode2"), "hz"))
144 env_set("outputmode2", "1080p60hz");
145 switch (hdev->enc_idx) {
146 case 0:
147 env_set("connector1_type", "HDMI-A-A");
148 break;
149 case 1:
150 env_set("connector1_type", "HDMI-A-B");
151 break;
152 case 2:
153 env_set("connector1_type", "HDMI-A-C");
154 break;
155 }
156 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800157 }
158
159 return 0;
160}
161
162int do_hpd_detect(cmd_tbl_t *cmdtp, int flag, int argc,
163 char *const argv[])
164{
165 char *st;
166 int hpd_st = 0;
167 unsigned long i = 0;
Wenjie Qiao4bdbbee2024-02-01 10:16:44 +0800168 /* some TV sets pull hpd high 1.3S after detect pwr5v high */
169 unsigned long hdmitx_hpd_wait_cnt = 15;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800170#ifdef CONFIG_AML_HDMITX20
171 struct hdmitx_dev *hdev = hdmitx_get_hdev();
172#else
173 struct hdmitx_dev *hdev = get_hdmitx21_device();
174#endif
175 int ret = 0;
176
177 st = env_get("hdmitx_hpd_bypass");
178 if (st && (strcmp((const char *)(uintptr_t)st[0], "1") == 0)) {
179 printf("hdmitx_hpd_bypass detect\n");
180 return 0;
181 }
182 st = env_get("hdmitx_hpd_wait_cnt");
183 if (st)
184 hdmitx_hpd_wait_cnt = simple_strtoul(st, NULL, 10);
185 hpd_st = hdev->hwop.get_hpd_state();
186
187 if (!hpd_st) {
188 /* For some TV, they cost extra time to pullup HPD after 5V */
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800189 for (i = 0; i < hdmitx_hpd_wait_cnt; i++) {
190 mdelay(100);
191 hpd_st = hdev->hwop.get_hpd_state();
192 if (hpd_st) {
193 printf("hpd delay %lu ms\n", (i + 1) * 100);
194 break;
195 }
196 }
197 }
198 printf("%s, hpd_state=%d\n", __func__, hpd_st);
199
lizhi.hu506ddfa2024-07-10 21:35:41 +0800200 ret = vout_hdmi_hpd(hdev, hpd_st);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800201 if (!ret)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800202 vout2_hdmi_hpd(hdev, hpd_st);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800203
Wenjie Qiao4bdbbee2024-02-01 10:16:44 +0800204 hdev->hpd_state = hpd_st;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800205 return hpd_st;
206}
207#endif
208
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800209static int do_vout_list(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
210{
lizhi.hu5252a222024-07-31 15:22:29 +0800211 vout_pr_connector_and_vmode();
lizhi.hu506ddfa2024-07-10 21:35:41 +0800212
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800213#ifdef CONFIG_AML_HDMITX
214#ifdef CONFIG_AML_HDMITX20
215 struct hdmitx_dev *hdmitx_device = hdmitx_get_hdev();
216#else
217 struct hdmitx_dev *hdmitx_device = get_hdmitx21_device();
218#endif
219#endif
220
221#ifdef CONFIG_AML_HDMITX
222 if (!hdmitx_device) {
223 printf("\nerror: hdmitx device is null\n");
224 } else {
225 printf("\nvalid hdmi mode:\n");
226 hdmitx_device->hwop.list_support_modes();
227 }
228#endif
229
230#ifdef CONFIG_AML_CVBS
231 printf("\nvalid cvbs mode:\n");
232 cvbs_show_valid_vmode();
233#endif
234
235#ifdef CONFIG_AML_LCD
236 printf("\nvalid lcd mode:\n");
237 aml_lcd_driver_list_support_mode();
238#endif
239
240 return CMD_RET_SUCCESS;
241}
242
lizhi.hu506ddfa2024-07-10 21:35:41 +0800243static int do_vout_prepare(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800244{
lizhi.hu506ddfa2024-07-10 21:35:41 +0800245 unsigned short on_connector_dev = vout_connector_check(0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800246#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800247 char mode[64]; //use stack instead of heap for smp
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800248 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800249
250 memset(mode, 0, 64);
251 sprintf(mode, "%s", argv[1]);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800252#endif
253#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800254 unsigned int venc_index = on_connector_dev & 0xf;
255#endif
256#ifdef CONFIG_AML_HDMITX
257 struct vinfo_s *vinfo = vout_get_current_vinfo();
258 unsigned int fmt_mode = vinfo->vpp_post_out_color_fmt;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800259#endif
260
261 if (argc != 2)
262 return CMD_RET_FAILURE;
263
lizhi.hu506ddfa2024-07-10 21:35:41 +0800264 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
265 case CONNECTOR_DEV_LCD:
266#ifdef CONFIG_AML_LCD
267 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
268 venc_sel = mux_sel & 0xf;
269 if (venc_sel != VIU_MUX_ENCL)
270 break;
271 vout_viu_mux(VOUT_VIU1_SEL, VIU_MUX_ENCL | venc_index << 4);
272 vpp_matrix_update(VPP_CM_RGB);
273 aml_lcd_driver_prepare(venc_index, mode);
274 return CMD_RET_SUCCESS;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800275#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800276 break;
277 case CONNECTOR_DEV_HDMI:
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800278#ifdef CONFIG_AML_HDMITX
lizhi.hu506ddfa2024-07-10 21:35:41 +0800279 mux_sel = hdmi_outputmode_check(mode, 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800280 venc_sel = mux_sel & 0xf;
281 if (venc_sel < VIU_MUX_MAX) {
282 vout_viu_mux(VOUT_VIU1_SEL, mux_sel);
lizhi.hu506ddfa2024-07-10 21:35:41 +0800283 if (fmt_mode == 1)
284 vpp_matrix_update(VPP_CM_RGB);
285 else
286 vpp_matrix_update(VPP_CM_YUV);
287 return CMD_RET_SUCCESS;
288 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800289#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800290 break;
291 case CONNECTOR_DEV_CVBS:
292#ifdef CONFIG_AML_CVBS
293 mux_sel = cvbs_outputmode_check(mode);
294 venc_sel = mux_sel & 0xf;
295 if (venc_sel == VIU_MUX_ENCI) {
296 vout_viu_mux(VOUT_VIU1_SEL, mux_sel);
297 vpp_matrix_update(VPP_CM_YUV);
298 return CMD_RET_SUCCESS;
299 }
300#endif
301 break;
302 default:
303 break;
304 }
305 printf("VOUT: output prepare fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800306 vout_pr_connector_and_vmode();
lizhi.hu506ddfa2024-07-10 21:35:41 +0800307 return CMD_RET_FAILURE;
308}
309
310static int do_vout_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
311{
312 unsigned short on_connector_dev = vout_connector_check(0);
313#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
314 char mode[64]; //use stack instead of heap for smp
315 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
316
317 memset(mode, 0, 64);
318 sprintf(mode, "%s", argv[1]);
319#endif
320#ifdef CONFIG_AML_LCD
321 unsigned int venc_index = on_connector_dev & 0xf;
322#endif
323#ifdef CONFIG_AML_HDMITX
324 struct vinfo_s *vinfo = vout_get_current_vinfo();
325 unsigned int fmt_mode = vinfo->vpp_post_out_color_fmt;
326 char str[64];
327#endif
328
329 if (argc != 2)
330 return CMD_RET_FAILURE;
331
332 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
333 case CONNECTOR_DEV_LCD:
334#ifdef CONFIG_AML_LCD
335 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
336 venc_sel = mux_sel & 0xf;
337 if (venc_sel != VIU_MUX_ENCL)
338 break;
339 vout_viu_mux(VOUT_VIU1_SEL, VIU_MUX_ENCL | venc_index << 4);
340 vpp_matrix_update(VPP_CM_RGB);
341 aml_lcd_driver_enable(venc_index, mode);
342 run_command("setenv vout_init enable", 0);
343 return CMD_RET_SUCCESS;
344#endif
345 break;
346 case CONNECTOR_DEV_HDMI:
347#ifdef CONFIG_AML_HDMITX
348 mux_sel = hdmi_outputmode_check(mode, 0);
349 venc_sel = mux_sel & 0xf;
350 if (venc_sel < VIU_MUX_MAX) {
351 vout_viu_mux(VOUT_VIU1_SEL, mux_sel);
352 if (fmt_mode == 1)
353 vpp_matrix_update(VPP_CM_RGB);
354 else
355 vpp_matrix_update(VPP_CM_YUV);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800356 memset(str, 0, sizeof(str));
357 sprintf(str, "hdmitx output %s", mode);
358 if (run_command(str, 0) == CMD_RET_SUCCESS)
359 run_command("setenv vout_init enable", 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800360 return CMD_RET_SUCCESS;
361 }
lizhi.hu506ddfa2024-07-10 21:35:41 +0800362#endif
363 break;
364 case CONNECTOR_DEV_CVBS:
365#ifdef CONFIG_AML_CVBS
366 mux_sel = cvbs_outputmode_check(mode);
367 venc_sel = mux_sel & 0xf;
368 if (venc_sel == VIU_MUX_ENCI) {
369 vout_viu_mux(VOUT_VIU1_SEL, mux_sel);
370 vpp_matrix_update(VPP_CM_YUV);
371 if (cvbs_set_vmode(mode) == 0) {
372 run_command("setenv vout_init enable", 0);
373 return CMD_RET_SUCCESS;
374 }
375 }
376#endif
377 break;
378 default:
379 break;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800380 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800381
lizhi.hu506ddfa2024-07-10 21:35:41 +0800382 printf("VOUT: output fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800383 vout_pr_connector_and_vmode();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800384 return CMD_RET_FAILURE;
385}
386
387static int do_vout2_list(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
388{
lizhi.hu5252a222024-07-31 15:22:29 +0800389 vout_pr_connector_and_vmode();
lizhi.hu506ddfa2024-07-10 21:35:41 +0800390
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800391#ifdef CONFIG_AML_HDMITX
392#ifdef CONFIG_AML_HDMITX20
393 struct hdmitx_dev *hdmitx_device = hdmitx_get_hdev();
394#else
395 struct hdmitx_dev *hdmitx_device = get_hdmitx21_device();
396#endif
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800397
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800398 if (!hdmitx_device) {
399 printf("\nerror: hdmitx device is null\n");
400 } else {
401 printf("\nvalid hdmi mode:\n");
402 hdmitx_device->hwop.list_support_modes();
403 }
404#endif
405
406#ifdef CONFIG_AML_CVBS
407 printf("\nvalid cvbs mode:\n");
408 cvbs_show_valid_vmode();
409#endif
410
411#ifdef CONFIG_AML_LCD
412 printf("\nvalid lcd mode:\n");
413 aml_lcd_driver_list_support_mode();
414#endif
415
416 return CMD_RET_SUCCESS;
417}
418
419static int do_vout2_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
420{
lizhi.hu506ddfa2024-07-10 21:35:41 +0800421 unsigned short on_connector_dev = vout_connector_check(1);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800422#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800423 char mode[64]; //use stack instead of heap for smp
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800424 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800425
426 memset(mode, 0, 64);
427 sprintf(mode, "%s", argv[1]);
428#endif
429#ifdef CONFIG_AML_LCD
430 unsigned int venc_index = on_connector_dev & 0xf;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800431#endif
432#ifdef CONFIG_AML_HDMITX
433 char str[64];
434#endif
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800435
436 if (argc != 2)
437 return CMD_RET_FAILURE;
438
lizhi.hu506ddfa2024-07-10 21:35:41 +0800439 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
440 case CONNECTOR_DEV_LCD:
441#ifdef CONFIG_AML_LCD
442 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
443 venc_sel = mux_sel & 0xf;
444 if (venc_sel != VIU_MUX_ENCL)
445 break;
446 aml_lcd_driver_enable(venc_index, mode);
447 run_command("setenv vout2_init enable", 0);
448 return CMD_RET_SUCCESS;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800449#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800450 break;
451 case CONNECTOR_DEV_HDMI:
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800452#ifdef CONFIG_AML_HDMITX
lizhi.hu506ddfa2024-07-10 21:35:41 +0800453 mux_sel = hdmi_outputmode_check(mode, 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800454 venc_sel = mux_sel & 0xf;
455 if (venc_sel < VIU_MUX_MAX) {
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800456 memset(str, 0, sizeof(str));
457 sprintf(str, "hdmitx output %s", mode);
458 run_command(str, 0);
lizhi.hu506ddfa2024-07-10 21:35:41 +0800459 run_command("setenv vout2_init enable", 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800460 return CMD_RET_SUCCESS;
461 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800462#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800463 break;
464 case CONNECTOR_DEV_CVBS:
465#ifdef CONFIG_AML_CVBS
466 mux_sel = cvbs_outputmode_check(mode);
467 venc_sel = mux_sel & 0xf;
468 if (venc_sel == VIU_MUX_ENCI) {
469 if (cvbs_set_vmode(mode) == 0) {
470 run_command("setenv vout2_init enable", 0);
471 return CMD_RET_SUCCESS;
472 }
473 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800474#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800475 break;
476 default:
477 break;
478 }
479 printf("VOUT2: output fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800480 vout_pr_connector_and_vmode();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800481 return CMD_RET_FAILURE;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800482
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800483}
484
485static int do_vout2_prepare(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
486{
lizhi.hu506ddfa2024-07-10 21:35:41 +0800487 unsigned short on_connector_dev = vout_connector_check(1);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800488#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800489 char mode[64]; //use stack instead of heap for smp
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800490 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800491
492 memset(mode, 0, 64);
493 sprintf(mode, "%s", argv[1]);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800494#endif
495#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800496 unsigned int venc_index = on_connector_dev & 0xf;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800497#endif
498
499 if (argc != 2)
500 return CMD_RET_FAILURE;
501
lizhi.hu506ddfa2024-07-10 21:35:41 +0800502 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
503 case CONNECTOR_DEV_LCD:
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800504#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800505 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
506 venc_sel = mux_sel & 0xf;
507 if (venc_sel != VIU_MUX_ENCL)
508 break;
509 vout_viu_mux(VOUT_VIU2_SEL, VIU_MUX_ENCL | venc_index << 4);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800510 vpp_viu2_matrix_update(VPP_CM_RGB);
lizhi.hu506ddfa2024-07-10 21:35:41 +0800511 aml_lcd_driver_prepare(venc_index, mode);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800512 return CMD_RET_SUCCESS;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800513#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800514 break;
515 case CONNECTOR_DEV_HDMI:
516#ifdef CONFIG_AML_HDMITX
517 mux_sel = hdmi_outputmode_check(mode, 0);
518 venc_sel = mux_sel & 0xf;
519 if (venc_sel < VIU_MUX_MAX) {
520 vout_viu_mux(VOUT_VIU2_SEL, mux_sel);
521 vpp_viu2_matrix_update(VPP_CM_YUV);
522 return CMD_RET_SUCCESS;
523 }
524#endif
525 break;
526 case CONNECTOR_DEV_CVBS:
527#ifdef CONFIG_AML_CVBS
528 mux_sel = cvbs_outputmode_check(mode);
529 venc_sel = mux_sel & 0xf;
530 if (venc_sel == VIU_MUX_ENCI) {
531 vout_viu_mux(VOUT_VIU2_SEL, mux_sel);
532 vpp_viu2_matrix_update(VPP_CM_YUV);
533 return CMD_RET_SUCCESS;
534 }
535#endif
536 break;
537 default:
538 break;
539 }
540 printf("VOUT2: output prepare fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800541 vout_pr_connector_and_vmode();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800542 return CMD_RET_FAILURE;
543}
544
545static int do_vout3_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
546{
lizhi.hu5252a222024-07-31 15:22:29 +0800547 vout_pr_connector_and_vmode();
lizhi.hu506ddfa2024-07-10 21:35:41 +0800548
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800549#ifdef CONFIG_AML_HDMITX
550#ifdef CONFIG_AML_HDMITX20
551 struct hdmitx_dev *hdmitx_device = hdmitx_get_hdev();
552#else
553 struct hdmitx_dev *hdmitx_device = get_hdmitx21_device();
554#endif
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800555
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800556 if (!hdmitx_device) {
557 printf("\nerror: hdmitx device is null\n");
558 } else {
559 printf("\nvalid hdmi mode:\n");
560 hdmitx_device->hwop.list_support_modes();
561 }
562#endif
563
564#ifdef CONFIG_AML_CVBS
565 printf("\nvalid cvbs mode:\n");
566 cvbs_show_valid_vmode();
567#endif
568
569#ifdef CONFIG_AML_LCD
570 printf("\nvalid lcd mode:\n");
571 aml_lcd_driver_list_support_mode();
572#endif
573
574 return CMD_RET_SUCCESS;
575}
576
577static int do_vout3_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
578{
lizhi.hu506ddfa2024-07-10 21:35:41 +0800579 unsigned short on_connector_dev = vout_connector_check(2);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800580#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800581 char mode[64]; //use stack instead of heap for smp
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800582 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800583
584 memset(mode, 0, 64);
585 sprintf(mode, "%s", argv[1]);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800586#endif
587#ifdef CONFIG_AML_HDMITX
588 char str[64];
589#endif
590#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800591 unsigned int venc_index = on_connector_dev & 0xf;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800592#endif
593
594 if (argc != 2)
595 return CMD_RET_FAILURE;
596
lizhi.hu506ddfa2024-07-10 21:35:41 +0800597 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
598 case CONNECTOR_DEV_LCD:
599#ifdef CONFIG_AML_LCD
600 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
601 venc_sel = mux_sel & 0xf;
602 if (venc_sel != VIU_MUX_ENCL)
603 break;
604 aml_lcd_driver_enable(venc_index, mode);
605 run_command("setenv vout3_init enable", 0);
606 return CMD_RET_SUCCESS;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800607#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800608 break;
609 case CONNECTOR_DEV_HDMI:
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800610#ifdef CONFIG_AML_HDMITX
lizhi.hu506ddfa2024-07-10 21:35:41 +0800611 mux_sel = hdmi_outputmode_check(mode, 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800612 venc_sel = mux_sel & 0xf;
613 if (venc_sel < VIU_MUX_MAX) {
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800614 memset(str, 0, sizeof(str));
615 sprintf(str, "hdmitx output %s", mode);
616 run_command(str, 0);
lizhi.hu506ddfa2024-07-10 21:35:41 +0800617 run_command("setenv vout3_init enable", 0);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800618 return CMD_RET_SUCCESS;
619 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800620#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800621 break;
622 case CONNECTOR_DEV_CVBS:
623#ifdef CONFIG_AML_CVBS
624 mux_sel = cvbs_outputmode_check(mode);
625 venc_sel = mux_sel & 0xf;
626 if (venc_sel == VIU_MUX_ENCI) {
627 if (cvbs_set_vmode(mode) == 0) {
628 run_command("setenv vout3_init enable", 0);
629 return CMD_RET_SUCCESS;
630 }
631 }
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800632#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800633 break;
634 default:
635 break;
636 }
637 printf("VOUT3: output fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800638 vout_pr_connector_and_vmode();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800639 return CMD_RET_FAILURE;
640}
641
642static int do_vout3_prepare(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
643{
lizhi.hu506ddfa2024-07-10 21:35:41 +0800644 unsigned short on_connector_dev = vout_connector_check(2);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800645#if defined(CONFIG_AML_CVBS) || defined(CONFIG_AML_HDMITX) || defined(CONFIG_AML_LCD)
lizhi.hu506ddfa2024-07-10 21:35:41 +0800646 char mode[64]; //use stack instead of heap for smp
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800647 unsigned int mux_sel = VIU_MUX_MAX, venc_sel = VIU_MUX_MAX;
lizhi.hu506ddfa2024-07-10 21:35:41 +0800648
649 memset(mode, 0, (sizeof(char) * 64));
650 sprintf(mode, "%s", argv[1]);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800651#endif
652#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800653 unsigned int venc_index = on_connector_dev & 0xf;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800654#endif
655
656 if (argc != 2)
657 return CMD_RET_FAILURE;
658
lizhi.hu506ddfa2024-07-10 21:35:41 +0800659 switch (on_connector_dev & CONNECTOR_DEV_MASK) {
660 case CONNECTOR_DEV_LCD:
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800661#ifdef CONFIG_AML_LCD
lizhi.hu506ddfa2024-07-10 21:35:41 +0800662 mux_sel = aml_lcd_driver_outputmode_check(venc_index, mode);
663 venc_sel = mux_sel & 0xf;
664 if (venc_sel != VIU_MUX_ENCL)
665 break;
666 vout_viu_mux(VOUT_VIU3_SEL, VIU_MUX_ENCL | venc_index << 4);
667 vpp_viu3_matrix_update(VPP_CM_RGB);
668 aml_lcd_driver_prepare(venc_index, mode);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800669 return CMD_RET_SUCCESS;
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800670#endif
lizhi.hu506ddfa2024-07-10 21:35:41 +0800671 break;
672 case CONNECTOR_DEV_HDMI:
673#ifdef CONFIG_AML_HDMITX
674 mux_sel = hdmi_outputmode_check(mode, 0);
675 venc_sel = mux_sel & 0xf;
676 if (venc_sel < VIU_MUX_MAX) {
677 vout_viu_mux(VOUT_VIU3_SEL, mux_sel);
678 vpp_viu3_matrix_update(VPP_CM_YUV);
679 return CMD_RET_SUCCESS;
680 }
681#endif
682 break;
683 case CONNECTOR_DEV_CVBS:
684#ifdef CONFIG_AML_CVBS
685 mux_sel = cvbs_outputmode_check(mode);
686 venc_sel = mux_sel & 0xf;
687 if (venc_sel == VIU_MUX_ENCI) {
688 vout_viu_mux(VOUT_VIU3_SEL, mux_sel);
689 vpp_viu3_matrix_update(VPP_CM_YUV);
690 return CMD_RET_SUCCESS;
691 }
692#endif
693 break;
694 default:
695 break;
696 }
697 printf("VOUT3: output prepare fail(0x%04x)\n", on_connector_dev);
lizhi.hu5252a222024-07-31 15:22:29 +0800698 vout_pr_connector_and_vmode();
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800699 return CMD_RET_FAILURE;
700}
701
702static int do_vout_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
703{
704 vout_vinfo_dump();
705
706 return CMD_RET_SUCCESS;
707}
708
lizhi.hu506ddfa2024-07-10 21:35:41 +0800709#define VOUT_HELPER_STRING \
710 "vout/vout2/vout3 [list | output format | info]\n" \
711 " list : list for valid video mode names\n" \
712 " prepare : prepare\n" \
713 " format : perfered output video mode\n" \
714 " info : dump vinfo\n"
715
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800716static cmd_tbl_t cmd_vout_sub[] = {
lizhi.hu506ddfa2024-07-10 21:35:41 +0800717 U_BOOT_CMD_MKENT(list, 1, 1, do_vout_list, "", ""),
718 U_BOOT_CMD_MKENT(prepare, 3, 1, do_vout_prepare, "", ""),
719 U_BOOT_CMD_MKENT(output, 3, 1, do_vout_output, "", ""),
720 U_BOOT_CMD_MKENT(info, 1, 1, do_vout_info, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800721};
722
723static int do_vout(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
724{
725 cmd_tbl_t *c;
726
727 if (argc < 2)
728 return cmd_usage(cmdtp);
729
730 argc--;
731 argv++;
732
733 c = find_cmd_tbl(argv[0], &cmd_vout_sub[0], ARRAY_SIZE(cmd_vout_sub));
734
735 if (c)
736 return c->cmd(cmdtp, flag, argc, argv);
737 else
738 return cmd_usage(cmdtp);
739}
740
lizhi.hu506ddfa2024-07-10 21:35:41 +0800741U_BOOT_CMD(vout, CONFIG_SYS_MAXARGS, 1, do_vout, "VOUT sub-system", VOUT_HELPER_STRING);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800742
743static cmd_tbl_t cmd_vout2_sub[] = {
lizhi.hu506ddfa2024-07-10 21:35:41 +0800744 U_BOOT_CMD_MKENT(list, 1, 1, do_vout2_list, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800745 U_BOOT_CMD_MKENT(prepare, 3, 1, do_vout2_prepare, "", ""),
lizhi.hu506ddfa2024-07-10 21:35:41 +0800746 U_BOOT_CMD_MKENT(output, 3, 1, do_vout2_output, "", ""),
747 U_BOOT_CMD_MKENT(info, 1, 1, do_vout_info, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800748};
749
750static int do_vout2(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
751{
752 cmd_tbl_t *c;
753
754 if (argc < 2)
755 return cmd_usage(cmdtp);
756
757 argc--;
758 argv++;
759
760 c = find_cmd_tbl(argv[0], &cmd_vout2_sub[0], ARRAY_SIZE(cmd_vout2_sub));
761
762 if (c)
763 return c->cmd(cmdtp, flag, argc, argv);
764 else
765 return cmd_usage(cmdtp);
766}
767
lizhi.hu506ddfa2024-07-10 21:35:41 +0800768U_BOOT_CMD(vout2, CONFIG_SYS_MAXARGS, 1, do_vout2, "VOUT2 sub-system", VOUT_HELPER_STRING);
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800769
770static cmd_tbl_t cmd_vout3_sub[] = {
lizhi.hu506ddfa2024-07-10 21:35:41 +0800771 U_BOOT_CMD_MKENT(list, 1, 1, do_vout3_list, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800772 U_BOOT_CMD_MKENT(prepare, 3, 1, do_vout3_prepare, "", ""),
lizhi.hu506ddfa2024-07-10 21:35:41 +0800773 U_BOOT_CMD_MKENT(output, 3, 1, do_vout3_output, "", ""),
774 U_BOOT_CMD_MKENT(info, 1, 1, do_vout_info, "", ""),
Wenjie Qiao8a73a562023-02-23 18:37:14 +0800775};
776
777static int do_vout3(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
778{
779 cmd_tbl_t *c;
780
781 if (argc < 2)
782 return cmd_usage(cmdtp);
783
784 argc--;
785 argv++;
786
787 c = find_cmd_tbl(argv[0], &cmd_vout3_sub[0], ARRAY_SIZE(cmd_vout3_sub));
788
789 if (c)
790 return c->cmd(cmdtp, flag, argc, argv);
791 else
792 return cmd_usage(cmdtp);
793}
794
lizhi.hu506ddfa2024-07-10 21:35:41 +0800795U_BOOT_CMD(vout3, CONFIG_SYS_MAXARGS, 1, do_vout3, "VOUT3 sub-system", VOUT_HELPER_STRING);