OSDN Git Service

media: cx231xx: Add i2c device analog tuner support
authorBrad Love <brad@nextdimension.cc>
Thu, 14 Nov 2019 20:04:05 +0000 (21:04 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 21 Apr 2020 14:50:05 +0000 (16:50 +0200)
The boards listed below use i2c device drivers and have
tuner_type equal TUNER_ABSENT. This means additional support
is required to enable the analog tuning capability, a case
statement is used to identify these models.

Models with analog tuning enabled:
- CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx (tested)
- CX231XX_BOARD_HAUPPAUGE_935C (tested)
- CX231XX_BOARD_HAUPPAUGE_955Q (tested)
- CX231XX_BOARD_HAUPPAUGE_975 (tested)
- CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD (untested)

The EvroMedia model was added, since it uses the si2157
tuner and the board profile claims it has analog inputs.

Signed-off-by: Brad Love <brad@nextdimension.cc>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/usb/cx231xx/cx231xx-avcore.c
drivers/media/usb/cx231xx/cx231xx-video.c

index 0974965..d611709 100644 (file)
@@ -587,14 +587,27 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
                                return status;
                        }
                }
-               if (dev->tuner_type == TUNER_NXP_TDA18271)
+               switch (dev->model) { /* i2c device tuners */
+               case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+               case CX231XX_BOARD_HAUPPAUGE_935C:
+               case CX231XX_BOARD_HAUPPAUGE_955Q:
+               case CX231XX_BOARD_HAUPPAUGE_975:
+               case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
                        status = cx231xx_set_decoder_video_input(dev,
                                                        CX231XX_VMUX_TELEVISION,
                                                        INPUT(input)->vmux);
-               else
-                       status = cx231xx_set_decoder_video_input(dev,
+                       break;
+               default:
+                       if (dev->tuner_type == TUNER_NXP_TDA18271)
+                               status = cx231xx_set_decoder_video_input(dev,
+                                                       CX231XX_VMUX_TELEVISION,
+                                                       INPUT(input)->vmux);
+                       else
+                               status = cx231xx_set_decoder_video_input(dev,
                                                        CX231XX_VMUX_COMPOSITE1,
                                                        INPUT(input)->vmux);
+                       break;
+               };
 
                break;
        default:
@@ -1193,12 +1206,22 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
                                        cx231xx_set_field(FLD_SIF_EN, 0));
                        break;
                default:
+                       switch (dev->model) { /* i2c device tuners */
+                       case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+                       case CX231XX_BOARD_HAUPPAUGE_935C:
+                       case CX231XX_BOARD_HAUPPAUGE_955Q:
+                       case CX231XX_BOARD_HAUPPAUGE_975:
+                       case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
+                       /* TODO: Normal mode: SIF passthrough at 14.32 MHz?? */
+                               break;
+                       default:
                        /* This is just a casual suggestion to people adding
                           new boards in case they use a tuner type we don't
                           currently know about */
-                       dev_info(dev->dev,
-                                "Unknown tuner type configuring SIF");
-                       break;
+                               dev_info(dev->dev,
+                                        "Unknown tuner type configuring SIF");
+                               break;
+                       }
                }
                break;
 
