From: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> Add four new options: --list-subdev-standards, --get-subdev-standard, --set-subdev-standard and --get-subdev-detected-standard. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> --- utils/v4l2-ctl/v4l2-ctl-subdev.cpp | 158 +++++++++++++++++++++++++++++ utils/v4l2-ctl/v4l2-ctl.cpp | 4 + utils/v4l2-ctl/v4l2-ctl.h | 4 + 3 files changed, 166 insertions(+) diff --git a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp index c1d3e5ad46f763fb..d08c04e787810516 100644 --- a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp @@ -48,6 +48,7 @@ static struct v4l2_subdev_frame_size_enum frmsize; static struct v4l2_subdev_frame_interval_enum frmival; static __u32 set_fps_pad; static double set_fps; +static v4l2_std_id standard; void subdev_usage(void) { @@ -96,9 +97,88 @@ void subdev_usage(void) " flags=le|ge|keep-config\n" " --set-subdev-fps pad=<pad>,fps=<fps> (for testing only, otherwise use media-ctl)\n" " set the frame rate [VIDIOC_SUBDEV_S_FRAME_INTERVAL]\n" + " --list-subdev-standards display supported video standards [VIDIOC_SUBDEV_ENUMSTD]\n" + " --get-subdev-standard\n" + " query the video standard [VIDIOC_SUBDEV_G_STD]\n" + " --set-subdev-standard <num>\n" + " set the video standard to <num> [VIDIOC_SUBDEV_S_STD]\n" + " <num> a numerical v4l2_std value, or one of:\n" + " pal or pal-X (X = B/G/H/N/Nc/I/D/K/M/60) (V4L2_STD_PAL)\n" + " ntsc or ntsc-X (X = M/J/K) (V4L2_STD_NTSC)\n" + " secam or secam-X (X = B/G/H/D/K/L/Lc) (V4L2_STD_SECAM)\n" + " --get-subdev-detected-standard\n" + " display detected input video standard [VIDIOC_SUBDEV_QUERYSTD]\n" ); } +static v4l2_std_id parse_pal(const char *pal) +{ + if (pal[0] == '-') { + switch (tolower(pal[1])) { + case '6': + return V4L2_STD_PAL_60; + case 'b': + case 'g': + return V4L2_STD_PAL_BG; + case 'h': + return V4L2_STD_PAL_H; + case 'n': + if (tolower(pal[2]) == 'c') + return V4L2_STD_PAL_Nc; + return V4L2_STD_PAL_N; + case 'i': + return V4L2_STD_PAL_I; + case 'd': + case 'k': + return V4L2_STD_PAL_DK; + case 'm': + return V4L2_STD_PAL_M; + } + } + fprintf(stderr, "pal specifier not recognised\n"); + subdev_usage(); + exit(1); +} + +static v4l2_std_id parse_secam(const char *secam) +{ + if (secam[0] == '-') { + switch (tolower(secam[1])) { + case 'b': + case 'g': + case 'h': + return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; + case 'd': + case 'k': + return V4L2_STD_SECAM_DK; + case 'l': + if (tolower(secam[2]) == 'c') + return V4L2_STD_SECAM_LC; + return V4L2_STD_SECAM_L; + } + } + fprintf(stderr, "secam specifier not recognised\n"); + subdev_usage(); + exit(1); +} + +static v4l2_std_id parse_ntsc(const char *ntsc) +{ + if (ntsc[0] == '-') { + switch (tolower(ntsc[1])) { + case 'm': + return V4L2_STD_NTSC_M; + case 'j': + return V4L2_STD_NTSC_M_JP; + case 'k': + return V4L2_STD_NTSC_M_KR; + } + } + fprintf(stderr, "ntsc specifier not recognised\n"); + subdev_usage(); + exit(1); +} + void subdev_cmd(int ch, char *optarg) { char *value, *subs; @@ -338,6 +418,33 @@ void subdev_cmd(int ch, char *optarg) } } break; + case OptSetSubDevStandard: + if (!strncasecmp(optarg, "pal", 3)) { + if (optarg[3]) + standard = parse_pal(optarg + 3); + else + standard = V4L2_STD_PAL; + } + else if (!strncasecmp(optarg, "ntsc", 4)) { + if (optarg[4]) + standard = parse_ntsc(optarg + 4); + else + standard = V4L2_STD_NTSC; + } + else if (!strncasecmp(optarg, "secam", 5)) { + if (optarg[5]) + standard = parse_secam(optarg + 5); + else + standard = V4L2_STD_SECAM; + } + else if (isdigit(optarg[0])) { + standard = strtol(optarg, 0L, 0) | (1ULL << 63); + } else { + fprintf(stderr, "Unknown standard '%s'\n", optarg); + subdev_usage(); + exit(1); + } + break; default: break; } @@ -492,6 +599,19 @@ void subdev_set(int fd) fival.interval.denominator, fival.interval.numerator); } } + + if (options[OptSetSubDevStandard]) { + if (standard & (1ULL << 63)) { + struct v4l2_standard vs; + + vs.index = standard & 0xffff; + if (test_ioctl(fd, VIDIOC_SUBDEV_ENUMSTD, &vs) >= 0) { + standard = vs.id; + } + } + if (doioctl(fd, VIDIOC_SUBDEV_S_STD, &standard) == 0) + printf("Standard set to %08llx\n", (unsigned long long)standard); + } } void subdev_get(int fd) @@ -547,6 +667,20 @@ void subdev_get(int fd) fival.interval.denominator, fival.interval.numerator); } } + + if (options[OptGetSubDevStandard]) { + if (doioctl(fd, VIDIOC_SUBDEV_G_STD, &standard) == 0) { + printf("Video Standard = 0x%08llx\n", (unsigned long long)standard); + printf("\t%s\n", std2s(standard, "\n\t").c_str()); + } + } + + if (options[OptQuerySubDevStandard]) { + if (doioctl(fd, VIDIOC_SUBDEV_QUERYSTD, &standard) == 0) { + printf("Video Standard = 0x%08llx\n", (unsigned long long)standard); + printf("\t%s\n", std2s(standard, "\n\t").c_str()); + } + } } static void print_mbus_code(__u32 code) @@ -637,4 +771,28 @@ void subdev_list(int fd) frmival.index++; } } + + if (options[OptListSubDevStandards]) { + struct v4l2_standard vs; + + printf("ioctl: VIDIOC_SUBDEV_ENUMSTD\n"); + vs.index = 0; + while (test_ioctl(fd, VIDIOC_SUBDEV_ENUMSTD, &vs) >= 0) { + if (options[OptConcise]) { + printf("\t%2d: 0x%016llX %s\n", vs.index, + (unsigned long long)vs.id, vs.name); + } else { + if (vs.index) + printf("\n"); + printf("\tIndex : %d\n", vs.index); + printf("\tID : 0x%016llX\n", (unsigned long long)vs.id); + printf("\tName : %s\n", vs.name); + printf("\tFrame period: %d/%d\n", + vs.frameperiod.numerator, + vs.frameperiod.denominator); + printf("\tFrame lines : %d\n", vs.framelines); + } + vs.index++; + } + } } diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index 2a87c48f1dbee797..9b15c40c36393a96 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -271,6 +271,10 @@ static struct option long_options[] = { {"stream-out-user", optional_argument, 0, OptStreamOutUser}, {"stream-out-dmabuf", no_argument, 0, OptStreamOutDmaBuf}, {"list-patterns", no_argument, 0, OptListPatterns}, + {"list-subdev-standards", no_argument, 0, OptListSubDevStandards}, + {"get-subdev-standard", no_argument, 0, OptGetSubDevStandard}, + {"set-subdev-standard", required_argument, 0, OptSetSubDevStandard}, + {"get-subdev-detected-standard", no_argument, 0, OptQuerySubDevStandard}, {0, 0, 0, 0} }; diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h index e510d778deb04984..d99fa74c1244023d 100644 --- a/utils/v4l2-ctl/v4l2-ctl.h +++ b/utils/v4l2-ctl/v4l2-ctl.h @@ -124,6 +124,10 @@ enum Option { OptListSubDevMBusCodes, OptListSubDevFrameSizes, OptListSubDevFrameIntervals, + OptListSubDevStandards, + OptGetSubDevStandard, + OptSetSubDevStandard, + OptQuerySubDevStandard, OptListOutFields, OptClearClips, OptClearBitmap, -- 2.18.0