/* * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include "hi_common_vo.h" #include "vo.h" #if CONFIG_HI_HDMI_SUPPORT #include "hi_hdmi.h" #endif #define CFG_MAXARGS_SETVOBG 3 #define CFG_MAXARGS_STARTVO 4 #define CFG_MAXARGS_STOPVO 2 #define CFG_MAXARGS_STARTVL 8 #define CFG_MAXARGS_STOPVL 2 #define CFG_MAXARGS_STARTGX 9 #define CFG_MAXARGS_STOPGX 2 #define CMD_VO_ARGS_BASE10 10 #define CMD_VO_ARGS_BASE16 16 #define CMD_VO_ARGS_BASE_ALL 0 #define INSUFFICIENT_PARAM_STR "insufficient parameter or operation not permitted!\n" #define VO_DEV_MAX_NUM 3 static unsigned int g_a_interface_type[VO_DEV_MAX_NUM] = { [0 ... (VO_DEV_MAX_NUM - 1)] = 0}; static unsigned int vo_get_interface_type(unsigned int dev) { if (dev >= VO_DEV_MAX_NUM) { return 0; } return g_a_interface_type[dev]; } static void vo_set_interface_type(unsigned int dev, unsigned int type) { if (dev >= VO_DEV_MAX_NUM) { return; } g_a_interface_type[dev] = type; } static int vobg_parse(char *const argv[], unsigned int *dev, unsigned int *rgb) { int ret; unsigned long dev_tmp, rgb_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &dev_tmp); /* 1st arg */ if (ret != 0) { printf("parse dev failed.\n"); return -1; } ret = strict_strtoul(argv[2], CMD_VO_ARGS_BASE_ALL, &rgb_tmp); /* 2nd arg */ if (ret != 0) { printf("parse color failed.\n"); return -1; } *dev = (unsigned int)dev_tmp; *rgb = (unsigned int)rgb_tmp; return 0; } static int do_vobg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int dev, rgb; if (argc < 3) { /* max 3 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = vobg_parse(argv, &dev, &rgb); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = set_vobg(dev, rgb); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } printf("dev %u set background color 0x%x!\n", dev, rgb); return 0; } static int startvo_parse(char *const argv[], unsigned int *dev, unsigned int *intftype, unsigned int *sync) { int ret; unsigned long dev_tmp, intftype_tmp, sync_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &dev_tmp); /* 1st arg */ if (ret != 0) { printf("parse dev failed.\n"); return -1; } ret = strict_strtoul(argv[2], CMD_VO_ARGS_BASE10, &intftype_tmp); /* 2nd arg */ if (ret != 0) { printf("parse intftype failed.\n"); return -1; } ret = strict_strtoul(argv[3], CMD_VO_ARGS_BASE10, &sync_tmp); /* 3rd arg */ if (ret != 0) { printf("parse sync failed.\n"); return -1; } *dev = (unsigned int)dev_tmp; *intftype = (unsigned int)intftype_tmp; *sync = (unsigned int)sync_tmp; return 0; } #if CONFIG_HI_HDMI_SUPPORT static void do_start_hdmi(unsigned int intftype, unsigned int sync) { if (intftype & HI_VO_INTF_HDMI) { if (intftype == (HI_VO_INTF_HDMI | HI_VO_INTF_MIPI)) { /* start hdmi */ hdmi_display(sync, HI_HDMI_VIDEO_MODE_RGB444, HI_HDMI_VIDEO_MODE_YCBCR444); } else { /* start hdmi */ hdmi_display(sync, HI_HDMI_VIDEO_MODE_YCBCR444, HI_HDMI_VIDEO_MODE_YCBCR444); } } } #endif static int do_startvo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int dev, intftype, sync; if (argc < 4) { /* max 4 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = startvo_parse(argv, &dev, &intftype, &sync); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = start_vo(dev, intftype, sync); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } #if CONFIG_HI_HDMI_SUPPORT do_start_hdmi(intftype, sync); #endif vo_set_interface_type(dev, intftype); printf("dev %u opened!\n", dev); return 0; } static void do_stop_hdmi(unsigned int dev) { if (vo_get_interface_type(dev) & HI_VO_INTF_HDMI) { /* stop hdmi */ #if CONFIG_HI_HDMI_SUPPORT hdmi_stop(); #endif } } static void do_stop_intf(unsigned int dev) { do_stop_hdmi(dev); vo_set_interface_type(dev, 0); } static int stopvo_parse(char *const argv[], unsigned int *dev) { int ret; unsigned long dev_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &dev_tmp); if (ret != 0) { printf("parse dev failed.\n"); return -1; } *dev = (unsigned int)dev_tmp; return 0; } static int do_stopvo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int dev; if (argc < 2) { /* max 2 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = stopvo_parse(argv, &dev); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } /* step1: stop vo */ ret = stop_vo(dev); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } /* step2: stop intf */ do_stop_intf(dev); printf("dev %u closed!\n", dev); return 0; } static int start_layer_parse(char *const argv[], unsigned int *layer, unsigned long *addr, unsigned int *strd, hi_rect *layer_rect) { int ret; unsigned long layer_tmp, addr_tmp, strd_tmp, x_tmp, y_tmp, width_tmp, height_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &layer_tmp); /* 1st arg */ if (ret != 0) { printf("parse layer failed.\n"); return -1; } ret = strict_strtoul(argv[2], CMD_VO_ARGS_BASE16, &addr_tmp); /* 2nd arg */ if (ret != 0) { printf("parse addr failed.\n"); return -1; } ret = strict_strtoul(argv[3], CMD_VO_ARGS_BASE10, &strd_tmp); /* 3rd arg */ if (ret != 0) { printf("parse strd failed.\n"); return -1; } ret = strict_strtoul(argv[4], CMD_VO_ARGS_BASE10, &x_tmp); /* 4th arg */ if (ret != 0) { printf("parse x failed.\n"); return -1; } ret = strict_strtoul(argv[5], CMD_VO_ARGS_BASE10, &y_tmp); /* 5th arg */ if (ret != 0) { printf("parse y failed.\n"); return -1; } ret = strict_strtoul(argv[6], CMD_VO_ARGS_BASE10, &width_tmp); /* 6th arg */ if (ret != 0) { printf("parse width failed.\n"); return -1; } ret = strict_strtoul(argv[7], CMD_VO_ARGS_BASE10, &height_tmp); /* 7th arg */ if (ret != 0) { printf("parse height failed.\n"); return -1; } *layer = (unsigned int)layer_tmp; *addr = addr_tmp; *strd = (unsigned int)strd_tmp; layer_rect->x = (unsigned int)x_tmp; layer_rect->y = (unsigned int)y_tmp; layer_rect->width = (unsigned int)width_tmp; layer_rect->height = (unsigned int)height_tmp; return 0; } static int start_gx_type_parse(char *const argv[], unsigned int *type) { int ret; unsigned long type_tmp; ret = strict_strtoul(argv[8], CMD_VO_ARGS_BASE10, &type_tmp); /* 8th arg */ if (ret != 0) { printf("parse type failed.\n"); return -1; } *type = (unsigned int)type_tmp; return 0; } static int do_startgx(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int layer, strd, type; unsigned long addr; hi_rect gx_rect; if (argc < 9) { /* max 9 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = start_layer_parse(argv, &layer, &addr, &strd, &gx_rect); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = start_gx_type_parse(argv, &type); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = start_gx(layer, addr, strd, gx_rect, type); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } printf("graphic layer %u opened!\n", layer); return 0; } static int stopgx_parse(char *const argv[], unsigned int *layer) { int ret; unsigned long layer_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &layer_tmp); /* 1st arg */ if (ret != 0) { printf("parse layer failed.\n"); return -1; } *layer = (unsigned int)layer_tmp; return 0; } static int do_stopgx(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int layer; if (argc < 2) { /* max 2 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = stopgx_parse(argv, &layer); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = stop_gx(layer); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } printf("graphic layer %u closed!\n", layer); return 0; } static int do_startvl(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int layer, strd; unsigned long addr; hi_rect layer_rect; if (argc < 8) { /* max 8 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = start_layer_parse(argv, &layer, &addr, &strd, &layer_rect); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = start_videolayer(layer, addr, strd, layer_rect); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } printf("video layer %u opened!\n", layer); return 0; } static int stopvl_parse(char *const argv[], unsigned int *layer) { int ret; unsigned long layer_tmp; ret = strict_strtoul(argv[1], CMD_VO_ARGS_BASE10, &layer_tmp); /* 1st arg */ if (ret != 0) { printf("parse layer failed.\n"); return -1; } *layer = (unsigned int)layer_tmp; return 0; } static int do_stopvl(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret; unsigned int layer; if (argc < 2) { /* max 2 args */ printf("insufficient parameter!\n"); printf("usage:\n%s\n", cmdtp->usage); return -1; } ret = stopvl_parse(argv, &layer); if (ret != 0) { printf("insufficient parameter!\n"); return -1; } ret = stop_videolayer(layer); if (ret != 0) { printf(INSUFFICIENT_PARAM_STR); return -1; } printf("video layer %u closed!\n", layer); return 0; } #if ((defined(CHIP_HI3531DV200)) || (defined(CHIP_HI3535AV100))) #define USAGE_DEV_STRING \ "\t- : 0: DHD0,1: DHD1,2: DSD0\n" #define USAGE_INTF_STRING \ "\t-: 1(CVBS),2(VGA),8(BT.1120),16(HDMI)\n" \ #define USAGE_GX_STRING \ "\t- : 4(G0), 5(G1), 7(G3)\n" #define USAGE_VL_STRING \ "\t- : 0(V0), 1(V1), 3(V3)\n" #elif (defined(CHIP_HI3521DV200)) #define USAGE_DEV_STRING \ "\t- : 0: DHD0,1: DHD1,2: DSD0\n" #define USAGE_INTF_STRING \ "\t-: 1(CVBS),2(VGA),4(BT.656),8(BT.1120),16(HDMI)\n" \ #define USAGE_GX_STRING \ "\t- : 4(G0), 5(G1), 7(G3)\n" #define USAGE_VL_STRING \ "\t- : 0(V0), 1(V1), 3(V3)\n" #elif (defined(CHIP_HI3520DV500)) #define USAGE_DEV_STRING \ "\t- : 0: DHD0,2: DSD0\n" #define USAGE_INTF_STRING \ "\t-: 1(CVBS),2(VGA),4(BT.656),8(BT.1120),16(HDMI)\n" \ "\t\t128(RGB_16BIT),256(RGB_18BIT),512(RGB_24BIT)\n" #define USAGE_GX_STRING \ "\t- : 4(G0), 7(G3)\n" #define USAGE_VL_STRING \ "\t- : 0(V0), 3(V3)\n" #else #define USAGE_DEV_STRING \ "\t- : 0: DHD0,1: DHD1,2: DSD0\n" #define USAGE_INTF_STRING \ "\t-: 1(CVBS),2(VGA),8(BT.1120),16(HDMI)\n" \ "\t\t32(RGB_6BIT),64(RGB_8BIT),128(RGB_16BIT),256(RGB_18BIT),512(RGB_24BIT)\n" #define USAGE_GX_STRING \ "\t- : 4(G0), 5(G1), 7(G3)\n" #define USAGE_VL_STRING \ "\t- : 0(V0), 1(V1), 3(V3)\n" #endif #define USAGE_GX_TYPE \ "\t- : 0(argb1555), 1(bmp1555)\n" #define USAGE_START_VO \ "\nargs: [dev, intftype, sync]\n" \ USAGE_DEV_STRING \ USAGE_INTF_STRING \ "\t-:\n" \ "\t\t0(PAL), 1(NTSC), 2(960H_PAL), 3(960H_NTSC)\n" \ "\t\t4(640x480_60), 5(480P60), 6(576P50), 7(800x600_60)\n" \ "\t\t8(1024x768_60), 9(720P50), 10(720P60), 11(1280x800_60)\n" \ "\t\t12(1280x1024_60),13(1366x768_60), 14(1400x1050_60),15(1440x900_60)\n" \ "\t\t16(1600x1200_60),17(1680x1050_60),18(1080P24), 19(1080P25)\n" \ "\t\t20(1080P30), 21(1080I50), 22(1080I60), 23(1080P50)\n" \ "\t\t24(1080P60), 25(1920x1200_60),26(1920x2160_30),27(2560x1440_30)\n" \ "\t\t28(2560x1440_60),29(2560x1600_60),30(3840x2160_24),31(3840x2160_25)\n" \ "\t\t32(3840x2160_30),33(3840x2160_50),34(3840x2160_60),35(4096x2160_24)\n" \ "\t\t36(4096x2160_25),37(4096x2160_30),38(4096x2160_50),39(4096x2160_60)\n" \ "\t\t40(7680x4320_30),41(240x320_50), 42(320x240_50), 43(240x320_60)\n" \ "\t\t44(320x240_60), 45(800x600_50), 46(720x1280_60), 47(1080x1920_60)\n" \ "\t\t48(user)\n" #define USAGE_STOP_VO \ "\nargs: [dev]\n" \ USAGE_DEV_STRING #define USAGE_START_GX \ "\nargs: [layer, addr, stride, x, y, w, h, type]\n" \ USAGE_GX_STRING \ "\t- : picture address\n" \ "\t- : picture stride\n" \ "\t- : display area\n" \ USAGE_GX_TYPE #define USAGE_STOP_GX \ "\nargs: [layer]\n" \ USAGE_GX_STRING #define USAGE_START_VL \ "\nargs: [layer, addr, stride, x, y, w, h]\n" \ USAGE_VL_STRING \ "\t- : picture address\n" \ "\t- : picture stride\n" \ "\t- : display area\n" #define USAGE_STOP_VL \ "\nargs: [layer]\n" \ USAGE_VL_STRING #define USAGE_SET_VO_BG \ "\nargs: [dev, color]\n" \ USAGE_DEV_STRING \ "\t-: rgb color space\n" U_BOOT_CMD(startvo, CFG_MAXARGS_STARTVO, 1, do_startvo, "startvo - open vo device with a certain output interface.\n" "\t- startvo [dev intftype sync]", USAGE_START_VO); U_BOOT_CMD(stopvo, CFG_MAXARGS_STOPVO, 1, do_stopvo, "stopvo - close interface of vo device.\n" "\t- stopvo [dev]", USAGE_STOP_VO); U_BOOT_CMD(startgx, CFG_MAXARGS_STARTGX, 1, do_startgx, "startgx - open graphics layer.\n" "\t- startgx [layer addr stride x y w h type]", USAGE_START_GX); U_BOOT_CMD(stopgx, CFG_MAXARGS_STOPGX, 1, do_stopgx, "stopgx - close graphics layer.\n" "\t- stopgx [layer]", USAGE_STOP_GX); U_BOOT_CMD(startvl, CFG_MAXARGS_STARTVL, 1, do_startvl, "startvl - open video layer.\n" "\t- startvl [layer addr stride x y w h]", USAGE_START_VL); U_BOOT_CMD(stopvl, CFG_MAXARGS_STOPVL, 1, do_stopvl, "stopvl - close video layer.\n" "\t- stopvl [layer]", USAGE_STOP_VL); U_BOOT_CMD(setvobg, CFG_MAXARGS_SETVOBG, 1, do_vobg, "setvobg - set vo backgroud color.\n" "\t- setvobg [dev color]", USAGE_SET_VO_BG);