linuxOS_D21X/source/artinchip/test-tp2825/test_tp2825.c
2024-11-29 16:33:21 +08:00

255 lines
5.8 KiB
C

// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) 2024 Artinchip Technology Co., Ltd.
* Authors: Matteo <duanmt@artinchip.com>
*/
#include <stdint.h>
#include <video/tp2825B.h>
#include <artinchip/sample_base.h>
/* Global macro and variables */
#define TP2825_DEV "/dev/tp2825"
#define TP2825_MAX_CH DIFF_VIN34
#define TP2825_MAX_MODE TP2802_960P25
#define UNDEFINED "Undefined"
static const char sopts[] = "m:c:h";
static const struct option lopts[] = {
{"mode", required_argument, NULL, 'm'},
{"channel", required_argument, NULL, 'c'},
{"usage", no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
static char *tp2825_modes[] = {
"720P60", // 0x00
"720P50", // 0x01
"1080P30", // 0x02
"1080P25", // 0x03
"720P30", // 0x04
"720P25", // 0x05
"SD", // 0x06
"INVALID_FORMAT", // 0x07
"PAL", // 0x08
"NTSC", // 0x09
UNDEFINED,
UNDEFINED,
"720P30V2", // 0x0C
"720P25V2", // 0x0D
UNDEFINED,
UNDEFINED, // 0x0F
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, // 0x10~0x13
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, // 0x14~0x17
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, // 0x18~0x1B
UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, // 0x1C~0x1F
"3M18", // 0x20, 2048x1536@18.75 for TVI
"5M12", // 0x21, 2592x1944@12.5 for TVI
"4M15", // 0x22, 2688x1520@15 for TVI
"3M20", // 0x23, 2048x1536@20 for TVI
"4M12", // 0x24, 2688x1520@12.5 for TVI
"6M10", // 0x25, 3200x1800@10 for TVI
"QHD30", // 0x26, 2560x1440@30 for TVI/HDA/HDC
"QHD25", // 0x27, 2560x1440@25 for TVI/HDA/HDC
"QHD15", // 0x28, 2560x1440@15 for HDA
"QXGA18", // 0x29, 2048x1536@18 for HDA/TVI
"QXGA30", // 0x2A, 2048x1536@30 for HDA
"QXGA25", // 0x2B, 2048x1536@25 for HDA
"4M30", // 0x2C, 2688x1520@30 for TVI(for future)
"4M25", // 0x2D, 2688x1520@25 for TVI(for future)
"5M20", // 0x2E, 2592x1944@20 for TVI/HDA
"8M15", // 0x2f, 3840x2160@15 for TVI
"8M12", // 0x30, 3840x2160@12.5 for TVI
"1080P15", // 0x31, 1920x1080@15 for TVI
"1080P60", // 0x32, 1920x1080@60 for TVI
"960P30", // 0x33, 1280x960@30 for TVI
"1080P20", // 0x34, 1920x1080@20 for TVI
"1080P50", // 0x35, 1920x1080@50 for TVI
"720P14", // 0x36, 1280x720@14 for TVI
"720P30HDR", // 0x37, 1280x720@30 for TVI
"6M20", // 0x38, 2960x1920@20 for CVI
"8M15V2", // 0x39, 3264x2448@15 for TVI
"5M20V2", // 0x3a, 2960x1664@20 for TVI
"8M7", // 0x3b, 3720x2160@7.5 for AHD
"3M20V2", // 0x3c, 2304x1296@20 for TVI
"1080P2750", // 0x3d, 1920x1080@27.5 for TVI
"1080P2700", // 0x3e, 1920x1080@27.5 for TVI
UNDEFINED,
UNDEFINED,
"1080P12", // 0x41, 1920x1080@12.5
"5M12V2", // 0x42, 2960x1664@12.5 for TVI
"960P25", // 0x43, 1280x960@25 for AHD
};
/* Functions */
void usage(char *program)
{
printf("Usage: %s [options]: \n", program);
printf("\t -m, --mode\t\toutput mode\n");
printf("\t -c, --channel\t\tthe number of video channel, [0, 3]\n");
printf("\t -h, --usage \n");
printf("\n");
printf("Example: %s -m 0xC -c 1\n", program);
}
/* Open a device file to be needed. */
static int device_open(char *_fname, int _flag)
{
s32 fd = -1;
fd = open(_fname, _flag);
if (fd < 0) {
ERR("Failed to open %s errno: %d[%s]\n",
_fname, errno, strerror(errno));
exit(0);
}
return fd;
}
static int tp2825_get_ch(int fd, uint8_t *ch)
{
tp2802_register tp_reg = {0};
int ret = 0;
ret = ioctl(fd, TP2802_GET_VIDEO_INPUT, &tp_reg);
if (ret < 0) {
ERR("Failed to get current video channel. return %d\n", ret);
return -1;
}
*ch = tp_reg.value;
return 0;
}
static int tp2825_set_ch(int fd, uint8_t ch)
{
tp2802_register tp_reg = {0};
int ret = 0;
tp_reg.value = ch;
ret = ioctl(fd, TP2802_SET_VIDEO_INPUT, &tp_reg);
if (ret < 0) {
ERR("Failed to set the video channel. return %d\n", ret);
return -1;
}
return 0;
}
static int tp2825_get_mode(int fd, tp2802_video_mode *out)
{
int ret = 0;
tp2802_video_mode vmode = {0};
tp2802_video_mode *pmode = &vmode;
if (out)
pmode = out;
ret = tp2825_get_ch(fd, &pmode->ch);
if (ret < 0)
return -1;
ret = ioctl(fd, TP2802_GET_VIDEO_MODE, pmode);
if (ret < 0) {
ERR("Failed to get current video mode. return %d\n", ret);
return -1;
}
printf("Current mode: Chip%d, ch%d, mode %s, std %d\n",
pmode->chip, pmode->ch, tp2825_modes[pmode->mode], pmode->std);
return 0;
}
static int tp2825_set_mode(int fd, uint32_t ch, uint32_t mode)
{
tp2802_video_mode vmode = {0};
int ret = 0;
ret = tp2825_get_mode(fd, &vmode);
if (ret < 0)
return -1;
if ((vmode.ch == ch) && (vmode.mode == mode)) {
printf("Don't need change anything.\n");
return 0;
}
printf("\tChange ch %d -> %d, mode %s -> %s\n",
vmode.ch, ch,
tp2825_modes[vmode.mode], tp2825_modes[mode]);
if (vmode.ch != ch) {
ret = tp2825_set_ch(fd, ch);
if (ret < 0)
return -1;
}
if (vmode.mode != mode) {
vmode.ch = ch;
vmode.mode = mode;
ret = ioctl(fd, TP2802_SET_VIDEO_MODE, &vmode);
if (ret < 0) {
ERR("Failed to set video mode. return %d\n", ret);
return -1;
}
}
return 0;
}
int main(int argc, char **argv)
{
int c, ret = 0, changed = 0;
uint32_t mode = TP2802_PAL, ch = 0;
int dev_fd = -1;
while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch (c) {
case 'm':
mode = str2int(optarg);
if (mode > TP2825_MAX_MODE) {
ERR("Invalid mode: %s\n", optarg);
return -1;
}
if (!strcmp(tp2825_modes[mode], UNDEFINED)) {
ERR("%s mode: %s\n", UNDEFINED, optarg);
return -1;
}
changed = 1;
break;
case 'c':
ch = str2int(optarg);
if (ch > TP2825_MAX_CH) {
ERR("Invalid channel: %s\n", optarg);
return -1;
}
changed = 1;
break;
case 'h':
usage(argv[0]);
return 0;
default:
break;
}
}
dev_fd = device_open(TP2825_DEV, O_RDWR);
if (dev_fd < 0)
return -1;
if (changed)
ret = tp2825_set_mode(dev_fd, ch, mode);
else
ret = tp2825_get_mode(dev_fd, NULL);
if (dev_fd > 0)
close(dev_fd);
return ret;
}