From 3c1ccbad80802fa8bf807725db75a92d0887c9f2 Mon Sep 17 00:00:00 2001 From: Brad Love Date: Thu, 14 Nov 2019 21:04:05 +0100 Subject: media: cx231xx: Add i2c device analog tuner support 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 Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-avcore.c | 35 +++++++++--- drivers/media/usb/cx231xx/cx231xx-video.c | 85 +++++++++++++++++++++++++----- 2 files changed, 101 insertions(+), 19 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 0974965e848f..d6117093491b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -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; diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 8bff7d8a0310..d9f953f2d088 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -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, -- cgit v1.2.3-59-g8ed1b