index 8bff7d8..d9f953f 100644 (file)
@@ -1129,7 +1129,7 @@ int cx231xx_s_frequency(struct file *file, void *priv,
 {
        struct cx231xx *dev = video_drvdata(file);
        struct v4l2_frequency new_freq = *f;
-       int rc;
+       int rc, need_if_freq = 0;
        u32 if_frequency = 5400000;
 
        dev_dbg(dev->dev,
@@ -1142,14 +1142,30 @@ int cx231xx_s_frequency(struct file *file, void *priv,
        /* set pre channel change settings in DIF first */
        rc = cx231xx_tuner_pre_channel_change(dev);
 
-       call_all(dev, tuner, s_frequency, f);
-       call_all(dev, tuner, g_frequency, &new_freq);
-       dev->ctl_freq = new_freq.frequency;
+       switch (dev->model) { /* i2c device tuners */
+       case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+       case CX231XX_BOARD_HAUPPAUGE_935C:
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
+       case CX231XX_BOARD_HAUPPAUGE_975:
+       case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
+               if (dev->cx231xx_set_analog_freq)
+                       dev->cx231xx_set_analog_freq(dev, f->frequency);
+               dev->ctl_freq = f->frequency;
+               need_if_freq = 1;
+               break;
+       default:
+               call_all(dev, tuner, s_frequency, f);
+               call_all(dev, tuner, g_frequency, &new_freq);
+               dev->ctl_freq = new_freq.frequency;
+               break;
+       }
+
+       pr_debug("%s() %u  :  %u\n", __func__, f->frequency, dev->ctl_freq);
 
        /* set post channel change settings in DIF first */
        rc = cx231xx_tuner_post_channel_change(dev);
 
-       if (dev->tuner_type == TUNER_NXP_TDA18271) {
+       if (need_if_freq || dev->tuner_type == TUNER_NXP_TDA18271) {
                if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
                        if_frequency = 5400000;  /*5.4MHz       */
                else if (dev->norm & V4L2_STD_B)
@@ -1362,9 +1378,20 @@ int cx231xx_querycap(struct file *file, void *priv,
                V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
        if (video_is_registered(&dev->radio_dev))
                cap->capabilities |= V4L2_CAP_RADIO;
-       if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
 
+       switch (dev->model) {
+       case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+       case CX231XX_BOARD_HAUPPAUGE_935C:
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
+       case CX231XX_BOARD_HAUPPAUGE_975:
+       case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
+               cap->capabilities |= V4L2_CAP_TUNER;
+               break;
+       default:
+               if (dev->tuner_type != TUNER_ABSENT)
+                       cap->capabilities |= V4L2_CAP_TUNER;
+               break;
+       }
        return 0;
 }
 
@@ -1708,10 +1735,20 @@ static void cx231xx_vdev_init(struct cx231xx *dev,
 
        video_set_drvdata(vfd, dev);
        if (dev->tuner_type == TUNER_ABSENT) {
-               v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
-               v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
-               v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
-               v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+               switch (dev->model) {
+               case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+               case CX231XX_BOARD_HAUPPAUGE_935C:
+               case CX231XX_BOARD_HAUPPAUGE_955Q:
+               case CX231XX_BOARD_HAUPPAUGE_975:
+               case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
+                       break;
+               default:
+                       v4l2_disable_ioctl(vfd, VIDIOC_G_FREQUENCY);
+                       v4l2_disable_ioctl(vfd, VIDIOC_S_FREQUENCY);
+                       v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
+                       v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
+                       break;
+               }
        }
 }
 
@@ -1781,8 +1818,20 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        dev->vdev.queue = q;
        dev->vdev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
                                V4L2_CAP_VIDEO_CAPTURE;
-       if (dev->tuner_type != TUNER_ABSENT)
+
+       switch (dev->model) { /* i2c device tuners */
+       case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+       case CX231XX_BOARD_HAUPPAUGE_935C:
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
+       case CX231XX_BOARD_HAUPPAUGE_975:
+       case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
                dev->vdev.device_caps |= V4L2_CAP_TUNER;
+               break;
+       default:
+               if (dev->tuner_type != TUNER_ABSENT)
+                       dev->vdev.device_caps |= V4L2_CAP_TUNER;
+               break;
+       }
 
        /* register v4l2 video video_device */
        ret = video_register_device(&dev->vdev, VFL_TYPE_VIDEO,
@@ -1829,8 +1878,18 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        dev->vbi_dev.queue = q;
        dev->vbi_dev.device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
                                   V4L2_CAP_VBI_CAPTURE;
-       if (dev->tuner_type != TUNER_ABSENT)
+       switch (dev->model) { /* i2c device tuners */
+       case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+       case CX231XX_BOARD_HAUPPAUGE_935C:
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
+       case CX231XX_BOARD_HAUPPAUGE_975:
+       case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
                dev->vbi_dev.device_caps |= V4L2_CAP_TUNER;
+               break;
+       default:
+               if (dev->tuner_type != TUNER_ABSENT)
+                       dev->vbi_dev.device_caps |= V4L2_CAP_TUNER;
+       }
 
        /* register v4l2 vbi video_device */
        ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,