1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * 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, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include <common.h>
20 #include <command.h>
21 #include "hi3519av100_vo.h"
22
23 #define CMD_VO_ARGS_BASE10 10
24 #define CMD_VO_ARGS_BASE16 16
25 #define CMD_VO_ARGS_BASE_ALL 0
26
27 extern int set_vobg(unsigned int dev, unsigned int rgb);
28 extern int start_vo(unsigned int dev, unsigned int type, unsigned int sync);
29 extern int stop_vo(unsigned int dev);
30 extern int start_videolayer(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect layer_rect);
31 extern int stop_videolayer(unsigned int layer);
32
33 extern int hdmi_display(unsigned int vosync, unsigned int input, unsigned int output);
34 extern void hdmi_stop(void);
35
36 extern int mipi_tx_display(unsigned int vosync);
37 extern int mipi_tx_stop(void);
38
39 extern int start_gx(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect gx_rect);
40 extern int stop_gx(unsigned int layer);
41
42 #define VO_DEV_MAX_NUM 3
43 static unsigned int g_a_interface_type[VO_DEV_MAX_NUM] = {[0 ... (VO_DEV_MAX_NUM - 1)] = 0};
44
check_vo_support(unsigned int dev,unsigned int type,unsigned int sync)45 static int check_vo_support(unsigned int dev, unsigned int type, unsigned int sync)
46 {
47 /* check interface type, ONLY VGA & HDMI interface is supported. */
48 if (dev == VO_DEV_DHD0) {
49 if ((type & ~(VO_INTF_HDMI | VO_INTF_BT1120 | VO_INTF_BT656 | VO_INTF_MIPI | VO_INTF_MIPI_SLAVE)) ||
50 (type == 0)) {
51 printf("hd%u only supports HDMI, BT.656, BT.1120, mipi_tx intftype, intf %u is illegal!\n", dev, type);
52 return -1;
53 }
54 /* just one interface at the the time for a dev. */
55 if (type & ~(VO_INTF_HDMI | VO_INTF_BT1120) &&
56 (type & ~(VO_INTF_HDMI | VO_INTF_MIPI)) &&
57 (type & ~VO_INTF_BT656) &&
58 (type & ~VO_INTF_MIPI_SLAVE)) {
59 printf("for VO %u, only HDMI and BT.1120 can be used at the same time!\n", dev);
60 return -1;
61 }
62 } else if (dev == VO_DEV_DHD1) {
63 if ((type
64 & ~(VO_INTF_BT1120 | VO_INTF_BT656 | VO_INTF_MIPI |
65 VO_INTF_MIPI_SLAVE | VO_INTF_LCD_6BIT | VO_INTF_LCD_8BIT |
66 VO_INTF_LCD_16BIT | VO_INTF_LCD_18BIT | VO_INTF_LCD_24BIT)) ||
67 (type == 0)) {
68 printf("hd%u only supports BT.656, BT.1120, mipi_tx, LCD intftype, intf %u is illegal!\n", dev, type);
69 return -1;
70 }
71 /* just one interface at the the time for a dev. */
72 if (
73 (type & ~VO_INTF_BT1120) && (type & ~VO_INTF_BT656) &&
74 (type & ~VO_INTF_MIPI) && (type & ~VO_INTF_MIPI_SLAVE) &&
75 (type & ~VO_INTF_LCD_6BIT) && (type & ~VO_INTF_LCD_8BIT) &&
76 (type & ~VO_INTF_LCD_16BIT) && (type & ~VO_INTF_LCD_18BIT) &&
77 (type & ~VO_INTF_LCD_24BIT)
78 ) {
79 printf("vo(%u), none of (BT.1120,BT.656,MIPI,LCD) can use at the same time!\n", dev);
80 return -1;
81 }
82 } else {
83 printf("unknow dev(%u)!\n", dev);
84 return -1;
85 }
86
87 if (VO_INTF_HDMI & type) {
88 if (!(((sync >= VO_OUTPUT_1080P24) && (sync <= VO_OUTPUT_640x480_60)) ||
89 ((sync >= VO_OUTPUT_1920x2160_30) && (sync <= VO_OUTPUT_4096x2160_60)))) {
90 printf("vo%u's intfsync %u illegal!\n", dev, sync);
91 return -1;
92 }
93 }
94
95 if (VO_INTF_BT1120 & type) {
96 if ((sync < VO_OUTPUT_1080P24) ||
97 (sync > VO_OUTPUT_7680x4320_30)) {
98 printf("vo%u's intfsync %u illegal!\n", dev, sync);
99 return -1;
100 }
101 }
102
103 if ((VO_INTF_MIPI & type) || (VO_INTF_MIPI_SLAVE & type)) {
104 if (dev == VO_DEV_DHD0) {
105 if ((sync != VO_OUTPUT_576P50) &&
106 (sync != VO_OUTPUT_720P50) &&
107 (sync != VO_OUTPUT_720P60) &&
108 (sync != VO_OUTPUT_1024x768_60) &&
109 (sync != VO_OUTPUT_1280x1024_60) &&
110 (sync != VO_OUTPUT_720x1280_60) &&
111 (sync != VO_OUTPUT_1080x1920_60) &&
112 (sync != VO_OUTPUT_1080P60) &&
113 (sync != VO_OUTPUT_3840x2160_30) &&
114 (sync != VO_OUTPUT_3840x2160_60)) {
115 printf("for MIPI(mipi_tx) intface, vo%u's intfsync %u illegal!\n", dev, sync);
116 return -1;
117 }
118 } else if (dev == VO_DEV_DHD1) {
119 if ((sync != VO_OUTPUT_576P50) &&
120 (sync != VO_OUTPUT_720P50) &&
121 (sync != VO_OUTPUT_720P60) &&
122 (sync != VO_OUTPUT_1024x768_60) &&
123 (sync != VO_OUTPUT_1280x1024_60) &&
124 (sync != VO_OUTPUT_720x1280_60) &&
125 (sync != VO_OUTPUT_1080x1920_60) &&
126 (sync != VO_OUTPUT_1080P60)) {
127 printf("for MIPI(mipi_tx) intface, vo%u's intfsync %u illegal! \n", dev, sync);
128 return -1;
129 }
130 }
131 }
132
133 if (type == (VO_INTF_HDMI | VO_INTF_MIPI)) {
134 if ((sync == VO_OUTPUT_576P50) ||
135 (sync == VO_OUTPUT_1024x768_60)) {
136 printf("when HDMI+MIPI, not support 576P50 or 1024x768_60\n");
137 return -1;
138 }
139 }
140
141 return 0;
142 }
143
do_vobg(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])144 static int do_vobg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
145 {
146 unsigned int dev, rgb;
147
148 if (argc < 3) {
149 printf("insufficient parameter!\n");
150 printf ("usage:\n%s\n", cmdtp->usage);
151 return -1;
152 }
153
154 dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
155 rgb = (unsigned int)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE_ALL);
156 if (dev >= VO_DEV_BUTT) {
157 printf("invalid parameter!\n");
158 return -1;
159 }
160
161 set_vobg(dev, rgb);
162
163 printf("dev %u set background color!\n", dev);
164
165 return 0;
166 }
167
do_startvo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])168 static int do_startvo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
169 {
170 unsigned int dev, intftype, sync;
171
172 if (argc < 4) {
173 printf("insufficient parameter!\n");
174 printf ("usage:\n%s\n", cmdtp->usage);
175 return -1;
176 }
177
178 dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
179 intftype = (unsigned int)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE10);
180 sync = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10);
181 if ((dev >= VO_DEV_BUTT) || (sync >= VO_OUTPUT_BUTT)) {
182 printf("invalid parameter!\n");
183 return -1;
184 }
185
186 if (check_vo_support(dev, intftype, sync)) {
187 printf("unsupport parameter!\n");
188 return -1;
189 }
190
191 start_vo(dev, intftype, sync);
192
193 g_a_interface_type[dev] = intftype;
194
195 if (intftype & VO_INTF_HDMI) {
196 if (intftype == (VO_INTF_HDMI | VO_INTF_MIPI)) {
197 hdmi_display(sync, 0, 2);
198 } else {
199 hdmi_display(sync, 2, 2);
200 }
201 }
202
203 if (intftype & VO_INTF_MIPI) {
204 /* to call mipi_display. */
205 mipi_tx_display(sync);
206 }
207
208 printf("dev %u opened!\n", dev);
209
210 return 0;
211 }
212
do_stopvo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])213 static int do_stopvo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
214 {
215 unsigned int dev;
216 if (argc < 2) {
217 printf("insufficient parameter!\n");
218 printf ("usage:\n%s\n", cmdtp->usage);
219 return -1;
220 }
221
222 dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
223 if (dev >= VO_DEV_BUTT) {
224 printf("invalid parameter!\n");
225 return -1;
226 }
227
228 if (g_a_interface_type[dev] & VO_INTF_HDMI) {
229 g_a_interface_type[dev] = 0;
230 hdmi_stop();
231 }
232
233 if (g_a_interface_type[dev] & VO_INTF_MIPI) {
234 mipi_tx_stop();
235 }
236
237 stop_vo(dev);
238
239 printf("dev %u closed!\n", dev);
240
241 return 0;
242 }
243
do_startvl(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])244 static int do_startvl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
245 {
246 unsigned int layer, strd, x, y, w, h;
247 unsigned long addr;
248 hi_vo_rect layer_rect;
249 int max_x, max_y, layer_max_w, layer_max_h;
250
251 if (argc < 8) {
252 printf("insufficient parameter!\n");
253 printf ("usage:\n%s\n", cmdtp->usage);
254 return -1;
255 }
256
257 layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
258 addr = (unsigned long)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE16);
259 strd = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10);
260 x = (unsigned int)simple_strtoul(argv[4], NULL, CMD_VO_ARGS_BASE10);
261 y = (unsigned int)simple_strtoul(argv[5], NULL, CMD_VO_ARGS_BASE10);
262 w = (unsigned int)simple_strtoul(argv[6], NULL, CMD_VO_ARGS_BASE10);
263 h = (unsigned int)simple_strtoul(argv[7], NULL, CMD_VO_ARGS_BASE10);
264
265 if (layer == VO_LAYER_VHD0) {
266 max_x = VHD0_PIC_MAX_WIDTH;
267 max_y = VHD0_PIC_MAX_HEIGHT;
268 layer_max_w = VHD0_PIC_MAX_WIDTH;
269 layer_max_h = VHD0_PIC_MAX_HEIGHT;
270 } else if (layer == VO_LAYER_VHD1) {
271 max_x =VHD1_PIC_MAX_WIDTH;
272 max_y = VHD1_PIC_MAX_HEIGHT;
273 layer_max_w = VHD1_PIC_MAX_WIDTH;
274 layer_max_h = VHD1_PIC_MAX_HEIGHT;
275 } else {
276 printf("invalid parameter!\n");
277 return -1;
278 }
279
280 if((strd > (layer_max_w * 2)) ||
281 (x > max_x) || (x & 0x1) ||
282 (y > max_y) || (y & 0x1) ||
283 (w > layer_max_w) || (w & 0x1) || (w < PIC_MIN_LENTH) ||
284 (h > layer_max_h) || (h & 0x1) || (h < PIC_MIN_LENTH)) {
285 printf("invalid parameter!\n");
286 return -1;
287 }
288
289
290 layer_rect.x = x;
291 layer_rect.y = y;
292 layer_rect.w = w;
293 layer_rect.h = h;
294
295 start_videolayer(layer, addr, strd, layer_rect);
296
297 printf("video layer %u opened!\n", layer);
298
299 return 0;
300 }
301
do_stopvl(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])302 static int do_stopvl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
303 {
304 unsigned int layer;
305
306 if (argc < 2) {
307 printf("insufficient parameter!\n");
308 printf ("usage:\n%s\n", cmdtp->usage);
309 return -1;
310 }
311
312 layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
313
314 if ((layer > VO_LAYER_VSD0) || (layer == VO_LAYER_VP)) {
315 printf("invalid parameter!\n");
316 return -1;
317 }
318
319 stop_videolayer(layer);
320
321 printf("video layer %u closed!\n", layer);
322
323 return 0;
324 }
325
do_startgx(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])326 static int do_startgx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
327 {
328 unsigned int layer, strd, x, y, w, h;
329 unsigned long addr;
330 hi_vo_rect gx_rect;
331 int max_x, max_y, layer_max_w, layer_max_h;
332 if (argc < 8) {
333 printf("insufficient parameter!\n");
334 printf ("usage:\n%s\n", cmdtp->usage);
335 return -1;
336 }
337
338 layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
339 addr = (unsigned long)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE16);
340 strd = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10);
341 x = (unsigned int)simple_strtoul(argv[4], NULL, CMD_VO_ARGS_BASE10);
342 y = (unsigned int)simple_strtoul(argv[5], NULL, CMD_VO_ARGS_BASE10);
343 w = (unsigned int)simple_strtoul(argv[6], NULL, CMD_VO_ARGS_BASE10);
344 h = (unsigned int)simple_strtoul(argv[7], NULL, CMD_VO_ARGS_BASE10);
345
346 if (layer == VO_GRAPHC_G0) {
347 max_x =GFX0_PIC_MAX_WIDTH;
348 max_y = GFX0_PIC_MAX_HEIGHT;
349 layer_max_w = GFX0_PIC_MAX_WIDTH;
350 layer_max_h = GFX0_PIC_MAX_HEIGHT;
351 } else if (layer == VO_GRAPHC_G1) {
352 max_x =GFX1_PIC_MAX_WIDTH;
353 max_y = GFX1_PIC_MAX_HEIGHT;
354 layer_max_w = GFX1_PIC_MAX_WIDTH;
355 layer_max_h = GFX1_PIC_MAX_HEIGHT;
356 } else {
357 printf("invalid parameter!\n");
358 return -1;
359 }
360
361 if((strd > (layer_max_w * 2)) ||
362 (x > max_x) || (x & 0x1) ||
363 (y > max_y) || (y & 0x1) ||
364 (w > layer_max_w) || (w & 0x1) || (w < PIC_MIN_LENTH) ||
365 (h > layer_max_h) || (h & 0x1) || (h < PIC_MIN_LENTH)) {
366 printf("invalid parameter!\n");
367 return -1;
368 }
369
370 gx_rect.x = x;
371 gx_rect.y = y;
372 gx_rect.w = w;
373 gx_rect.h = h;
374
375 start_gx(layer, addr, strd, gx_rect);
376
377 printf("graphic layer %u opened!\n", layer);
378
379 return 0;
380 }
381
do_stopgx(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])382 static int do_stopgx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
383 {
384 unsigned int layer;
385
386 if (argc < 2) {
387 printf("insufficient parameter!\n");
388 printf ("usage:\n%s\n", cmdtp->usage);
389 return -1;
390 }
391
392 layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10);
393
394 if (layer >= VO_GRAPHC_BUTT) {
395 printf("invalid parameter!\n");
396 return -1;
397 }
398
399 stop_gx(layer);
400
401 printf("graphic layer %u closed!\n", layer);
402
403 return 0;
404 }
405
406 U_BOOT_CMD(
407 startvo, CFG_MAXARGS, 1, do_startvo,
408 "startvo - open vo device with a certain output interface.\n"
409 "\t- startvo [dev intftype sync]",
410 "\nargs: [dev, intftype, sync]\n"
411 "\t-<dev> : 0: DHD0,1: DHD1\n"
412 "\t-<intftype>: 8(BT.656),16(BT.1120),32(HDMI),16384(mipi_tx)\n"
413 "\t-<sync>: typical value:\n"
414 "\t\t0(PAL), 1(NTSC), 4(1080P30), 6(720P60)\n"
415 "\t\t10(1080P60), 21(1920x1200), 26(2560x1440_30),31(3840x2160_30)\n"
416 "\t\t33(3840x2160_60),45(1080x1920_60),47(user)\n");
417
418 U_BOOT_CMD(
419 stopvo, CFG_MAXARGS, 1, do_stopvo,
420 "stopvo - close interface of vo device.\n"
421 "\t- stopvo [dev]",
422 "\nargs: [dev]\n"
423 "\t-<dev> : 0~1(HD0~HD1)\n");
424
425 U_BOOT_CMD(
426 startvl, CFG_MAXARGS, 1, do_startvl,
427 "startvl - open video layer.\n"
428 "\t- startvl [layer addr stride x y w h]\n",
429 "\nargs: [layer, addr, stride, x, y, w, h]\n"
430 "\t-<layer> : 0(V0), 1(V1)\n"
431 "\t-<addr> : picture address\n"
432 "\t-<stride> : picture stride\n"
433 "\t-<x,y,w,h> : display area\n");
434
435 U_BOOT_CMD(
436 stopvl, CFG_MAXARGS, 1, do_stopvl,
437 "stopvl - close video layer.\n"
438 "\t- stopvl [layer]",
439 "\nargs: [layer]\n"
440 "\t-<layer> : 0(V0), 1(V1)\n");
441
442 U_BOOT_CMD(
443 setvobg, CFG_MAXARGS, 1, do_vobg,
444 "setvobg - set vo backgroud color.\n"
445 "\t- setvobg [dev color]",
446 "\nargs: [dev, color]\n"
447 "\t-<dev> : 0~1(HD0~1)\n"
448 "\t-<color>: rgb color space\n");
449
450 U_BOOT_CMD(
451 startgx, CFG_MAXARGS, 1, do_startgx,
452 "startgx - open graphics layer.\n"
453 "\t- startgx [layer addr stride x y w h]\n",
454 "\nargs: [layer, addr, stride, x, y, w, h]\n"
455 "\t-<layer> : 0(G0), 1(G1)\n"
456 "\t-<addr> : picture address\n"
457 "\t-<stride> : picture stride\n"
458 "\t-<x,y,w,h> : display area\n");
459
460 U_BOOT_CMD(
461 stopgx, CFG_MAXARGS, 1, do_stopgx,
462 "stopgx - close graphics layer.\n"
463 "\t- stopgx [layer]",
464 "\nargs: [layer]\n"
465 "\t-<layer> : 0(G0), 1(G1)\n");
466