| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for the Conexant CX23885 PCIe bridge |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 8 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - * (at your option) any later version. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | 6 | */ |
|---|
| 17 | 7 | |
|---|
| 18 | 8 | #include "cx23885.h" |
|---|
| .. | .. |
|---|
| 77 | 67 | #define FORMAT_FLAGS_PACKED 0x01 |
|---|
| 78 | 68 | static struct cx23885_fmt formats[] = { |
|---|
| 79 | 69 | { |
|---|
| 80 | | - .name = "4:2:2, packed, YUYV", |
|---|
| 81 | 70 | .fourcc = V4L2_PIX_FMT_YUYV, |
|---|
| 82 | 71 | .depth = 16, |
|---|
| 83 | 72 | .flags = FORMAT_FLAGS_PACKED, |
|---|
| .. | .. |
|---|
| 264 | 253 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || |
|---|
| 265 | 254 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || |
|---|
| 266 | 255 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || |
|---|
| 256 | + (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC) || |
|---|
| 257 | + (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || |
|---|
| 267 | 258 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || |
|---|
| 259 | + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR5525) || |
|---|
| 268 | 260 | (dev->board == CX23885_BOARD_MYGICA_X8507) || |
|---|
| 269 | 261 | (dev->board == CX23885_BOARD_AVERMEDIA_HC81R) || |
|---|
| 270 | 262 | (dev->board == CX23885_BOARD_VIEWCAST_260E) || |
|---|
| .. | .. |
|---|
| 420 | 412 | dev->height >> 1); |
|---|
| 421 | 413 | break; |
|---|
| 422 | 414 | default: |
|---|
| 423 | | - BUG(); |
|---|
| 415 | + return -EINVAL; /* should not happen */ |
|---|
| 424 | 416 | } |
|---|
| 425 | | - dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", |
|---|
| 417 | + dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp 0x%08x - dma=0x%08lx\n", |
|---|
| 426 | 418 | buf, buf->vb.vb2_buf.index, |
|---|
| 427 | | - dev->width, dev->height, dev->fmt->depth, dev->fmt->name, |
|---|
| 419 | + dev->width, dev->height, dev->fmt->depth, dev->fmt->fourcc, |
|---|
| 428 | 420 | (unsigned long)buf->risc.dma); |
|---|
| 429 | 421 | return 0; |
|---|
| 430 | 422 | } |
|---|
| .. | .. |
|---|
| 638 | 630 | struct v4l2_capability *cap) |
|---|
| 639 | 631 | { |
|---|
| 640 | 632 | struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 641 | | - struct video_device *vdev = video_devdata(file); |
|---|
| 642 | 633 | |
|---|
| 643 | | - strcpy(cap->driver, "cx23885"); |
|---|
| 644 | | - strlcpy(cap->card, cx23885_boards[dev->board].name, |
|---|
| 634 | + strscpy(cap->driver, "cx23885", sizeof(cap->driver)); |
|---|
| 635 | + strscpy(cap->card, cx23885_boards[dev->board].name, |
|---|
| 645 | 636 | sizeof(cap->card)); |
|---|
| 646 | 637 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); |
|---|
| 647 | | - cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO; |
|---|
| 648 | | - if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 649 | | - cap->device_caps |= V4L2_CAP_TUNER; |
|---|
| 650 | | - if (vdev->vfl_type == VFL_TYPE_VBI) |
|---|
| 651 | | - cap->device_caps |= V4L2_CAP_VBI_CAPTURE; |
|---|
| 652 | | - else |
|---|
| 653 | | - cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; |
|---|
| 654 | | - cap->capabilities = cap->device_caps | V4L2_CAP_VBI_CAPTURE | |
|---|
| 655 | | - V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_DEVICE_CAPS; |
|---|
| 638 | + cap->capabilities = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | |
|---|
| 639 | + V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE | |
|---|
| 640 | + V4L2_CAP_VIDEO_CAPTURE | |
|---|
| 641 | + V4L2_CAP_DEVICE_CAPS; |
|---|
| 642 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 643 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 644 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 645 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 646 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 647 | + cap->capabilities |= V4L2_CAP_TUNER; |
|---|
| 648 | + break; |
|---|
| 649 | + default: |
|---|
| 650 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 651 | + cap->capabilities |= V4L2_CAP_TUNER; |
|---|
| 652 | + break; |
|---|
| 653 | + } |
|---|
| 656 | 654 | return 0; |
|---|
| 657 | 655 | } |
|---|
| 658 | 656 | |
|---|
| .. | .. |
|---|
| 662 | 660 | if (unlikely(f->index >= ARRAY_SIZE(formats))) |
|---|
| 663 | 661 | return -EINVAL; |
|---|
| 664 | 662 | |
|---|
| 665 | | - strlcpy(f->description, formats[f->index].name, |
|---|
| 666 | | - sizeof(f->description)); |
|---|
| 667 | 663 | f->pixelformat = formats[f->index].fourcc; |
|---|
| 668 | 664 | |
|---|
| 669 | 665 | return 0; |
|---|
| 670 | 666 | } |
|---|
| 671 | 667 | |
|---|
| 672 | | -static int vidioc_cropcap(struct file *file, void *priv, |
|---|
| 673 | | - struct v4l2_cropcap *cc) |
|---|
| 668 | +static int vidioc_g_pixelaspect(struct file *file, void *priv, |
|---|
| 669 | + int type, struct v4l2_fract *f) |
|---|
| 674 | 670 | { |
|---|
| 675 | 671 | struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 676 | 672 | bool is_50hz = dev->tvnorm & V4L2_STD_625_50; |
|---|
| 677 | 673 | |
|---|
| 678 | | - if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 674 | + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 679 | 675 | return -EINVAL; |
|---|
| 680 | 676 | |
|---|
| 681 | | - cc->bounds.left = 0; |
|---|
| 682 | | - cc->bounds.top = 0; |
|---|
| 683 | | - cc->bounds.width = 720; |
|---|
| 684 | | - cc->bounds.height = norm_maxh(dev->tvnorm); |
|---|
| 685 | | - cc->defrect = cc->bounds; |
|---|
| 686 | | - cc->pixelaspect.numerator = is_50hz ? 54 : 11; |
|---|
| 687 | | - cc->pixelaspect.denominator = is_50hz ? 59 : 10; |
|---|
| 677 | + f->numerator = is_50hz ? 54 : 11; |
|---|
| 678 | + f->denominator = is_50hz ? 59 : 10; |
|---|
| 688 | 679 | |
|---|
| 680 | + return 0; |
|---|
| 681 | +} |
|---|
| 682 | + |
|---|
| 683 | +static int vidioc_g_selection(struct file *file, void *fh, |
|---|
| 684 | + struct v4l2_selection *sel) |
|---|
| 685 | +{ |
|---|
| 686 | + struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 687 | + |
|---|
| 688 | + if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
|---|
| 689 | + return -EINVAL; |
|---|
| 690 | + |
|---|
| 691 | + switch (sel->target) { |
|---|
| 692 | + case V4L2_SEL_TGT_CROP_BOUNDS: |
|---|
| 693 | + case V4L2_SEL_TGT_CROP_DEFAULT: |
|---|
| 694 | + sel->r.top = 0; |
|---|
| 695 | + sel->r.left = 0; |
|---|
| 696 | + sel->r.width = 720; |
|---|
| 697 | + sel->r.height = norm_maxh(dev->tvnorm); |
|---|
| 698 | + break; |
|---|
| 699 | + default: |
|---|
| 700 | + return -EINVAL; |
|---|
| 701 | + } |
|---|
| 689 | 702 | return 0; |
|---|
| 690 | 703 | } |
|---|
| 691 | 704 | |
|---|
| .. | .. |
|---|
| 732 | 745 | |
|---|
| 733 | 746 | i->index = n; |
|---|
| 734 | 747 | i->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 735 | | - strcpy(i->name, iname[INPUT(n)->type]); |
|---|
| 748 | + strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name)); |
|---|
| 736 | 749 | i->std = CX23885_NORMS; |
|---|
| 737 | 750 | if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) || |
|---|
| 738 | 751 | (CX23885_VMUX_CABLE == INPUT(n)->type)) { |
|---|
| .. | .. |
|---|
| 829 | 842 | |
|---|
| 830 | 843 | memset(i, 0, sizeof(*i)); |
|---|
| 831 | 844 | i->index = n; |
|---|
| 832 | | - strcpy(i->name, iname[n]); |
|---|
| 845 | + strscpy(i->name, iname[n], sizeof(i->name)); |
|---|
| 833 | 846 | i->capability = V4L2_AUDCAP_STEREO; |
|---|
| 834 | 847 | return 0; |
|---|
| 835 | 848 | |
|---|
| .. | .. |
|---|
| 883 | 896 | { |
|---|
| 884 | 897 | struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 885 | 898 | |
|---|
| 886 | | - if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 887 | | - return -EINVAL; |
|---|
| 899 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 900 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 901 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 902 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 903 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 904 | + break; |
|---|
| 905 | + default: |
|---|
| 906 | + if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 907 | + return -EINVAL; |
|---|
| 908 | + break; |
|---|
| 909 | + } |
|---|
| 888 | 910 | if (0 != t->index) |
|---|
| 889 | 911 | return -EINVAL; |
|---|
| 890 | 912 | |
|---|
| 891 | | - strcpy(t->name, "Television"); |
|---|
| 913 | + strscpy(t->name, "Television", sizeof(t->name)); |
|---|
| 892 | 914 | |
|---|
| 893 | 915 | call_all(dev, tuner, g_tuner, t); |
|---|
| 894 | 916 | return 0; |
|---|
| .. | .. |
|---|
| 899 | 921 | { |
|---|
| 900 | 922 | struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 901 | 923 | |
|---|
| 902 | | - if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 903 | | - return -EINVAL; |
|---|
| 924 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 925 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 926 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 927 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 928 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 929 | + break; |
|---|
| 930 | + default: |
|---|
| 931 | + if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 932 | + return -EINVAL; |
|---|
| 933 | + break; |
|---|
| 934 | + } |
|---|
| 904 | 935 | if (0 != t->index) |
|---|
| 905 | 936 | return -EINVAL; |
|---|
| 906 | 937 | /* Update the A/V core */ |
|---|
| .. | .. |
|---|
| 914 | 945 | { |
|---|
| 915 | 946 | struct cx23885_dev *dev = video_drvdata(file); |
|---|
| 916 | 947 | |
|---|
| 917 | | - if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 918 | | - return -EINVAL; |
|---|
| 919 | | - |
|---|
| 948 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 949 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 950 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 951 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 952 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 953 | + break; |
|---|
| 954 | + default: |
|---|
| 955 | + if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 956 | + return -EINVAL; |
|---|
| 957 | + break; |
|---|
| 958 | + } |
|---|
| 920 | 959 | f->type = V4L2_TUNER_ANALOG_TV; |
|---|
| 921 | 960 | f->frequency = dev->freq; |
|---|
| 922 | 961 | |
|---|
| .. | .. |
|---|
| 930 | 969 | struct v4l2_ctrl *mute; |
|---|
| 931 | 970 | int old_mute_val = 1; |
|---|
| 932 | 971 | |
|---|
| 933 | | - if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 934 | | - return -EINVAL; |
|---|
| 972 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 973 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 974 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 975 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 976 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 977 | + break; |
|---|
| 978 | + default: |
|---|
| 979 | + if (dev->tuner_type == TUNER_ABSENT) |
|---|
| 980 | + return -EINVAL; |
|---|
| 981 | + break; |
|---|
| 982 | + } |
|---|
| 935 | 983 | if (unlikely(f->tuner != 0)) |
|---|
| 936 | 984 | return -EINVAL; |
|---|
| 937 | 985 | |
|---|
| .. | .. |
|---|
| 996 | 1044 | if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) || |
|---|
| 997 | 1045 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) || |
|---|
| 998 | 1046 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) || |
|---|
| 999 | | - (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4)) |
|---|
| 1047 | + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1265_K4) || |
|---|
| 1048 | + (dev->board == CX23885_BOARD_HAUPPAUGE_HVR5525) || |
|---|
| 1049 | + (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_DVB) || |
|---|
| 1050 | + (dev->board == CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC)) |
|---|
| 1000 | 1051 | fe = &dev->ts1.analog_fe; |
|---|
| 1001 | 1052 | |
|---|
| 1002 | 1053 | if (fe && fe->ops.tuner_ops.set_analog_params) { |
|---|
| .. | .. |
|---|
| 1027 | 1078 | case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: |
|---|
| 1028 | 1079 | case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 1029 | 1080 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
|---|
| 1081 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 1082 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 1083 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 1030 | 1084 | ret = cx23885_set_freq_via_ops(dev, f); |
|---|
| 1031 | 1085 | break; |
|---|
| 1032 | 1086 | default: |
|---|
| .. | .. |
|---|
| 1123 | 1177 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
|---|
| 1124 | 1178 | .vidioc_streamon = vb2_ioctl_streamon, |
|---|
| 1125 | 1179 | .vidioc_streamoff = vb2_ioctl_streamoff, |
|---|
| 1126 | | - .vidioc_cropcap = vidioc_cropcap, |
|---|
| 1180 | + .vidioc_g_pixelaspect = vidioc_g_pixelaspect, |
|---|
| 1181 | + .vidioc_g_selection = vidioc_g_selection, |
|---|
| 1127 | 1182 | .vidioc_s_std = vidioc_s_std, |
|---|
| 1128 | 1183 | .vidioc_g_std = vidioc_g_std, |
|---|
| 1129 | 1184 | .vidioc_enum_input = vidioc_enum_input, |
|---|
| .. | .. |
|---|
| 1187 | 1242 | |
|---|
| 1188 | 1243 | /* Initialize VBI template */ |
|---|
| 1189 | 1244 | cx23885_vbi_template = cx23885_video_template; |
|---|
| 1190 | | - strcpy(cx23885_vbi_template.name, "cx23885-vbi"); |
|---|
| 1245 | + strscpy(cx23885_vbi_template.name, "cx23885-vbi", |
|---|
| 1246 | + sizeof(cx23885_vbi_template.name)); |
|---|
| 1191 | 1247 | |
|---|
| 1192 | 1248 | dev->tvnorm = V4L2_STD_NTSC_M; |
|---|
| 1193 | 1249 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); |
|---|
| .. | .. |
|---|
| 1298 | 1354 | dev->video_dev = cx23885_vdev_init(dev, dev->pci, |
|---|
| 1299 | 1355 | &cx23885_video_template, "video"); |
|---|
| 1300 | 1356 | dev->video_dev->queue = &dev->vb2_vidq; |
|---|
| 1301 | | - err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, |
|---|
| 1357 | + dev->video_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | |
|---|
| 1358 | + V4L2_CAP_AUDIO | V4L2_CAP_VIDEO_CAPTURE; |
|---|
| 1359 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 1360 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 1361 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 1362 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 1363 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 1364 | + dev->video_dev->device_caps |= V4L2_CAP_TUNER; |
|---|
| 1365 | + break; |
|---|
| 1366 | + default: |
|---|
| 1367 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1368 | + dev->video_dev->device_caps |= V4L2_CAP_TUNER; |
|---|
| 1369 | + } |
|---|
| 1370 | + |
|---|
| 1371 | + err = video_register_device(dev->video_dev, VFL_TYPE_VIDEO, |
|---|
| 1302 | 1372 | video_nr[dev->nr]); |
|---|
| 1303 | 1373 | if (err < 0) { |
|---|
| 1304 | 1374 | pr_info("%s: can't register video device\n", |
|---|
| .. | .. |
|---|
| 1312 | 1382 | dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, |
|---|
| 1313 | 1383 | &cx23885_vbi_template, "vbi"); |
|---|
| 1314 | 1384 | dev->vbi_dev->queue = &dev->vb2_vbiq; |
|---|
| 1385 | + dev->vbi_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | |
|---|
| 1386 | + V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE; |
|---|
| 1387 | + switch (dev->board) { /* i2c device tuners */ |
|---|
| 1388 | + case CX23885_BOARD_HAUPPAUGE_HVR1265_K4: |
|---|
| 1389 | + case CX23885_BOARD_HAUPPAUGE_HVR5525: |
|---|
| 1390 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_DVB: |
|---|
| 1391 | + case CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC: |
|---|
| 1392 | + dev->vbi_dev->device_caps |= V4L2_CAP_TUNER; |
|---|
| 1393 | + break; |
|---|
| 1394 | + default: |
|---|
| 1395 | + if (dev->tuner_type != TUNER_ABSENT) |
|---|
| 1396 | + dev->vbi_dev->device_caps |= V4L2_CAP_TUNER; |
|---|
| 1397 | + } |
|---|
| 1315 | 1398 | err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, |
|---|
| 1316 | 1399 | vbi_nr[dev->nr]); |
|---|
| 1317 | 1400 | if (err < 0) { |
|---|