/* * 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 "hi3519av100_vo.h" #define CMD_VO_ARGS_BASE10 10 #define CMD_VO_ARGS_BASE16 16 #define CMD_VO_ARGS_BASE_ALL 0 extern int set_vobg(unsigned int dev, unsigned int rgb); extern int start_vo(unsigned int dev, unsigned int type, unsigned int sync); extern int stop_vo(unsigned int dev); extern int start_videolayer(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect layer_rect); extern int stop_videolayer(unsigned int layer); extern int hdmi_display(unsigned int vosync, unsigned int input, unsigned int output); extern void hdmi_stop(void); extern int mipi_tx_display(unsigned int vosync); extern int mipi_tx_stop(void); extern int start_gx(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect gx_rect); extern int stop_gx(unsigned int layer); #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 int check_vo_support(unsigned int dev, unsigned int type, unsigned int sync) { /* check interface type, ONLY VGA & HDMI interface is supported. */ if (dev == VO_DEV_DHD0) { if ((type & ~(VO_INTF_HDMI | VO_INTF_BT1120 | VO_INTF_BT656 | VO_INTF_MIPI | VO_INTF_MIPI_SLAVE)) || (type == 0)) { printf("hd%u only supports HDMI, BT.656, BT.1120, mipi_tx intftype, intf %u is illegal!\n", dev, type); return -1; } /* just one interface at the the time for a dev. */ if (type & ~(VO_INTF_HDMI | VO_INTF_BT1120) && (type & ~(VO_INTF_HDMI | VO_INTF_MIPI)) && (type & ~VO_INTF_BT656) && (type & ~VO_INTF_MIPI_SLAVE)) { printf("for VO %u, only HDMI and BT.1120 can be used at the same time!\n", dev); return -1; } } else if (dev == VO_DEV_DHD1) { if ((type & ~(VO_INTF_BT1120 | VO_INTF_BT656 | VO_INTF_MIPI | VO_INTF_MIPI_SLAVE | VO_INTF_LCD_6BIT | VO_INTF_LCD_8BIT | VO_INTF_LCD_16BIT | VO_INTF_LCD_18BIT | VO_INTF_LCD_24BIT)) || (type == 0)) { printf("hd%u only supports BT.656, BT.1120, mipi_tx, LCD intftype, intf %u is illegal!\n", dev, type); return -1; } /* just one interface at the the time for a dev. */ if ( (type & ~VO_INTF_BT1120) && (type & ~VO_INTF_BT656) && (type & ~VO_INTF_MIPI) && (type & ~VO_INTF_MIPI_SLAVE) && (type & ~VO_INTF_LCD_6BIT) && (type & ~VO_INTF_LCD_8BIT) && (type & ~VO_INTF_LCD_16BIT) && (type & ~VO_INTF_LCD_18BIT) && (type & ~VO_INTF_LCD_24BIT) ) { printf("vo(%u), none of (BT.1120,BT.656,MIPI,LCD) can use at the same time!\n", dev); return -1; } } else { printf("unknow dev(%u)!\n", dev); return -1; } if (VO_INTF_HDMI & type) { if (!(((sync >= VO_OUTPUT_1080P24) && (sync <= VO_OUTPUT_640x480_60)) || ((sync >= VO_OUTPUT_1920x2160_30) && (sync <= VO_OUTPUT_4096x2160_60)))) { printf("vo%u's intfsync %u illegal!\n", dev, sync); return -1; } } if (VO_INTF_BT1120 & type) { if ((sync < VO_OUTPUT_1080P24) || (sync > VO_OUTPUT_7680x4320_30)) { printf("vo%u's intfsync %u illegal!\n", dev, sync); return -1; } } if ((VO_INTF_MIPI & type) || (VO_INTF_MIPI_SLAVE & type)) { if (dev == VO_DEV_DHD0) { if ((sync != VO_OUTPUT_576P50) && (sync != VO_OUTPUT_720P50) && (sync != VO_OUTPUT_720P60) && (sync != VO_OUTPUT_1024x768_60) && (sync != VO_OUTPUT_1280x1024_60) && (sync != VO_OUTPUT_720x1280_60) && (sync != VO_OUTPUT_1080x1920_60) && (sync != VO_OUTPUT_1080P60) && (sync != VO_OUTPUT_3840x2160_30) && (sync != VO_OUTPUT_3840x2160_60)) { printf("for MIPI(mipi_tx) intface, vo%u's intfsync %u illegal!\n", dev, sync); return -1; } } else if (dev == VO_DEV_DHD1) { if ((sync != VO_OUTPUT_576P50) && (sync != VO_OUTPUT_720P50) && (sync != VO_OUTPUT_720P60) && (sync != VO_OUTPUT_1024x768_60) && (sync != VO_OUTPUT_1280x1024_60) && (sync != VO_OUTPUT_720x1280_60) && (sync != VO_OUTPUT_1080x1920_60) && (sync != VO_OUTPUT_1080P60)) { printf("for MIPI(mipi_tx) intface, vo%u's intfsync %u illegal! \n", dev, sync); return -1; } } } if (type == (VO_INTF_HDMI | VO_INTF_MIPI)) { if ((sync == VO_OUTPUT_576P50) || (sync == VO_OUTPUT_1024x768_60)) { printf("when HDMI+MIPI, not support 576P50 or 1024x768_60\n"); return -1; } } return 0; } static int do_vobg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int dev, rgb; if (argc < 3) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); rgb = (unsigned int)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE_ALL); if (dev >= VO_DEV_BUTT) { printf("invalid parameter!\n"); return -1; } set_vobg(dev, rgb); printf("dev %u set background color!\n", dev); return 0; } static int do_startvo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int dev, intftype, sync; if (argc < 4) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); intftype = (unsigned int)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE10); sync = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10); if ((dev >= VO_DEV_BUTT) || (sync >= VO_OUTPUT_BUTT)) { printf("invalid parameter!\n"); return -1; } if (check_vo_support(dev, intftype, sync)) { printf("unsupport parameter!\n"); return -1; } start_vo(dev, intftype, sync); g_a_interface_type[dev] = intftype; if (intftype & VO_INTF_HDMI) { if (intftype == (VO_INTF_HDMI | VO_INTF_MIPI)) { hdmi_display(sync, 0, 2); } else { hdmi_display(sync, 2, 2); } } if (intftype & VO_INTF_MIPI) { /* to call mipi_display. */ mipi_tx_display(sync); } printf("dev %u opened!\n", dev); return 0; } static int do_stopvo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int dev; if (argc < 2) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } dev = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); if (dev >= VO_DEV_BUTT) { printf("invalid parameter!\n"); return -1; } if (g_a_interface_type[dev] & VO_INTF_HDMI) { g_a_interface_type[dev] = 0; hdmi_stop(); } if (g_a_interface_type[dev] & VO_INTF_MIPI) { mipi_tx_stop(); } stop_vo(dev); printf("dev %u closed!\n", dev); return 0; } static int do_startvl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int layer, strd, x, y, w, h; unsigned long addr; hi_vo_rect layer_rect; int max_x, max_y, layer_max_w, layer_max_h; if (argc < 8) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); addr = (unsigned long)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE16); strd = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10); x = (unsigned int)simple_strtoul(argv[4], NULL, CMD_VO_ARGS_BASE10); y = (unsigned int)simple_strtoul(argv[5], NULL, CMD_VO_ARGS_BASE10); w = (unsigned int)simple_strtoul(argv[6], NULL, CMD_VO_ARGS_BASE10); h = (unsigned int)simple_strtoul(argv[7], NULL, CMD_VO_ARGS_BASE10); if (layer == VO_LAYER_VHD0) { max_x = VHD0_PIC_MAX_WIDTH; max_y = VHD0_PIC_MAX_HEIGHT; layer_max_w = VHD0_PIC_MAX_WIDTH; layer_max_h = VHD0_PIC_MAX_HEIGHT; } else if (layer == VO_LAYER_VHD1) { max_x =VHD1_PIC_MAX_WIDTH; max_y = VHD1_PIC_MAX_HEIGHT; layer_max_w = VHD1_PIC_MAX_WIDTH; layer_max_h = VHD1_PIC_MAX_HEIGHT; } else { printf("invalid parameter!\n"); return -1; } if((strd > (layer_max_w * 2)) || (x > max_x) || (x & 0x1) || (y > max_y) || (y & 0x1) || (w > layer_max_w) || (w & 0x1) || (w < PIC_MIN_LENTH) || (h > layer_max_h) || (h & 0x1) || (h < PIC_MIN_LENTH)) { printf("invalid parameter!\n"); return -1; } layer_rect.x = x; layer_rect.y = y; layer_rect.w = w; layer_rect.h = h; start_videolayer(layer, addr, strd, layer_rect); printf("video layer %u opened!\n", layer); return 0; } static int do_stopvl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int layer; if (argc < 2) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); if ((layer > VO_LAYER_VSD0) || (layer == VO_LAYER_VP)) { printf("invalid parameter!\n"); return -1; } stop_videolayer(layer); printf("video layer %u closed!\n", layer); return 0; } static int do_startgx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int layer, strd, x, y, w, h; unsigned long addr; hi_vo_rect gx_rect; int max_x, max_y, layer_max_w, layer_max_h; if (argc < 8) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); addr = (unsigned long)simple_strtoul(argv[2], NULL, CMD_VO_ARGS_BASE16); strd = (unsigned int)simple_strtoul(argv[3], NULL, CMD_VO_ARGS_BASE10); x = (unsigned int)simple_strtoul(argv[4], NULL, CMD_VO_ARGS_BASE10); y = (unsigned int)simple_strtoul(argv[5], NULL, CMD_VO_ARGS_BASE10); w = (unsigned int)simple_strtoul(argv[6], NULL, CMD_VO_ARGS_BASE10); h = (unsigned int)simple_strtoul(argv[7], NULL, CMD_VO_ARGS_BASE10); if (layer == VO_GRAPHC_G0) { max_x =GFX0_PIC_MAX_WIDTH; max_y = GFX0_PIC_MAX_HEIGHT; layer_max_w = GFX0_PIC_MAX_WIDTH; layer_max_h = GFX0_PIC_MAX_HEIGHT; } else if (layer == VO_GRAPHC_G1) { max_x =GFX1_PIC_MAX_WIDTH; max_y = GFX1_PIC_MAX_HEIGHT; layer_max_w = GFX1_PIC_MAX_WIDTH; layer_max_h = GFX1_PIC_MAX_HEIGHT; } else { printf("invalid parameter!\n"); return -1; } if((strd > (layer_max_w * 2)) || (x > max_x) || (x & 0x1) || (y > max_y) || (y & 0x1) || (w > layer_max_w) || (w & 0x1) || (w < PIC_MIN_LENTH) || (h > layer_max_h) || (h & 0x1) || (h < PIC_MIN_LENTH)) { printf("invalid parameter!\n"); return -1; } gx_rect.x = x; gx_rect.y = y; gx_rect.w = w; gx_rect.h = h; start_gx(layer, addr, strd, gx_rect); printf("graphic layer %u opened!\n", layer); return 0; } static int do_stopgx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned int layer; if (argc < 2) { printf("insufficient parameter!\n"); printf ("usage:\n%s\n", cmdtp->usage); return -1; } layer = (unsigned int)simple_strtoul(argv[1], NULL, CMD_VO_ARGS_BASE10); if (layer >= VO_GRAPHC_BUTT) { printf("invalid parameter!\n"); return -1; } stop_gx(layer); printf("graphic layer %u closed!\n", layer); return 0; } U_BOOT_CMD( startvo, CFG_MAXARGS, 1, do_startvo, "startvo - open vo device with a certain output interface.\n" "\t- startvo [dev intftype sync]", "\nargs: [dev, intftype, sync]\n" "\t- : 0: DHD0,1: DHD1\n" "\t-: 8(BT.656),16(BT.1120),32(HDMI),16384(mipi_tx)\n" "\t-: typical value:\n" "\t\t0(PAL), 1(NTSC), 4(1080P30), 6(720P60)\n" "\t\t10(1080P60), 21(1920x1200), 26(2560x1440_30),31(3840x2160_30)\n" "\t\t33(3840x2160_60),45(1080x1920_60),47(user)\n"); U_BOOT_CMD( stopvo, CFG_MAXARGS, 1, do_stopvo, "stopvo - close interface of vo device.\n" "\t- stopvo [dev]", "\nargs: [dev]\n" "\t- : 0~1(HD0~HD1)\n"); U_BOOT_CMD( startvl, CFG_MAXARGS, 1, do_startvl, "startvl - open video layer.\n" "\t- startvl [layer addr stride x y w h]\n", "\nargs: [layer, addr, stride, x, y, w, h]\n" "\t- : 0(V0), 1(V1)\n" "\t- : picture address\n" "\t- : picture stride\n" "\t- : display area\n"); U_BOOT_CMD( stopvl, CFG_MAXARGS, 1, do_stopvl, "stopvl - close video layer.\n" "\t- stopvl [layer]", "\nargs: [layer]\n" "\t- : 0(V0), 1(V1)\n"); U_BOOT_CMD( setvobg, CFG_MAXARGS, 1, do_vobg, "setvobg - set vo backgroud color.\n" "\t- setvobg [dev color]", "\nargs: [dev, color]\n" "\t- : 0~1(HD0~1)\n" "\t-: rgb color space\n"); U_BOOT_CMD( startgx, CFG_MAXARGS, 1, do_startgx, "startgx - open graphics layer.\n" "\t- startgx [layer addr stride x y w h]\n", "\nargs: [layer, addr, stride, x, y, w, h]\n" "\t- : 0(G0), 1(G1)\n" "\t- : picture address\n" "\t- : picture stride\n" "\t- : display area\n"); U_BOOT_CMD( stopgx, CFG_MAXARGS, 1, do_stopgx, "stopgx - close graphics layer.\n" "\t- stopgx [layer]", "\nargs: [layer]\n" "\t- : 0(G0), 1(G1)\n");