summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/em28xx')
-rw-r--r--drivers/media/usb/em28xx/em28xx-audio.c116
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c49
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c905
-rw-r--r--drivers/media/usb/em28xx/em28xx-core.c231
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c1015
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c173
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c172
-rw-r--r--drivers/media/usb/em28xx/em28xx-reg.h52
-rw-r--r--drivers/media/usb/em28xx/em28xx-v4l.h27
-rw-r--r--drivers/media/usb/em28xx/em28xx-vbi.c39
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c391
-rw-r--r--drivers/media/usb/em28xx/em28xx.h396
12 files changed, 1916 insertions, 1650 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 4628d73..8e799ae 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -1,25 +1,25 @@
-/*
- * Empiatech em28x1 audio extension
- *
- * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
- *
- * Copyright (C) 2007-2016 Mauro Carvalho Chehab
- * - Port to work with the in-kernel driver
- * - Cleanups, fixes, alsa-controls, etc.
- *
- * This driver is based on my previous au600 usb pstn audio driver
- * and inherits all the copyrights
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Empiatech em28x1 audio extension
+//
+// Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
+//
+// Copyright (C) 2007-2016 Mauro Carvalho Chehab
+// - Port to work with the in-kernel driver
+// - Cleanups, fixes, alsa-controls, etc.
+//
+// This driver is based on my previous au600 usb pstn audio driver
+// and inherits all the copyrights
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -103,7 +103,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
case -ESHUTDOWN:
return;
default: /* error */
- dprintk("urb completition error %d.\n", urb->status);
+ dprintk("urb completion error %d.\n", urb->status);
break;
}
@@ -165,12 +165,11 @@ static void em28xx_audio_isocirq(struct urb *urb)
dev_err(&dev->intf->dev,
"resubmit of audio urb failed (error=%i)\n",
status);
- return;
}
static int em28xx_init_audio_isoc(struct em28xx *dev)
{
- int i, errCode;
+ int i, err;
dprintk("Starting isoc transfers\n");
@@ -179,16 +178,15 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
memset(dev->adev.transfer_buffer[i], 0x80,
dev->adev.urb[i]->transfer_buffer_length);
- errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
- if (errCode) {
+ err = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
+ if (err) {
dev_err(&dev->intf->dev,
"submit of audio urb failed (error=%i)\n",
- errCode);
+ err);
em28xx_deinit_isoc_audio(dev);
atomic_set(&dev->adev.stream_started, 0);
- return errCode;
+ return err;
}
-
}
return 0;
@@ -268,14 +266,17 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
- } else
+ } else {
mutex_lock(&dev->lock);
+ }
runtime->hw = snd_em28xx_hw_capture;
if (dev->adev.users == 0) {
- if (dev->alt == 0 || dev->is_audio_only) {
- struct usb_device *udev = interface_to_usbdev(dev->intf);
+ if (!dev->alt || dev->is_audio_only) {
+ struct usb_device *udev;
+
+ udev = interface_to_usbdev(dev->intf);
if (dev->is_audio_only)
/* audio is on a separate interface */
@@ -367,9 +368,11 @@ static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
#if 0
- /* TODO: set up em28xx audio chip to deliver the correct audio format,
- current default is 48000hz multiplexed => 96000hz mono
- which shouldn't matter since analogue TV only supports mono */
+ /*
+ * TODO: set up em28xx audio chip to deliver the correct audio format,
+ * current default is 48000hz multiplexed => 96000hz mono
+ * which shouldn't matter since analogue TV only supports mono
+ */
unsigned int channels, rate, format;
format = params_format(hw_params);
@@ -513,8 +516,9 @@ static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
- } else
+ } else {
mutex_lock(&dev->lock);
+ }
rc = em28xx_read_ac97(dev, kcontrol->private_value);
if (rc < 0)
goto err;
@@ -551,8 +555,9 @@ static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
- } else
+ } else {
mutex_lock(&dev->lock);
+ }
val = em28xx_read_ac97(dev, kcontrol->private_value);
mutex_unlock(&dev->lock);
if (val < 0)
@@ -586,8 +591,9 @@ static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
- } else
+ } else {
mutex_lock(&dev->lock);
+ }
rc = em28xx_read_ac97(dev, kcontrol->private_value);
if (rc < 0)
goto err;
@@ -627,8 +633,9 @@ static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
if (nonblock) {
if (!mutex_trylock(&dev->lock))
return -EAGAIN;
- } else
+ } else {
mutex_lock(&dev->lock);
+ }
val = em28xx_read_ac97(dev, kcontrol->private_value);
mutex_unlock(&dev->lock);
if (val < 0)
@@ -762,7 +769,7 @@ static int em28xx_audio_urb_init(struct em28xx *dev)
if (intf->num_altsetting <= alt) {
dev_err(&dev->intf->dev, "alt %d doesn't exist on interface %d\n",
- dev->ifnum, alt);
+ dev->ifnum, alt);
return -ENODEV;
}
@@ -836,9 +843,8 @@ static int em28xx_audio_urb_init(struct em28xx *dev)
dev->adev.transfer_buffer = kcalloc(num_urb,
sizeof(*dev->adev.transfer_buffer),
GFP_ATOMIC);
- if (!dev->adev.transfer_buffer) {
+ if (!dev->adev.transfer_buffer)
return -ENOMEM;
- }
dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_ATOMIC);
if (!dev->adev.urb) {
@@ -899,9 +905,11 @@ static int em28xx_audio_init(struct em28xx *dev)
int err;
if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) {
- /* This device does not support the extension (in this case
- the device is expecting the snd-usb-audio module or
- doesn't have analog audio support at all) */
+ /*
+ * This device does not support the extension (in this case
+ * the device is expecting the snd-usb-audio module or
+ * doesn't have analog audio support at all)
+ */
return 0;
}
@@ -977,13 +985,15 @@ card_free:
static int em28xx_audio_fini(struct em28xx *dev)
{
- if (dev == NULL)
+ if (!dev)
return 0;
if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR) {
- /* This device does not support the extension (in this case
- the device is expecting the snd-usb-audio module or
- doesn't have analog audio support at all) */
+ /*
+ * This device does not support the extension (in this case
+ * the device is expecting the snd-usb-audio module or
+ * doesn't have analog audio support at all)
+ */
return 0;
}
@@ -1005,7 +1015,7 @@ static int em28xx_audio_fini(struct em28xx *dev)
static int em28xx_audio_suspend(struct em28xx *dev)
{
- if (dev == NULL)
+ if (!dev)
return 0;
if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
@@ -1019,7 +1029,7 @@ static int em28xx_audio_suspend(struct em28xx *dev)
static int em28xx_audio_resume(struct em28xx *dev)
{
- if (dev == NULL)
+ if (!dev)
return 0;
if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
@@ -1050,7 +1060,7 @@ static void __exit em28xx_alsa_unregister(void)
em28xx_unregister_extension(&audio_ops);
}
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_DESCRIPTION(DRIVER_DESC " - audio interface");
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index ae87dd3..3c2694a 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -1,23 +1,19 @@
-/*
- em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices
-
- Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
- Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-camera.c - driver for Empia EM25xx/27xx/28xx USB video capture devices
+//
+// Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
+// Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -49,7 +45,7 @@ static int em28xx_initialize_mt9m111(struct em28xx *dev)
{ 0x0d, 0x00, 0x01, }, /* reset and use defaults */
{ 0x0d, 0x00, 0x00, },
{ 0x0a, 0x00, 0x21, },
- { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */
+ { 0x21, 0x04, 0x00, }, /* full readout spd, no row/col skip */
};
for (i = 0; i < ARRAY_SIZE(regs); i++)
@@ -157,7 +153,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev)
break;
default:
dev_info(&dev->intf->dev,
- "unknown Micron sensor detected: 0x%04x\n", id);
+ "unknown Micron sensor detected: 0x%04x\n",
+ id);
return 0;
}
@@ -186,8 +183,10 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
dev->em28xx_sensor = EM28XX_NOSENSOR;
- /* NOTE: these devices have the register auto incrementation disabled
- * by default, so we have to use single byte reads ! */
+ /*
+ * NOTE: these devices have the register auto incrementation disabled
+ * by default, so we have to use single byte reads !
+ */
for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) {
client->addr = omnivision_sensor_addrs[i];
/* Read manufacturer ID from registers 0x1c-0x1d (BE) */
@@ -397,7 +396,7 @@ int em28xx_init_camera(struct em28xx *dev)
subdev =
v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
&ov2640_info, NULL);
- if (subdev == NULL)
+ if (!subdev)
return -ENODEV;
format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 34e16f6a..6e0e67d 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -1,27 +1,23 @@
-/*
- em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
- video capture devices
-
- Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- Markus Rechberger <mrechberger@gmail.com>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Sascha Sommer <saschasommer@freenet.de>
- Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
+// video capture devices
+//
+// Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+// Markus Rechberger <mrechberger@gmail.com>
+// Mauro Carvalho Chehab <mchehab@infradead.org>
+// Sascha Sommer <saschasommer@freenet.de>
+// Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -40,7 +36,6 @@
#include <media/v4l2-common.h>
#include <sound/ac97_codec.h>
-
#define DRIVER_NAME "em28xx"
static int tuner = -1;
@@ -81,26 +76,26 @@ static void em28xx_pre_card_setup(struct em28xx *dev);
*/
/* Reset for the most [analog] boards */
-static struct em28xx_reg_seq default_analog[] = {
+static const struct em28xx_reg_seq default_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
/* Reset for the most [digital] boards */
-static struct em28xx_reg_seq default_digital[] = {
+static const struct em28xx_reg_seq default_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
/* Board Hauppauge WinTV HVR 900 analog */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
+static const struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x2d, ~EM_GPIO_4, 10},
{ 0x05, 0xff, 0x10, 10},
{ -1, -1, -1, -1},
};
/* Board Hauppauge WinTV HVR 900 digital */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
+static const struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x04, 0x0f, 10},
{EM2880_R04_GPO, 0x0c, 0x0f, 10},
@@ -108,25 +103,20 @@ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
};
/* Board Hauppauge WinTV HVR 900 (R2) digital */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = {
+static const struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x0c, 0x0f, 10},
{ -1, -1, -1, -1},
};
/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
-static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
+static const struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x69, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
-/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
-
-/* Board - EM2870 Kworld 355u
- Analog - No input analog */
-
/* Board - EM2882 Kworld 315U digital */
-static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
+static const struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10},
{EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10},
{EM2880_R04_GPO, 0x04, 0xff, 10},
@@ -135,7 +125,7 @@ static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
+static const struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
{EM2880_R04_GPO, 0x08, 0xff, 10},
{EM2880_R04_GPO, 0x0c, 0xff, 10},
{EM2880_R04_GPO, 0x08, 0xff, 10},
@@ -143,30 +133,31 @@ static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq kworld_330u_analog[] = {
+static const struct em28xx_reg_seq kworld_330u_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x00, 0xff, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq kworld_330u_digital[] = {
+static const struct em28xx_reg_seq kworld_330u_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x08, 0xff, 10},
{ -1, -1, -1, -1},
};
-/* Evga inDtube
- GPIO0 - Enable digital power (s5h1409) - low to enable
- GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
- GPIO4 - xc3028 reset
- GOP3 - s5h1409 reset
+/*
+ * Evga inDtube
+ * GPIO0 - Enable digital power (s5h1409) - low to enable
+ * GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
+ * GPIO4 - xc3028 reset
+ * GOP3 - s5h1409 reset
*/
-static struct em28xx_reg_seq evga_indtube_analog[] = {
+static const struct em28xx_reg_seq evga_indtube_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x79, 0xff, 60},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq evga_indtube_digital[] = {
+static const struct em28xx_reg_seq evga_indtube_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x7a, 0xff, 1},
{EM2880_R04_GPO, 0x04, 0xff, 10},
{EM2880_R04_GPO, 0x0c, 0xff, 1},
@@ -184,12 +175,12 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
* EM_GPIO_6 - currently unknown
* EM_GPIO_7 - currently unknown
*/
-static struct em28xx_reg_seq kworld_a340_digital[] = {
+static const struct em28xx_reg_seq kworld_a340_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq kworld_ub435q_v3_digital[] = {
+static const struct em28xx_reg_seq kworld_ub435q_v3_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xbe, 0xff, 100},
@@ -198,45 +189,49 @@ static struct em28xx_reg_seq kworld_ub435q_v3_digital[] = {
};
/* Pinnacle Hybrid Pro eb1a:2881 */
-static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
+static const struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
{EM2820_R08_GPIO_CTRL, 0xfd, ~EM_GPIO_4, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
+static const struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */
{EM2880_R04_GPO, 0x0c, 0xff, 1},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = {
+static const struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = {
{EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x00, 0xff, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = {
+static const struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x08, 0xff, 10},
{ -1, -1, -1, -1},
};
-/* PCTV HD Mini (80e) GPIOs
- 0-5: not used
- 6: demod reset, active low
- 7: LED on, active high */
-static struct em28xx_reg_seq em2874_pctv_80e_digital[] = {
+/*
+ * PCTV HD Mini (80e) GPIOs
+ * 0-5: not used
+ * 6: demod reset, active low
+ * 7: LED on, active high
+ */
+static const struct em28xx_reg_seq em2874_pctv_80e_digital[] = {
{EM28XX_R06_I2C_CLK, 0x45, 0xff, 10}, /*400 KHz*/
{EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 100},/*Demod reset*/
{EM2874_R80_GPIO_P0_CTRL, 0x40, 0xff, 10},
{ -1, -1, -1, -1},
};
-/* eb1a:2868 Reddo DVB-C USB TV Box
- GPIO4 - CU1216L NIM
- Other GPIOs seems to be don't care. */
-static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = {
+/*
+ * eb1a:2868 Reddo DVB-C USB TV Box
+ * GPIO4 - CU1216L NIM
+ * Other GPIOs seems to be don't care.
+ */
+static const struct em28xx_reg_seq reddo_dvb_c_usb_box[] = {
{EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10},
{EM2820_R08_GPIO_CTRL, 0xde, 0xff, 10},
{EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10},
@@ -248,7 +243,7 @@ static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = {
};
/* Callback for the most boards */
-static struct em28xx_reg_seq default_tuner_gpio[] = {
+static const struct em28xx_reg_seq default_tuner_gpio[] = {
{EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10},
{EM2820_R08_GPIO_CTRL, 0, EM_GPIO_4, 10},
{EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10},
@@ -256,69 +251,70 @@ static struct em28xx_reg_seq default_tuner_gpio[] = {
};
/* Mute/unmute */
-static struct em28xx_reg_seq compro_unmute_tv_gpio[] = {
+static const struct em28xx_reg_seq compro_unmute_tv_gpio[] = {
{EM2820_R08_GPIO_CTRL, 5, 7, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq compro_unmute_svid_gpio[] = {
+static const struct em28xx_reg_seq compro_unmute_svid_gpio[] = {
{EM2820_R08_GPIO_CTRL, 4, 7, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq compro_mute_gpio[] = {
+static const struct em28xx_reg_seq compro_mute_gpio[] = {
{EM2820_R08_GPIO_CTRL, 6, 7, 10},
{ -1, -1, -1, -1},
};
/* Terratec AV350 */
-static struct em28xx_reg_seq terratec_av350_mute_gpio[] = {
+static const struct em28xx_reg_seq terratec_av350_mute_gpio[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0x7f, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
+static const struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq silvercrest_reg_seq[] = {
+static const struct em28xx_reg_seq silvercrest_reg_seq[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10},
{EM2820_R08_GPIO_CTRL, 0x01, 0xf7, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq vc211a_enable[] = {
+static const struct em28xx_reg_seq vc211a_enable[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0x07, 10},
{EM2820_R08_GPIO_CTRL, 0xff, 0x0f, 10},
{EM2820_R08_GPIO_CTRL, 0xff, 0x0b, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq dikom_dk300_digital[] = {
+static const struct em28xx_reg_seq dikom_dk300_digital[] = {
{EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x08, 0xff, 10},
{ -1, -1, -1, -1},
};
/* Reset for the most [digital] boards */
-static struct em28xx_reg_seq leadership_digital[] = {
+static const struct em28xx_reg_seq leadership_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x70, 0xff, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq leadership_reset[] = {
+static const struct em28xx_reg_seq leadership_reset[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xb0, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10},
{ -1, -1, -1, -1},
};
-/* 2013:024f PCTV nanoStick T2 290e
+/*
+ * 2013:024f PCTV nanoStick T2 290e
* GPIO_6 - demod reset
* GPIO_7 - LED
*/
-static struct em28xx_reg_seq pctv_290e[] = {
+static const struct em28xx_reg_seq pctv_290e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 80},
{EM2874_R80_GPIO_P0_CTRL, 0x40, 0xff, 80}, /* GPIO_6 = 1 */
{EM2874_R80_GPIO_P0_CTRL, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */
@@ -326,7 +322,7 @@ static struct em28xx_reg_seq pctv_290e[] = {
};
#if 0
-static struct em28xx_reg_seq terratec_h5_gpio[] = {
+static const struct em28xx_reg_seq terratec_h5_gpio[] = {
{EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50},
@@ -334,7 +330,7 @@ static struct em28xx_reg_seq terratec_h5_gpio[] = {
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_h5_digital[] = {
+static const struct em28xx_reg_seq terratec_h5_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10},
@@ -342,7 +338,8 @@ static struct em28xx_reg_seq terratec_h5_digital[] = {
};
#endif
-/* 2013:024f PCTV DVB-S2 Stick 460e
+/*
+ * 2013:024f PCTV DVB-S2 Stick 460e
* GPIO_0 - POWER_ON
* GPIO_1 - BOOST
* GPIO_2 - VUV_LNB (red LED)
@@ -352,7 +349,7 @@ static struct em28xx_reg_seq terratec_h5_digital[] = {
* GPIO_6 - RESET_DEM
* GPIO_7 - LED (green LED)
*/
-static struct em28xx_reg_seq pctv_460e[] = {
+static const struct em28xx_reg_seq pctv_460e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x01, 0xff, 50},
{ 0x0d, 0xff, 0xff, 50},
{EM2874_R80_GPIO_P0_CTRL, 0x41, 0xff, 50}, /* GPIO_6=1 */
@@ -361,7 +358,7 @@ static struct em28xx_reg_seq pctv_460e[] = {
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq c3tech_digital_duo_digital[] = {
+static const struct em28xx_reg_seq c3tech_digital_duo_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, /* xc5000 reset */
{EM2874_R80_GPIO_P0_CTRL, 0xf9, 0xff, 35},
@@ -384,7 +381,7 @@ static struct em28xx_reg_seq c3tech_digital_duo_digital[] = {
* GPIO 6 = #RESET_DEM
* GPIO 7 = P07_LED (green LED)
*/
-static struct em28xx_reg_seq pctv_461e[] = {
+static const struct em28xx_reg_seq pctv_461e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x7f, 0xff, 0},
{0x0d, 0xff, 0xff, 0},
{EM2874_R80_GPIO_P0_CTRL, 0x3f, 0xff, 100}, /* reset demod */
@@ -396,7 +393,7 @@ static struct em28xx_reg_seq pctv_461e[] = {
};
#if 0
-static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
+static const struct em28xx_reg_seq hauppauge_930c_gpio[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0x4f, 0xff, 10}, /* xc5000 reset */
{EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10},
@@ -404,7 +401,7 @@ static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq hauppauge_930c_digital[] = {
+static const struct em28xx_reg_seq hauppauge_930c_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10},
@@ -412,38 +409,41 @@ static struct em28xx_reg_seq hauppauge_930c_digital[] = {
};
#endif
-/* 1b80:e425 MaxMedia UB425-TC
+/*
+ * 1b80:e425 MaxMedia UB425-TC
* 1b80:e1cc Delock 61959
* GPIO_6 - demod reset, 0=active
* GPIO_7 - LED, 0=active
*/
-static struct em28xx_reg_seq maxmedia_ub425_tc[] = {
+static const struct em28xx_reg_seq maxmedia_ub425_tc[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x83, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */
{EM2874_R80_GPIO_P0_CTRL, 0x43, 0xff, 000}, /* GPIO_7 = 0 */
{ -1, -1, -1, -1},
};
-/* 2304:0242 PCTV QuatroStick (510e)
+/*
+ * 2304:0242 PCTV QuatroStick (510e)
* GPIO_2: decoder reset, 0=active
* GPIO_4: decoder suspend, 0=active
* GPIO_6: demod reset, 0=active
* GPIO_7: LED, 1=active
*/
-static struct em28xx_reg_seq pctv_510e[] = {
+static const struct em28xx_reg_seq pctv_510e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
{EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
{ -1, -1, -1, -1},
};
-/* 2013:0251 PCTV QuatroStick nano (520e)
+/*
+ * 2013:0251 PCTV QuatroStick nano (520e)
* GPIO_2: decoder reset, 0=active
* GPIO_4: decoder suspend, 0=active
* GPIO_6: demod reset, 0=active
* GPIO_7: LED, 1=active
*/
-static struct em28xx_reg_seq pctv_520e[] = {
+static const struct em28xx_reg_seq pctv_520e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
{EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
@@ -451,7 +451,8 @@ static struct em28xx_reg_seq pctv_520e[] = {
{ -1, -1, -1, -1},
};
-/* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam
+/*
+ * 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam
* reg 0x80/0x84:
* GPIO_0: capturing LED, 0=on, 1=off
* GPIO_2: AV mute button, 0=pressed, 1=unpressed
@@ -460,13 +461,13 @@ static struct em28xx_reg_seq pctv_520e[] = {
* reg 0x81/0x85:
* GPIO_7: snapshot button, 0=pressed, 1=unpressed
*/
-static struct em28xx_reg_seq speedlink_vad_laplace_reg_seq[] = {
+static const struct em28xx_reg_seq speedlink_vad_laplace_reg_seq[] = {
{EM2820_R08_GPIO_CTRL, 0xf7, 0xff, 10},
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xb2, 10},
{ -1, -1, -1, -1},
};
-static struct em28xx_reg_seq pctv_292e[] = {
+static const struct em28xx_reg_seq pctv_292e[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
{0x0d, 0xff, 0xff, 950},
{EM2874_R80_GPIO_P0_CTRL, 0xbd, 0xff, 100},
@@ -478,7 +479,7 @@ static struct em28xx_reg_seq pctv_292e[] = {
{-1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
+static const struct em28xx_reg_seq terratec_t2_stick_hd[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
{0x0d, 0xff, 0xff, 600},
{EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 10},
@@ -492,7 +493,7 @@ static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
{-1, -1, -1, -1},
};
-static struct em28xx_reg_seq plex_px_bcud[] = {
+static const struct em28xx_reg_seq plex_px_bcud[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
{0x0d, 0xff, 0xff, 0},
{EM2874_R50_IR_CONFIG, 0x01, 0xff, 0},
@@ -507,8 +508,10 @@ static struct em28xx_reg_seq plex_px_bcud[] = {
};
/*
- * 2040:0265 Hauppauge WinTV-dualHD DVB
- * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM
+ * 2040:0265 Hauppauge WinTV-dualHD DVB Isoc
+ * 2040:8265 Hauppauge WinTV-dualHD DVB Bulk
+ * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM Isoc
+ * 2040:826d Hauppauge WinTV-dualHD ATSC/QAM Bulk
* reg 0x80/0x84:
* GPIO_0: Yellow LED tuner 1, 0=on, 1=off
* GPIO_1: Green LED tuner 1, 0=on, 1=off
@@ -517,7 +520,7 @@ static struct em28xx_reg_seq plex_px_bcud[] = {
* GPIO_5: Reset #2, 0=active
* GPIO_6: Reset #1, 0=active
*/
-static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = {
+static const struct em28xx_reg_seq hauppauge_dualhd_dvb[] = {
{EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
{0x0d, 0xff, 0xff, 200},
{0x50, 0x04, 0xff, 300},
@@ -534,7 +537,7 @@ static struct em28xx_reg_seq hauppauge_dualhd_dvb[] = {
/*
* Button definitions
*/
-static struct em28xx_button std_snapshot_button[] = {
+static const struct em28xx_button std_snapshot_button[] = {
{
.role = EM28XX_BUTTON_SNAPSHOT,
.reg_r = EM28XX_R0C_USBSUSP,
@@ -545,7 +548,7 @@ static struct em28xx_button std_snapshot_button[] = {
{-1, 0, 0, 0, 0},
};
-static struct em28xx_button speedlink_vad_laplace_buttons[] = {
+static const struct em28xx_button speedlink_vad_laplace_buttons[] = {
{
.role = EM28XX_BUTTON_SNAPSHOT,
.reg_r = EM2874_R85_GPIO_P1_STATE,
@@ -629,7 +632,7 @@ static struct em28xx_led hauppauge_dualhd_leds[] = {
/*
* Board definitions
*/
-struct em28xx_board em28xx_boards[] = {
+const struct em28xx_board em28xx_boards[] = {
[EM2750_BOARD_UNKNOWN] = {
.name = "EM2710/EM2750/EM2751 webcam grabber",
.xclk = EM28XX_XCLK_FREQUENCY_20MHZ,
@@ -1436,9 +1439,11 @@ struct em28xx_board em28xx_boards[] = {
.gpio = default_analog,
} },
},
- /* maybe there's a reason behind it why Terratec sells the Hybrid XS
- as Prodigy XS with a different PID, let's keep it separated for now
- maybe we'll need it lateron */
+ /*
+ * maybe there's a reason behind it why Terratec sells the Hybrid XS
+ * as Prodigy XS with a different PID, let's keep it separated for now
+ * maybe we'll need it later on
+ */
[EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
.name = "Terratec Prodigy XS",
.tuner_type = TUNER_XC2028,
@@ -1782,8 +1787,9 @@ struct em28xx_board em28xx_boards[] = {
.ir_codes = RC_MAP_KWORLD_315U,
.xclk = EM28XX_XCLK_FREQUENCY_12MHZ,
.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE,
- /* Analog mode - still not ready */
- /*.input = { {
+#if 0
+ /* FIXME: Analog mode - still not ready */
+ .input = { {
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = EM28XX_AMUX_VIDEO,
@@ -1801,7 +1807,8 @@ struct em28xx_board em28xx_boards[] = {
.amux = EM28XX_AMUX_LINE_IN,
.gpio = em2882_kworld_315u_analog1,
.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
- } }, */
+ } },
+#endif
},
[EM2880_BOARD_EMPIRE_DUAL_TV] = {
.name = "Empire dual TV",
@@ -2162,17 +2169,21 @@ struct em28xx_board em28xx_boards[] = {
.gpio = evga_indtube_analog,
} },
},
- /* eb1a:2868 Empia EM2870 + Philips CU1216L NIM (Philips TDA10023 +
- Infineon TUA6034) */
+ /*
+ * eb1a:2868 Empia EM2870 + Philips CU1216L NIM
+ * (Philips TDA10023 + Infineon TUA6034)
+ */
[EM2870_BOARD_REDDO_DVB_C_USB_BOX] = {
.name = "Reddo DVB-C USB TV Box",
.tuner_type = TUNER_ABSENT,
.tuner_gpio = reddo_dvb_c_usb_box,
.has_dvb = 1,
},
- /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
+ /*
+ * 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
* initially as the KWorld PlusTV 340U, then as the UB435-Q.
- * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */
+ * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2
+ */
[EM2870_BOARD_KWORLD_A340] = {
.name = "KWorld PlusTV 340U or UB435-Q (ATSC)",
.tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */
@@ -2180,30 +2191,38 @@ struct em28xx_board em28xx_boards[] = {
.dvb_gpio = kworld_a340_digital,
.tuner_gpio = default_tuner_gpio,
},
- /* 2013:024f PCTV nanoStick T2 290e.
- * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
+ /*
+ * 2013:024f PCTV nanoStick T2 290e.
+ * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2
+ */
[EM28174_BOARD_PCTV_290E] = {
.name = "PCTV nanoStick T2 290e",
.def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_100_KHZ,
.tuner_type = TUNER_ABSENT,
.tuner_gpio = pctv_290e,
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
- /* 2013:024f PCTV DVB-S2 Stick 460e
- * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+ /*
+ * 2013:024f PCTV DVB-S2 Stick 460e
+ * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293
+ */
[EM28174_BOARD_PCTV_460E] = {
.def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
.name = "PCTV DVB-S2 Stick (460e)",
.tuner_type = TUNER_ABSENT,
.tuner_gpio = pctv_460e,
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
- /* eb1a:5006 Honestech VIDBOX NW03
- * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */
+ /*
+ * eb1a:5006 Honestech VIDBOX NW03
+ * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner
+ */
[EM2860_BOARD_HT_VIDBOX_NW03] = {
.name = "Honestech Vidbox NW03",
.tuner_type = TUNER_ABSENT,
@@ -2214,12 +2233,14 @@ struct em28xx_board em28xx_boards[] = {
.amux = EM28XX_AMUX_LINE_IN,
}, {
.type = EM28XX_VMUX_SVIDEO,
- .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */
+ .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs check */
.amux = EM28XX_AMUX_LINE_IN,
} },
},
- /* 1b80:e425 MaxMedia UB425-TC
- * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */
+ /*
+ * 1b80:e425 MaxMedia UB425-TC
+ * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2
+ */
[EM2874_BOARD_MAXMEDIA_UB425_TC] = {
.name = "MaxMedia UB425-TC",
.tuner_type = TUNER_ABSENT,
@@ -2230,8 +2251,10 @@ struct em28xx_board em28xx_boards[] = {
.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
EM28XX_I2C_FREQ_400_KHZ,
},
- /* 2304:0242 PCTV QuatroStick (510e)
- * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
+ /*
+ * 2304:0242 PCTV QuatroStick (510e)
+ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2
+ */
[EM2884_BOARD_PCTV_510E] = {
.name = "PCTV QuatroStick (510e)",
.tuner_type = TUNER_ABSENT,
@@ -2242,8 +2265,10 @@ struct em28xx_board em28xx_boards[] = {
.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
EM28XX_I2C_FREQ_400_KHZ,
},
- /* 2013:0251 PCTV QuatroStick nano (520e)
- * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
+ /*
+ * 2013:0251 PCTV QuatroStick nano (520e)
+ * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2
+ */
[EM2884_BOARD_PCTV_520E] = {
.name = "PCTV QuatroStick nano (520e)",
.tuner_type = TUNER_ABSENT,
@@ -2263,9 +2288,11 @@ struct em28xx_board em28xx_boards[] = {
.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
EM28XX_I2C_FREQ_400_KHZ,
},
- /* 1b80:e1cc Delock 61959
+ /*
+ * 1b80:e1cc Delock 61959
* Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2
- * mostly the same as MaxMedia UB-425-TC but different remote */
+ * mostly the same as MaxMedia UB-425-TC but different remote
+ */
[EM2874_BOARD_DELOCK_61959] = {
.name = "Delock 61959",
.tuner_type = TUNER_ABSENT,
@@ -2311,8 +2338,10 @@ struct em28xx_board em28xx_boards[] = {
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
.leds = pctv_80e_leds,
},
- /* 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam
- * Empia EM2765 + OmniVision OV2640 */
+ /*
+ * 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam
+ * Empia EM2765 + OmniVision OV2640
+ */
[EM2765_BOARD_SPEEDLINK_VAD_LAPLACE] = {
.name = "SpeedLink Vicious And Devine Laplace webcam",
.xclk = EM28XX_XCLK_FREQUENCY_24MHZ,
@@ -2329,23 +2358,29 @@ struct em28xx_board em28xx_boards[] = {
.buttons = speedlink_vad_laplace_buttons,
.leds = speedlink_vad_laplace_leds,
},
- /* 2013:0258 PCTV DVB-S2 Stick (461e)
- * Empia EM28178, Montage M88DS3103, Montage M88TS2022, Allegro A8293 */
+ /*
+ * 2013:0258 PCTV DVB-S2 Stick (461e)
+ * Empia EM28178, Montage M88DS3103, Montage M88TS2022, Allegro A8293
+ */
[EM28178_BOARD_PCTV_461E] = {
.def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
.name = "PCTV DVB-S2 Stick (461e)",
.tuner_type = TUNER_ABSENT,
.tuner_gpio = pctv_461e,
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
- /* 2013:025f PCTV tripleStick (292e).
- * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157 */
+ /*
+ * 2013:025f PCTV tripleStick (292e).
+ * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2157
+ */
[EM28178_BOARD_PCTV_292E] = {
.name = "PCTV tripleStick (292e)",
.def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
.tuner_type = TUNER_ABSENT,
.tuner_gpio = pctv_292e,
.has_dvb = 1,
@@ -2365,12 +2400,15 @@ struct em28xx_board em28xx_boards[] = {
.amux = EM28XX_AMUX_LINE_IN,
} },
},
- /* eb1a:8179 Terratec Cinergy T2 Stick HD.
- * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2146 */
+ /*
+ * eb1a:8179 Terratec Cinergy T2 Stick HD.
+ * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2146
+ */
[EM28178_BOARD_TERRATEC_T2_STICK_HD] = {
.name = "Terratec Cinergy T2 Stick HD",
.def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_400_KHZ,
.tuner_type = TUNER_ABSENT,
.tuner_gpio = terratec_t2_stick_hd,
.has_dvb = 1,
@@ -2391,7 +2429,8 @@ struct em28xx_board em28xx_boards[] = {
.has_dvb = 1,
},
/*
- * 2040:0265 Hauppauge WinTV-dualHD (DVB version).
+ * 2040:0265 Hauppauge WinTV-dualHD (DVB version) Isoc.
+ * 2040:8265 Hauppauge WinTV-dualHD (DVB version) Bulk.
* Empia EM28274, 2x Silicon Labs Si2168, 2x Silicon Labs Si2157
*/
[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB] = {
@@ -2402,11 +2441,13 @@ struct em28xx_board em28xx_boards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_gpio = hauppauge_dualhd_dvb,
.has_dvb = 1,
+ .has_dual_ts = 1,
.ir_codes = RC_MAP_HAUPPAUGE,
.leds = hauppauge_dualhd_leds,
},
/*
- * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM).
+ * 2040:026d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Isoc.
+ * 2040:826d Hauppauge WinTV-dualHD (model 01595 - ATSC/QAM) Bulk.
* Empia EM28274, 2x LG LGDT3306A, 2x Silicon Labs Si2157
*/
[EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595] = {
@@ -2417,6 +2458,7 @@ struct em28xx_board em28xx_boards[] = {
.tuner_type = TUNER_ABSENT,
.tuner_gpio = hauppauge_dualhd_dvb,
.has_dvb = 1,
+ .has_dual_ts = 1,
.ir_codes = RC_MAP_HAUPPAUGE,
.leds = hauppauge_dualhd_leds,
},
@@ -2485,10 +2527,10 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2870_BOARD_KWORLD_355U },
{ USB_DEVICE(0xeb1a, 0xe359),
.driver_info = EM2870_BOARD_KWORLD_355U },
- { USB_DEVICE(0x1b80, 0xe302),
- .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
- { USB_DEVICE(0x1b80, 0xe304),
- .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */
+ { USB_DEVICE(0x1b80, 0xe302), /* Kaiser Baas Video to DVD maker */
+ .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+ { USB_DEVICE(0x1b80, 0xe304), /* Kworld DVD Maker 2 */
+ .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
{ USB_DEVICE(0x0ccd, 0x0036),
.driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
{ USB_DEVICE(0x0ccd, 0x004c),
@@ -2547,8 +2589,12 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 },
{ USB_DEVICE(0x2040, 0x0265),
.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
+ { USB_DEVICE(0x2040, 0x8265),
+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB },
{ USB_DEVICE(0x2040, 0x026d),
.driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 },
+ { USB_DEVICE(0x2040, 0x826d),
+ .driver_info = EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 },
{ USB_DEVICE(0x0438, 0xb002),
.driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
{ USB_DEVICE(0x2001, 0xf112),
@@ -2609,7 +2655,13 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM28178_BOARD_PCTV_461E },
{ USB_DEVICE(0x2013, 0x025f),
.driver_info = EM28178_BOARD_PCTV_292E },
- { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD */
+ { USB_DEVICE(0x2013, 0x0264), /* Hauppauge WinTV-soloHD 292e SE */
+ .driver_info = EM28178_BOARD_PCTV_292E },
+ { USB_DEVICE(0x2040, 0x0264), /* Hauppauge WinTV-soloHD Isoc */
+ .driver_info = EM28178_BOARD_PCTV_292E },
+ { USB_DEVICE(0x2040, 0x8264), /* Hauppauge OEM Generic WinTV-soloHD Bulk */
+ .driver_info = EM28178_BOARD_PCTV_292E },
+ { USB_DEVICE(0x2040, 0x8268), /* Hauppauge Retail WinTV-soloHD Bulk */
.driver_info = EM28178_BOARD_PCTV_292E },
{ USB_DEVICE(0x0413, 0x6f07),
.driver_info = EM2861_BOARD_LEADTEK_VC100 },
@@ -2626,7 +2678,7 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table);
/*
* EEPROM hash table for devices with generic USB IDs
*/
-static struct em28xx_hash_table em28xx_eeprom_hash[] = {
+static const struct em28xx_hash_table em28xx_eeprom_hash[] = {
/* P/N: SA 60002070465 Tuner: TVF7533-MF */
{0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
{0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
@@ -2639,7 +2691,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
};
/* I2C devicelist hash table for devices with generic USB IDs */
-static struct em28xx_hash_table em28xx_i2c_hash[] = {
+static const struct em28xx_hash_table em28xx_i2c_hash[] = {
{0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
{0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT},
@@ -2669,26 +2721,46 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
}
EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
-static inline void em28xx_set_model(struct em28xx *dev)
+static inline void em28xx_set_xclk_i2c_speed(struct em28xx *dev)
{
- dev->board = em28xx_boards[dev->model];
+ const struct em28xx_board *board = &em28xx_boards[dev->model];
+ u8 xclk = board->xclk, i2c_speed = board->i2c_speed;
- /* Those are the default values for the majority of boards
- Use those values if not specified otherwise at boards entry
+ /*
+ * Those are the default values for the majority of boards
+ * Use those values if not specified otherwise at boards entry
*/
- if (!dev->board.xclk)
- dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE |
- EM28XX_XCLK_FREQUENCY_12MHZ;
+ if (!xclk)
+ xclk = EM28XX_XCLK_IR_RC5_MODE |
+ EM28XX_XCLK_FREQUENCY_12MHZ;
+
+ em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk);
- if (!dev->board.i2c_speed)
- dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
- EM28XX_I2C_FREQ_100_KHZ;
+ if (!i2c_speed)
+ i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+ EM28XX_I2C_FREQ_100_KHZ;
+
+ dev->i2c_speed = i2c_speed & 0x03;
+
+ if (!dev->board.is_em2800)
+ em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, i2c_speed);
+ msleep(50);
+}
+
+static inline void em28xx_set_model(struct em28xx *dev)
+{
+ dev->board = em28xx_boards[dev->model];
+ dev->has_msp34xx = dev->board.has_msp34xx;
+ dev->is_webcam = dev->board.is_webcam;
+
+ em28xx_set_xclk_i2c_speed(dev);
/* Should be initialized early, for I2C to work */
dev->def_i2c_bus = dev->board.def_i2c_bus;
}
-/* Wait until AC97_RESET reports the expected value reliably before proceeding.
+/*
+ * Wait until AC97_RESET reports the expected value reliably before proceeding.
* We also check that two unrelated registers accesses don't return the same
* value to avoid premature return.
* This procedure helps ensuring AC97 register accesses are reliable.
@@ -2718,17 +2790,17 @@ static int em28xx_wait_until_ac97_features_equals(struct em28xx *dev,
return -ETIMEDOUT;
}
-/* Since em28xx_pre_card_setup() requires a proper dev->model,
+/*
+ * Since em28xx_pre_card_setup() requires a proper dev->model,
* this won't work for boards with generic PCI IDs
*/
static void em28xx_pre_card_setup(struct em28xx *dev)
{
- /* Set the initial XCLK and I2C clock values based on the board
- definition */
- em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
- if (!dev->board.is_em2800)
- em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
- msleep(50);
+ /*
+ * Set the initial XCLK and I2C clock values based on the board
+ * definition
+ */
+ em28xx_set_xclk_i2c_speed(dev);
/* request some modules */
switch (dev->model) {
@@ -2739,17 +2811,19 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
case EM2861_BOARD_KWORLD_PVRTV_300U:
case EM2880_BOARD_KWORLD_DVB_305U:
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x6d);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x7d);
- msleep(10);
+ usleep_range(10000, 11000);
break;
case EM2870_BOARD_COMPRO_VIDEOMATE:
- /* TODO: someone can do some cleanup here...
- not everything's needed */
+ /*
+ * TODO: someone can do some cleanup here...
+ * not everything's needed
+ */
em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2880_R04_GPO, 0x01);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd);
mdelay(70);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfc);
@@ -2760,8 +2834,10 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
mdelay(70);
break;
case EM2870_BOARD_TERRATEC_XS_MT2060:
- /* this device needs some gpio writes to get the DVB-T
- demod work */
+ /*
+ * this device needs some gpio writes to get the DVB-T
+ * demod work
+ */
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe);
mdelay(70);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde);
@@ -2770,8 +2846,10 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
mdelay(70);
break;
case EM2870_BOARD_PINNACLE_PCTV_DVB:
- /* this device needs some gpio writes to get the
- DVB-T demod work */
+ /*
+ * this device needs some gpio writes to get the
+ * DVB-T demod work
+ */
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe);
mdelay(70);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde);
@@ -2787,13 +2865,13 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
case EM2882_BOARD_KWORLD_ATSC_315U:
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2880_R04_GPO, 0x08);
- msleep(10);
+ usleep_range(10000, 11000);
break;
case EM2860_BOARD_KAIOMY_TVNPC_U2:
@@ -2801,11 +2879,11 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
em28xx_write_regs(dev, 0x0d, "\x42", 1);
em28xx_write_regs(dev, 0x08, "\xfd", 1);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_regs(dev, 0x08, "\xff", 1);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_regs(dev, 0x08, "\x7f", 1);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_regs(dev, 0x08, "\x6b", 1);
break;
@@ -2817,7 +2895,7 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
msleep(70);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe);
msleep(70);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd);
@@ -2825,7 +2903,8 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
break;
case EM2860_BOARD_TERRATEC_GRABBY:
- /* HACK?: Ensure AC97 register reading is reliable before
+ /*
+ * HACK?: Ensure AC97 register reading is reliable before
* proceeding. In practice, this will wait about 1.6 seconds.
*/
em28xx_wait_until_ac97_features_equals(dev, 0x6a90);
@@ -2843,7 +2922,7 @@ static int em28xx_hint_board(struct em28xx *dev)
{
int i;
- if (dev->board.is_webcam) {
+ if (dev->is_webcam) {
if (dev->em28xx_sensor == EM28XX_MT9V011) {
dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
} else if (dev->em28xx_sensor == EM28XX_MT9M001 ||
@@ -2855,7 +2934,8 @@ static int em28xx_hint_board(struct em28xx *dev)
return 0;
}
- /* HINT method: EEPROM
+ /*
+ * HINT method: EEPROM
*
* This method works only for boards with eeprom.
* Uses a hash of all eeprom bytes. The hash should be
@@ -2881,7 +2961,8 @@ static int em28xx_hint_board(struct em28xx *dev)
}
}
- /* HINT method: I2C attached devices
+ /*
+ * HINT method: I2C attached devices
*
* This method works for all boards.
* Uses a hash of i2c scanned devices.
@@ -2935,11 +3016,11 @@ static void em28xx_card_setup(struct em28xx *dev)
* If the device can be a webcam, seek for a sensor.
* If sensor is not found, then it isn't a webcam.
*/
- if (dev->board.is_webcam) {
+ if (dev->is_webcam) {
em28xx_detect_sensor(dev);
if (dev->em28xx_sensor == EM28XX_NOSENSOR)
/* NOTE: error/unknown sensor/no sensor */
- dev->board.is_webcam = 0;
+ dev->is_webcam = 0;
}
switch (dev->model) {
@@ -2959,9 +3040,9 @@ static void em28xx_card_setup(struct em28xx *dev)
* This solution is only valid if they do not share eeprom
* hash identities which has not been determined as yet.
*/
- if (em28xx_hint_board(dev) < 0)
+ if (em28xx_hint_board(dev) < 0) {
dev_err(&dev->intf->dev, "Board not discovered\n");
- else {
+ } else {
em28xx_set_model(dev);
em28xx_pre_card_setup(dev);
}
@@ -2971,7 +3052,7 @@ static void em28xx_card_setup(struct em28xx *dev)
}
dev_info(&dev->intf->dev, "Identified as %s (card=%d)\n",
- dev->board.name, dev->model);
+ dev->board.name, dev->model);
dev->tuner_type = em28xx_boards[dev->model].tuner_type;
@@ -2988,7 +3069,7 @@ static void em28xx_card_setup(struct em28xx *dev)
{
struct tveeprom tv;
- if (dev->eedata == NULL)
+ if (!dev->eedata)
break;
#if defined(CONFIG_MODULES) && defined(MODULE)
request_module("tveeprom");
@@ -3001,15 +3082,15 @@ static void em28xx_card_setup(struct em28xx *dev)
if (tv.audio_processor == TVEEPROM_AUDPROC_MSP) {
dev->i2s_speed = 2048000;
- dev->board.has_msp34xx = 1;
+ dev->has_msp34xx = 1;
}
break;
}
case EM2882_BOARD_KWORLD_ATSC_315U:
em28xx_write_reg(dev, 0x0d, 0x42);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd);
- msleep(10);
+ usleep_range(10000, 11000);
break;
case EM2820_BOARD_KWORLD_PVRTV2800RF:
/* GPIO enables sound on KWORLD PVR TV 2800RF */
@@ -3034,10 +3115,12 @@ static void em28xx_card_setup(struct em28xx *dev)
if (!em28xx_hint_board(dev))
em28xx_set_model(dev);
- /* In cases where we had to use a board hint, the call to
- em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
- so make the call now so the analog GPIOs are set properly
- before probing the i2c bus. */
+ /*
+ * In cases where we had to use a board hint, the call to
+ * em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+ * so make the call now so the analog GPIOs are set properly
+ * before probing the i2c bus.
+ */
em28xx_gpio_set(dev, dev->board.tuner_gpio);
em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
break;
@@ -3059,10 +3142,12 @@ static void em28xx_card_setup(struct em28xx *dev)
if (!em28xx_hint_board(dev))
em28xx_set_model(dev);
- /* In cases where we had to use a board hint, the call to
- em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
- so make the call now so the analog GPIOs are set properly
- before probing the i2c bus. */
+ /*
+ * In cases where we had to use a board hint, the call to
+ * em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+ * so make the call now so the analog GPIOs are set properly
+ * before probing the i2c bus.
+ */
em28xx_gpio_set(dev, dev->board.tuner_gpio);
em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
break;
@@ -3147,8 +3232,8 @@ static void request_module_async(struct work_struct *work)
*/
/*
- * Devicdes with an audio-only interface also have a V4L/DVB/RC
- * interface. Don't register extensions twice on those devices.
+ * Devices with an audio-only intf also have a V4L/DVB/RC
+ * intf. Don't register extensions twice on those devices.
*/
if (dev->is_audio_only) {
#if defined(CONFIG_MODULES) && defined(MODULE)
@@ -3209,7 +3294,6 @@ static int em28xx_media_device_init(struct em28xx *dev,
static void em28xx_unregister_media_device(struct em28xx *dev)
{
-
#ifdef CONFIG_MEDIA_CONTROLLER
if (dev->media_dev) {
media_device_unregister(dev->media_dev);
@@ -3224,7 +3308,7 @@ static void em28xx_unregister_media_device(struct em28xx *dev)
* em28xx_release_resources()
* unregisters the v4l2,i2c and usb devices
* called when the device gets disconnected or at module unload
-*/
+ */
static void em28xx_release_resources(struct em28xx *dev)
{
struct usb_device *udev = interface_to_usbdev(dev->intf);
@@ -3239,7 +3323,8 @@ static void em28xx_release_resources(struct em28xx *dev)
em28xx_i2c_unregister(dev, 1);
em28xx_i2c_unregister(dev, 0);
- usb_put_dev(udev);
+ if (dev->ts == PRIMARY_TS)
+ usb_put_dev(udev);
/* Mark device as unused */
clear_bit(dev->devno, em28xx_devused);
@@ -3273,13 +3358,13 @@ EXPORT_SYMBOL_GPL(em28xx_free_device);
* allocates and inits the device structs, registers i2c bus and v4l device
*/
static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
- struct usb_interface *interface,
+ struct usb_interface *intf,
int minor)
{
int retval;
const char *chip_name = NULL;
- dev->intf = interface;
+ dev->intf = intf;
mutex_init(&dev->ctrl_urb_lock);
spin_lock_init(&dev->slock);
@@ -3382,17 +3467,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
em28xx_pre_card_setup(dev);
- if (!dev->board.is_em2800) {
- /* Resets I2C speed */
- retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
- if (retval < 0) {
- dev_err(&dev->intf->dev,
- "%s: em28xx_write_reg failed! retval [%d]\n",
- __func__, retval);
- return retval;
- }
- }
-
rt_mutex_init(&dev->i2c_bus_lock);
/* register i2c bus 0 */
@@ -3417,8 +3491,8 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
EM28XX_I2C_ALGO_EM28XX);
if (retval < 0) {
dev_err(&dev->intf->dev,
- "%s: em28xx_i2c_register bus 1 - error [%d]!\n",
- __func__, retval);
+ "%s: em28xx_i2c_register bus 1 - error [%d]!\n",
+ __func__, retval);
em28xx_i2c_unregister(dev, 0);
@@ -3432,14 +3506,147 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
return 0;
}
+static int em28xx_duplicate_dev(struct em28xx *dev)
+{
+ int nr;
+ struct em28xx *sec_dev = kzalloc(sizeof(*sec_dev), GFP_KERNEL);
+
+ if (!sec_dev) {
+ dev->dev_next = NULL;
+ return -ENOMEM;
+ }
+ memcpy(sec_dev, dev, sizeof(*sec_dev));
+ /* Check to see next free device and mark as used */
+ do {
+ nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS);
+ if (nr >= EM28XX_MAXBOARDS) {
+ /* No free device slots */
+ dev_warn(&dev->intf->dev, ": Supports only %i em28xx boards.\n",
+ EM28XX_MAXBOARDS);
+ kfree(sec_dev);
+ dev->dev_next = NULL;
+ return -ENOMEM;
+ }
+ } while (test_and_set_bit(nr, em28xx_devused));
+ sec_dev->devno = nr;
+ snprintf(sec_dev->name, 28, "em28xx #%d", nr);
+ sec_dev->dev_next = NULL;
+ dev->dev_next = sec_dev;
+ return 0;
+}
+
/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+static void em28xx_check_usb_descriptor(struct em28xx *dev,
+ struct usb_device *udev,
+ struct usb_interface *intf,
+ int alt, int ep,
+ bool *has_vendor_audio,
+ bool *has_video,
+ bool *has_dvb)
+{
+ const struct usb_endpoint_descriptor *e;
+ int sizedescr, size;
+
+ /*
+ * NOTE:
+ *
+ * Old logic with support for isoc transfers only was:
+ * 0x82 isoc => analog
+ * 0x83 isoc => audio
+ * 0x84 isoc => digital
+ *
+ * New logic with support for bulk transfers
+ * 0x82 isoc => analog
+ * 0x82 bulk => analog
+ * 0x83 isoc* => audio
+ * 0x84 isoc => digital
+ * 0x84 bulk => analog or digital**
+ * 0x85 isoc => digital TS2
+ * 0x85 bulk => digital TS2
+ * (*: audio should always be isoc)
+ * (**: analog, if ep 0x82 is isoc, otherwise digital)
+ *
+ * The new logic preserves backwards compatibility and
+ * reflects the endpoint configurations we have seen
+ * so far. But there might be devices for which this
+ * logic is not sufficient...
+ */
+
+ e = &intf->altsetting[alt].endpoint[ep].desc;
+
+ if (!usb_endpoint_dir_in(e))
+ return;
+
+ sizedescr = le16_to_cpu(e->wMaxPacketSize);
+ size = sizedescr & 0x7ff;
+
+ if (udev->speed == USB_SPEED_HIGH)
+ size = size * hb_mult(sizedescr);
+
+ /* Only inspect input endpoints */
+
+ switch (e->bEndpointAddress) {
+ case 0x82:
+ *has_video = true;
+ if (usb_endpoint_xfer_isoc(e)) {
+ dev->analog_ep_isoc = e->bEndpointAddress;
+ dev->alt_max_pkt_size_isoc[alt] = size;
+ } else if (usb_endpoint_xfer_bulk(e)) {
+ dev->analog_ep_bulk = e->bEndpointAddress;
+ }
+ return;
+ case 0x83:
+ if (usb_endpoint_xfer_isoc(e))
+ *has_vendor_audio = true;
+ else
+ dev_err(&intf->dev,
+ "error: skipping audio endpoint 0x83, because it uses bulk transfers !\n");
+ return;
+ case 0x84:
+ if (*has_video && (usb_endpoint_xfer_bulk(e))) {
+ dev->analog_ep_bulk = e->bEndpointAddress;
+ } else {
+ if (usb_endpoint_xfer_isoc(e)) {
+ if (size > dev->dvb_max_pkt_size_isoc) {
+ /*
+ * 2) some manufacturers (e.g. Terratec)
+ * disable endpoints by setting
+ * wMaxPacketSize to 0 bytes for all
+ * alt settings. So far, we've seen
+ * this for DVB isoc endpoints only.
+ */
+ *has_dvb = true;
+ dev->dvb_ep_isoc = e->bEndpointAddress;
+ dev->dvb_max_pkt_size_isoc = size;
+ dev->dvb_alt_isoc = alt;
+ }
+ } else {
+ *has_dvb = true;
+ dev->dvb_ep_bulk = e->bEndpointAddress;
+ }
+ }
+ return;
+ case 0x85:
+ if (usb_endpoint_xfer_isoc(e)) {
+ if (size > dev->dvb_max_pkt_size_isoc_ts2) {
+ dev->dvb_ep_isoc_ts2 = e->bEndpointAddress;
+ dev->dvb_max_pkt_size_isoc_ts2 = size;
+ dev->dvb_alt_isoc = alt;
+ }
+ } else {
+ dev->dvb_ep_bulk_ts2 = e->bEndpointAddress;
+ }
+ return;
+ }
+}
+
/*
* em28xx_usb_probe()
* checks for supported devices
*/
-static int em28xx_usb_probe(struct usb_interface *interface,
+static int em28xx_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev;
@@ -3447,17 +3654,17 @@ static int em28xx_usb_probe(struct usb_interface *interface,
int retval;
bool has_vendor_audio = false, has_video = false, has_dvb = false;
int i, nr, try_bulk;
- const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+ const int ifnum = intf->altsetting[0].desc.bInterfaceNumber;
char *speed;
- udev = usb_get_dev(interface_to_usbdev(interface));
+ udev = usb_get_dev(interface_to_usbdev(intf));
/* Check to see next free device and mark as used */
do {
nr = find_first_zero_bit(em28xx_devused, EM28XX_MAXBOARDS);
if (nr >= EM28XX_MAXBOARDS) {
/* No free device slots */
- dev_err(&interface->dev,
+ dev_err(&intf->dev,
"Driver supports up to %i em28xx boards.\n",
EM28XX_MAXBOARDS);
retval = -ENOMEM;
@@ -3466,13 +3673,13 @@ static int em28xx_usb_probe(struct usb_interface *interface,
} while (test_and_set_bit(nr, em28xx_devused));
/* Don't register audio interfaces */
- if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
- dev_err(&interface->dev,
+ if (intf->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
+ dev_err(&intf->dev,
"audio device (%04x:%04x): interface %i, class %i\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
ifnum,
- interface->altsetting[0].desc.bInterfaceClass);
+ intf->altsetting[0].desc.bInterfaceClass);
retval = -ENODEV;
goto err;
@@ -3480,106 +3687,33 @@ static int em28xx_usb_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
+ if (!dev) {
retval = -ENOMEM;
goto err;
}
/* compute alternate max packet sizes */
- dev->alt_max_pkt_size_isoc =
- kmalloc(sizeof(dev->alt_max_pkt_size_isoc[0]) *
- interface->num_altsetting, GFP_KERNEL);
- if (dev->alt_max_pkt_size_isoc == NULL) {
+ dev->alt_max_pkt_size_isoc = kcalloc(intf->num_altsetting,
+ sizeof(dev->alt_max_pkt_size_isoc[0]),
+ GFP_KERNEL);
+ if (!dev->alt_max_pkt_size_isoc) {
kfree(dev);
retval = -ENOMEM;
goto err;
}
/* Get endpoints */
- for (i = 0; i < interface->num_altsetting; i++) {
+ for (i = 0; i < intf->num_altsetting; i++) {
int ep;
- for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
- const struct usb_endpoint_descriptor *e;
- int sizedescr, size;
-
- e = &interface->altsetting[i].endpoint[ep].desc;
-
- sizedescr = le16_to_cpu(e->wMaxPacketSize);
- size = sizedescr & 0x7ff;
-
- if (udev->speed == USB_SPEED_HIGH)
- size = size * hb_mult(sizedescr);
-
- if (usb_endpoint_dir_in(e)) {
- switch (e->bEndpointAddress) {
- case 0x82:
- has_video = true;
- if (usb_endpoint_xfer_isoc(e)) {
- dev->analog_ep_isoc =
- e->bEndpointAddress;
- dev->alt_max_pkt_size_isoc[i] = size;
- } else if (usb_endpoint_xfer_bulk(e)) {
- dev->analog_ep_bulk =
- e->bEndpointAddress;
- }
- break;
- case 0x83:
- if (usb_endpoint_xfer_isoc(e)) {
- has_vendor_audio = true;
- } else {
- dev_err(&interface->dev,
- "error: skipping audio endpoint 0x83, because it uses bulk transfers !\n");
- }
- break;
- case 0x84:
- if (has_video &&
- (usb_endpoint_xfer_bulk(e))) {
- dev->analog_ep_bulk =
- e->bEndpointAddress;
- } else {
- if (usb_endpoint_xfer_isoc(e)) {
- if (size > dev->dvb_max_pkt_size_isoc) {
- has_dvb = true; /* see NOTE (~) */
- dev->dvb_ep_isoc = e->bEndpointAddress;
- dev->dvb_max_pkt_size_isoc = size;
- dev->dvb_alt_isoc = i;
- }
- } else {
- has_dvb = true;
- dev->dvb_ep_bulk = e->bEndpointAddress;
- }
- }
- break;
- }
- }
- /* NOTE:
- * Old logic with support for isoc transfers only was:
- * 0x82 isoc => analog
- * 0x83 isoc => audio
- * 0x84 isoc => digital
- *
- * New logic with support for bulk transfers
- * 0x82 isoc => analog
- * 0x82 bulk => analog
- * 0x83 isoc* => audio
- * 0x84 isoc => digital
- * 0x84 bulk => analog or digital**
- * (*: audio should always be isoc)
- * (**: analog, if ep 0x82 is isoc, otherwise digital)
- *
- * The new logic preserves backwards compatibility and
- * reflects the endpoint configurations we have seen
- * so far. But there might be devices for which this
- * logic is not sufficient...
- */
- /*
- * NOTE (~): some manufacturers (e.g. Terratec) disable
- * endpoints by setting wMaxPacketSize to 0 bytes for
- * all alt settings. So far, we've seen this for
- * DVB isoc endpoints only.
- */
- }
+ for (ep = 0;
+ ep < intf->altsetting[i].desc.bNumEndpoints;
+ ep++)
+ em28xx_check_usb_descriptor(dev, udev, intf,
+ i, ep,
+ &has_vendor_audio,
+ &has_video,
+ &has_dvb);
}
if (!(has_vendor_audio || has_video || has_dvb)) {
@@ -3602,7 +3736,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
speed = "unknown";
}
- dev_err(&interface->dev,
+ dev_err(&intf->dev,
"New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n",
udev->manufacturer ? udev->manufacturer : "",
udev->product ? udev->product : "",
@@ -3610,7 +3744,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
ifnum,
- interface->altsetting->desc.bInterfaceNumber);
+ intf->altsetting->desc.bInterfaceNumber);
/*
* Make sure we have 480 Mbps of bandwidth, otherwise things like
@@ -3618,8 +3752,8 @@ static int em28xx_usb_probe(struct usb_interface *interface,
* not enough even for most Digital TV streams.
*/
if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
- dev_err(&interface->dev, "Device initialization failed.\n");
- dev_err(&interface->dev,
+ dev_err(&intf->dev, "Device initialization failed.\n");
+ dev_err(&intf->dev,
"Device must be connected to a high-speed USB 2.0 port.\n");
retval = -ENODEV;
goto err_free;
@@ -3632,53 +3766,56 @@ static int em28xx_usb_probe(struct usb_interface *interface,
dev->has_video = has_video;
dev->ifnum = ifnum;
+ dev->ts = PRIMARY_TS;
+ snprintf(dev->name, 28, "em28xx");
+ dev->dev_next = NULL;
+
if (has_vendor_audio) {
- dev_err(&interface->dev,
+ dev_err(&intf->dev,
"Audio interface %i found (Vendor Class)\n", ifnum);
dev->usb_audio_type = EM28XX_USB_AUDIO_VENDOR;
}
- /* Checks if audio is provided by a USB Audio Class interface */
+ /* Checks if audio is provided by a USB Audio Class intf */
for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
struct usb_interface *uif = udev->config->interface[i];
if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
if (has_vendor_audio)
- dev_err(&interface->dev,
+ dev_err(&intf->dev,
"em28xx: device seems to have vendor AND usb audio class interfaces !\n"
- "\t\tThe vendor interface will be ignored. Please contact the developers <linux-media@vger.kernel.org>\n");
+ "\t\tThe vendor interface will be ignored. Please contact the developers <linux-media@vger.kernel.org>\n");
dev->usb_audio_type = EM28XX_USB_AUDIO_CLASS;
break;
}
}
if (has_video)
- dev_err(&interface->dev, "Video interface %i found:%s%s\n",
+ dev_err(&intf->dev, "Video interface %i found:%s%s\n",
ifnum,
dev->analog_ep_bulk ? " bulk" : "",
dev->analog_ep_isoc ? " isoc" : "");
if (has_dvb)
- dev_err(&interface->dev, "DVB interface %i found:%s%s\n",
+ dev_err(&intf->dev, "DVB interface %i found:%s%s\n",
ifnum,
dev->dvb_ep_bulk ? " bulk" : "",
dev->dvb_ep_isoc ? " isoc" : "");
- dev->num_alt = interface->num_altsetting;
+ dev->num_alt = intf->num_altsetting;
- if ((unsigned)card[nr] < em28xx_bcount)
+ if ((unsigned int)card[nr] < em28xx_bcount)
dev->model = card[nr];
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, dev);
+ /* save our data pointer in this intf device */
+ usb_set_intfdata(intf, dev);
/* allocate device struct and check if the device is a webcam */
mutex_init(&dev->lock);
- retval = em28xx_init_dev(dev, udev, interface, nr);
- if (retval) {
+ retval = em28xx_init_dev(dev, udev, intf, nr);
+ if (retval)
goto err_free;
- }
if (usb_xfer_mode < 0) {
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
try_bulk = 1;
else
try_bulk = 0;
@@ -3690,8 +3827,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (has_video &&
dev->board.decoder == EM28XX_NODECODER &&
dev->em28xx_sensor == EM28XX_NOSENSOR) {
-
- dev_err(&interface->dev,
+ dev_err(&intf->dev,
"Currently, V4L2 is not supported on this model\n");
has_video = false;
dev->has_video = false;
@@ -3701,16 +3837,75 @@ static int em28xx_usb_probe(struct usb_interface *interface,
if (has_video) {
if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk))
dev->analog_xfer_bulk = 1;
- dev_err(&interface->dev, "analog set to %s mode.\n",
+ dev_err(&intf->dev, "analog set to %s mode.\n",
dev->analog_xfer_bulk ? "bulk" : "isoc");
}
if (has_dvb) {
if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk))
dev->dvb_xfer_bulk = 1;
- dev_err(&interface->dev, "dvb set to %s mode.\n",
+ dev_err(&intf->dev, "dvb set to %s mode.\n",
dev->dvb_xfer_bulk ? "bulk" : "isoc");
}
+ if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) {
+ dev->dev_next->ts = SECONDARY_TS;
+ dev->dev_next->alt = -1;
+ dev->dev_next->is_audio_only = has_vendor_audio &&
+ !(has_video || has_dvb);
+ dev->dev_next->has_video = false;
+ dev->dev_next->ifnum = ifnum;
+ dev->dev_next->model = id->driver_info;
+
+ mutex_init(&dev->dev_next->lock);
+ retval = em28xx_init_dev(dev->dev_next, udev, intf,
+ dev->dev_next->devno);
+ if (retval)
+ goto err_free;
+
+ dev->dev_next->board.ir_codes = NULL; /* No IR for 2nd tuner */
+ dev->dev_next->board.has_ir_i2c = 0; /* No IR for 2nd tuner */
+
+ if (usb_xfer_mode < 0) {
+ if (dev->dev_next->is_webcam)
+ try_bulk = 1;
+ else
+ try_bulk = 0;
+ } else {
+ try_bulk = usb_xfer_mode > 0;
+ }
+
+ /* Select USB transfer types to use */
+ if (has_dvb) {
+ if (!dev->dvb_ep_isoc_ts2 ||
+ (try_bulk && dev->dvb_ep_bulk_ts2))
+ dev->dev_next->dvb_xfer_bulk = 1;
+ dev_info(&dev->intf->dev, "dvb ts2 set to %s mode.\n",
+ dev->dev_next->dvb_xfer_bulk ? "bulk" : "isoc");
+ }
+
+ dev->dev_next->dvb_ep_isoc = dev->dvb_ep_isoc_ts2;
+ dev->dev_next->dvb_ep_bulk = dev->dvb_ep_bulk_ts2;
+ dev->dev_next->dvb_max_pkt_size_isoc = dev->dvb_max_pkt_size_isoc_ts2;
+ dev->dev_next->dvb_alt_isoc = dev->dvb_alt_isoc;
+
+ /* Configuare hardware to support TS2*/
+ if (dev->dvb_xfer_bulk) {
+ /* The ep4 and ep5 are configuared for BULK */
+ em28xx_write_reg(dev, 0x0b, 0x96);
+ mdelay(100);
+ em28xx_write_reg(dev, 0x0b, 0x80);
+ mdelay(100);
+ } else {
+ /* The ep4 and ep5 are configuared for ISO */
+ em28xx_write_reg(dev, 0x0b, 0x96);
+ mdelay(100);
+ em28xx_write_reg(dev, 0x0b, 0x82);
+ mdelay(100);
+ }
+
+ kref_init(&dev->dev_next->ref);
+ }
+
kref_init(&dev->ref);
request_modules(dev);
@@ -3743,45 +3938,59 @@ err_no_slot:
* called when the device gets disconnected
* video device will be unregistered on v4l2_close in case it is still open
*/
-static void em28xx_usb_disconnect(struct usb_interface *interface)
+static void em28xx_usb_disconnect(struct usb_interface *intf)
{
struct em28xx *dev;
- dev = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
if (!dev)
return;
+ if (dev->dev_next) {
+ dev->dev_next->disconnected = 1;
+ dev_info(&dev->intf->dev, "Disconnecting %s\n",
+ dev->dev_next->name);
+ flush_request_modules(dev->dev_next);
+ }
+
dev->disconnected = 1;
- dev_err(&dev->intf->dev, "Disconnecting\n");
+ dev_err(&dev->intf->dev, "Disconnecting %s\n", dev->name);
flush_request_modules(dev);
em28xx_close_extension(dev);
+ if (dev->dev_next)
+ em28xx_release_resources(dev->dev_next);
em28xx_release_resources(dev);
+
+ if (dev->dev_next) {
+ kref_put(&dev->dev_next->ref, em28xx_free_device);
+ dev->dev_next = NULL;
+ }
kref_put(&dev->ref, em28xx_free_device);
}
-static int em28xx_usb_suspend(struct usb_interface *interface,
+static int em28xx_usb_suspend(struct usb_interface *intf,
pm_message_t message)
{
struct em28xx *dev;
- dev = usb_get_intfdata(interface);
+ dev = usb_get_intfdata(intf);
if (!dev)
return 0;
em28xx_suspend_extension(dev);
return 0;
}
-static int em28xx_usb_resume(struct usb_interface *interface)
+static int em28xx_usb_resume(struct usb_interface *intf)
{
struct em28xx *dev;
- dev = usb_get_intfdata(interface);
+ dev = usb_get_intfdata(intf);
if (!dev)
return 0;
em28xx_resume_extension(dev);
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 1d0d8cc..36d341f 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -1,26 +1,22 @@
-/*
- em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
- Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- Markus Rechberger <mrechberger@gmail.com>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Sascha Sommer <saschasommer@freenet.de>
- Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+//
+// Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+// Markus Rechberger <mrechberger@gmail.com>
+// Mauro Carvalho Chehab <mchehab@infradead.org>
+// Sascha Sommer <saschasommer@freenet.de>
+// Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -41,7 +37,7 @@
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_VERSION(EM28XX_VERSION);
/* #define ENABLE_DEBUG_ISOC_FRAMES */
@@ -60,7 +56,6 @@ static unsigned int reg_debug;
module_param(reg_debug, int, 0644);
MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
-
#define em28xx_regdbg(fmt, arg...) do { \
if (reg_debug) \
dev_printk(KERN_DEBUG, &dev->intf->dev, \
@@ -97,10 +92,11 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
0x0000, reg, dev->urb_buf, len, HZ);
if (ret < 0) {
em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x failed with error %i\n",
- pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- req, 0, 0,
- reg & 0xff, reg >> 8,
- len & 0xff, len >> 8, ret);
+ pipe,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ req, 0, 0,
+ reg & 0xff, reg >> 8,
+ len & 0xff, len >> 8, ret);
mutex_unlock(&dev->ctrl_urb_lock);
return usb_translate_errors(ret);
}
@@ -111,10 +107,10 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
mutex_unlock(&dev->ctrl_urb_lock);
em28xx_regdbg("(pipe 0x%08x): IN: %02x %02x %02x %02x %02x %02x %02x %02x <<< %*ph\n",
- pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- req, 0, 0,
- reg & 0xff, reg >> 8,
- len & 0xff, len >> 8, len, buf);
+ pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ req, 0, 0,
+ reg & 0xff, reg >> 8,
+ len & 0xff, len >> 8, len, buf);
return ret;
}
@@ -155,7 +151,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
if (dev->disconnected)
return -ENODEV;
- if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
+ if (len < 1 || len > URB_MAX_CTRL_SIZE)
return -EINVAL;
mutex_lock(&dev->ctrl_urb_lock);
@@ -341,8 +337,9 @@ static int set_ac97_input(struct em28xx *dev)
int ret, i;
enum em28xx_amux amux = dev->ctl_ainput;
- /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that
- em28xx should point to LINE IN, while AC97 should use VIDEO
+ /*
+ * EM28XX_AMUX_VIDEO2 is a special case used to indicate that
+ * em28xx should point to LINE IN, while AC97 should use VIDEO
*/
if (amux == EM28XX_AMUX_VIDEO2)
amux = EM28XX_AMUX_VIDEO;
@@ -378,9 +375,9 @@ static int em28xx_set_audio_source(struct em28xx *dev)
return ret;
}
- if (dev->board.has_msp34xx)
+ if (dev->has_msp34xx) {
input = EM28XX_AUDIO_SRC_TUNER;
- else {
+ } else {
switch (dev->ctl_ainput) {
case EM28XX_AMUX_VIDEO:
input = EM28XX_AUDIO_SRC_TUNER;
@@ -399,7 +396,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
if (ret < 0)
return ret;
- msleep(5);
+ usleep_range(10000, 11000);
switch (dev->audio_mode.ac97) {
case EM28XX_NO_AC97:
@@ -432,8 +429,9 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE)
return 0;
- /* It is assumed that all devices use master volume for output.
- It would be possible to use also line output.
+ /*
+ * It is assumed that all devices use master volume for output.
+ * It would be possible to use also line output.
*/
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
/* Mute all outputs */
@@ -453,7 +451,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk);
if (ret < 0)
return ret;
- msleep(10);
+ usleep_range(10000, 11000);
/* Selects the proper audio input */
ret = em28xx_set_audio_source(dev);
@@ -487,8 +485,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
int sel = ac97_return_record_select(dev->ctl_aoutput);
- /* Use the same input for both left and right
- channels */
+ /*
+ * Use the same input for both left and right
+ * channels
+ */
sel |= (sel << 8);
em28xx_write_ac97(dev, AC97_REC_SEL, sel);
@@ -539,7 +539,7 @@ int em28xx_audio_setup(struct em28xx *dev)
else
i2s_samplerates = 3;
dev_info(&dev->intf->dev, "I2S Audio (%d sample rate(s))\n",
- i2s_samplerates);
+ i2s_samplerates);
/* Skip the code that does AC97 vendor detection */
dev->audio_mode.ac97 = EM28XX_NO_AC97;
goto init_audio;
@@ -579,7 +579,7 @@ int em28xx_audio_setup(struct em28xx *dev)
dev_warn(&dev->intf->dev, "AC97 features = 0x%04x\n", feat);
/* Try to identify what audio processor we have */
- if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
+ if ((vid == 0xffffffff || vid == 0x83847650) && feat == 0x6a90)
dev->audio_mode.ac97 = EM28XX_AC97_EM202;
else if ((vid >> 8) == 0x838476)
dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL;
@@ -638,10 +638,29 @@ int em28xx_capture_start(struct em28xx *dev, int start)
dev->chip_id == CHIP_ID_EM28174 ||
dev->chip_id == CHIP_ID_EM28178) {
/* The Transport Stream Enable Register moved in em2874 */
- rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
- start ?
- EM2874_TS1_CAPTURE_ENABLE : 0x00,
- EM2874_TS1_CAPTURE_ENABLE);
+ if (dev->dvb_xfer_bulk) {
+ /* Max Tx Size = 188 * 256 = 48128 - LCM(188,512) * 2 */
+ em28xx_write_reg(dev, (dev->ts == PRIMARY_TS) ?
+ EM2874_R5D_TS1_PKT_SIZE :
+ EM2874_R5E_TS2_PKT_SIZE,
+ 0xff);
+ } else {
+ /* ISOC Maximum Transfer Size = 188 * 5 */
+ em28xx_write_reg(dev, (dev->ts == PRIMARY_TS) ?
+ EM2874_R5D_TS1_PKT_SIZE :
+ EM2874_R5E_TS2_PKT_SIZE,
+ dev->dvb_max_pkt_size_isoc / 188);
+ }
+ if (dev->ts == PRIMARY_TS)
+ rc = em28xx_write_reg_bits(dev,
+ EM2874_R5F_TS_ENABLE,
+ start ? EM2874_TS1_CAPTURE_ENABLE : 0x00,
+ EM2874_TS1_CAPTURE_ENABLE);
+ else
+ rc = em28xx_write_reg_bits(dev,
+ EM2874_R5F_TS_ENABLE,
+ start ? EM2874_TS2_CAPTURE_ENABLE : 0x00,
+ EM2874_TS2_CAPTURE_ENABLE);
} else {
/* FIXME: which is the best order? */
/* video registers are sampled by VREF */
@@ -651,7 +670,7 @@ int em28xx_capture_start(struct em28xx *dev, int start)
return rc;
if (start) {
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
rc = em28xx_write_reg(dev, 0x13, 0x0c);
/* Enable video capture */
@@ -670,7 +689,7 @@ int em28xx_capture_start(struct em28xx *dev, int start)
if (rc < 0)
return rc;
- msleep(6);
+ usleep_range(10000, 11000);
} else {
/* disable video capture */
rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27);
@@ -691,7 +710,7 @@ int em28xx_capture_start(struct em28xx *dev, int start)
return rc;
}
-int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
+int em28xx_gpio_set(struct em28xx *dev, const struct em28xx_reg_seq *gpio)
{
int rc = 0;
@@ -704,7 +723,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
else
em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
- msleep(6);
+ usleep_range(10000, 11000);
}
/* Send GPIO reset sequences specified at board entry */
@@ -748,9 +767,9 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
}
EXPORT_SYMBOL_GPL(em28xx_set_mode);
-/* ------------------------------------------------------------------
- URB control
- ------------------------------------------------------------------*/
+/*
+ *URB control
+ */
/*
* URB completion handler for isoc/bulk transfers
@@ -769,7 +788,7 @@ static void em28xx_irq_callback(struct urb *urb)
case -ESHUTDOWN:
return;
default: /* error */
- em28xx_isocdbg("urb completition error %d.\n", urb->status);
+ em28xx_isocdbg("urb completion error %d.\n", urb->status);
break;
}
@@ -800,11 +819,9 @@ void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode)
{
struct urb *urb;
struct em28xx_usb_bufs *usb_bufs;
- struct usb_device *udev = interface_to_usbdev(dev->intf);
int i;
- em28xx_isocdbg("em28xx: called em28xx_uninit_usb_xfer in mode %d\n",
- mode);
+ em28xx_isocdbg("called %s in mode %d\n", __func__, mode);
if (mode == EM28XX_DIGITAL_MODE)
usb_bufs = &dev->usb_ctl.digital_bufs;
@@ -819,23 +836,16 @@ void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode)
else
usb_unlink_urb(urb);
- if (usb_bufs->transfer_buffer[i]) {
- usb_free_coherent(udev,
- urb->transfer_buffer_length,
- usb_bufs->transfer_buffer[i],
- urb->transfer_dma);
- }
usb_free_urb(urb);
usb_bufs->urb[i] = NULL;
}
- usb_bufs->transfer_buffer[i] = NULL;
}
kfree(usb_bufs->urb);
- kfree(usb_bufs->transfer_buffer);
+ kfree(usb_bufs->buf);
usb_bufs->urb = NULL;
- usb_bufs->transfer_buffer = NULL;
+ usb_bufs->buf = NULL;
usb_bufs->num_bufs = 0;
em28xx_capture_start(dev, 0);
@@ -851,7 +861,7 @@ void em28xx_stop_urbs(struct em28xx *dev)
struct urb *urb;
struct em28xx_usb_bufs *isoc_bufs = &dev->usb_ctl.digital_bufs;
- em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n");
+ em28xx_isocdbg("called %s\n", __func__);
for (i = 0; i < isoc_bufs->num_bufs; i++) {
urb = isoc_bufs->urb[i];
@@ -880,10 +890,12 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
int sb_size, pipe;
int j, k;
- em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
+ em28xx_isocdbg("em28xx: called %s in mode %d\n", __func__, mode);
- /* Check mode and if we have an endpoint for the selected
- transfer type, select buffer */
+ /*
+ * Check mode and if we have an endpoint for the selected
+ * transfer type, select buffer
+ */
if (mode == EM28XX_DIGITAL_MODE) {
if ((xfer_bulk && !dev->dvb_ep_bulk) ||
(!xfer_bulk && !dev->dvb_ep_isoc)) {
@@ -912,14 +924,13 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
usb_bufs->num_bufs = num_bufs;
- usb_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ usb_bufs->urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!usb_bufs->urb)
return -ENOMEM;
- usb_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
- GFP_KERNEL);
- if (!usb_bufs->transfer_buffer) {
- kfree(usb_bufs->urb);
+ usb_bufs->buf = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
+ if (!usb_bufs->buf) {
+ kfree(usb_bufs->buf);
return -ENOMEM;
}
@@ -942,37 +953,36 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk,
}
usb_bufs->urb[i] = urb;
- usb_bufs->transfer_buffer[i] = usb_alloc_coherent(udev,
- sb_size, GFP_KERNEL, &urb->transfer_dma);
- if (!usb_bufs->transfer_buffer[i]) {
- dev_err(&dev->intf->dev,
- "unable to allocate %i bytes for transfer buffer %i%s\n",
- sb_size, i,
- in_interrupt() ? " while in int" : "");
+ usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
+ if (!usb_bufs->buf[i]) {
em28xx_uninit_usb_xfer(dev, mode);
+
+ for (i--; i >= 0; i--)
+ kfree(usb_bufs->buf[i]);
+
+ kfree(usb_bufs->buf);
+ usb_bufs->buf = NULL;
+
return -ENOMEM;
}
- memset(usb_bufs->transfer_buffer[i], 0, sb_size);
+
+ urb->transfer_flags = URB_FREE_BUFFER;
if (xfer_bulk) { /* bulk */
pipe = usb_rcvbulkpipe(udev,
mode == EM28XX_ANALOG_MODE ?
dev->analog_ep_bulk :
dev->dvb_ep_bulk);
- usb_fill_bulk_urb(urb, udev, pipe,
- usb_bufs->transfer_buffer[i], sb_size,
- em28xx_irq_callback, dev);
- urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+ usb_fill_bulk_urb(urb, udev, pipe, usb_bufs->buf[i],
+ sb_size, em28xx_irq_callback, dev);
} else { /* isoc */
pipe = usb_rcvisocpipe(udev,
mode == EM28XX_ANALOG_MODE ?
dev->analog_ep_isoc :
dev->dvb_ep_isoc);
- usb_fill_int_urb(urb, udev, pipe,
- usb_bufs->transfer_buffer[i], sb_size,
- em28xx_irq_callback, dev, 1);
- urb->transfer_flags = URB_ISO_ASAP |
- URB_NO_TRANSFER_DMA_MAP;
+ usb_fill_int_urb(urb, udev, pipe, usb_bufs->buf[i],
+ sb_size, em28xx_irq_callback, dev, 1);
+ urb->transfer_flags |= URB_ISO_ASAP;
k = 0;
for (j = 0; j < usb_bufs->num_packets; j++) {
urb->iso_frame_desc[j].offset = k;
@@ -1005,8 +1015,7 @@ int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
int rc;
int alloc;
- em28xx_isocdbg("em28xx: called em28xx_init_usb_xfer in mode %d\n",
- mode);
+ em28xx_isocdbg("em28xx: called %s in mode %d\n", __func__, mode);
dev->usb_ctl.urb_data_copy = urb_data_copy;
@@ -1077,7 +1086,11 @@ int em28xx_register_extension(struct em28xx_ops *ops)
mutex_lock(&em28xx_devlist_mutex);
list_add_tail(&ops->next, &em28xx_extension_devlist);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
- ops->init(dev);
+ if (ops->init) {
+ ops->init(dev);
+ if (dev->dev_next)
+ ops->init(dev->dev_next);
+ }
}
mutex_unlock(&em28xx_devlist_mutex);
pr_info("em28xx: Registered (%s) extension\n", ops->name);
@@ -1091,7 +1104,11 @@ void em28xx_unregister_extension(struct em28xx_ops *ops)
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(dev, &em28xx_devlist, devlist) {
- ops->fini(dev);
+ if (ops->fini) {
+ if (dev->dev_next)
+ ops->fini(dev->dev_next);
+ ops->fini(dev);
+ }
}
list_del(&ops->next);
mutex_unlock(&em28xx_devlist_mutex);
@@ -1106,8 +1123,11 @@ void em28xx_init_extension(struct em28xx *dev)
mutex_lock(&em28xx_devlist_mutex);
list_add_tail(&dev->devlist, &em28xx_devlist);
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->init)
+ if (ops->init) {
ops->init(dev);
+ if (dev->dev_next)
+ ops->init(dev->dev_next);
+ }
}
mutex_unlock(&em28xx_devlist_mutex);
}
@@ -1118,8 +1138,11 @@ void em28xx_close_extension(struct em28xx *dev)
mutex_lock(&em28xx_devlist_mutex);
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
- if (ops->fini)
+ if (ops->fini) {
+ if (dev->dev_next)
+ ops->fini(dev->dev_next);
ops->fini(dev);
+ }
}
list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
@@ -1134,6 +1157,8 @@ int em28xx_suspend_extension(struct em28xx *dev)
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->suspend)
ops->suspend(dev);
+ if (dev->dev_next)
+ ops->suspend(dev->dev_next);
}
mutex_unlock(&em28xx_devlist_mutex);
return 0;
@@ -1148,6 +1173,8 @@ int em28xx_resume_extension(struct em28xx *dev)
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->resume)
ops->resume(dev);
+ if (dev->dev_next)
+ ops->resume(dev->dev_next);
}
mutex_unlock(&em28xx_devlist_mutex);
return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 8a81c94..a54cb8d 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1,25 +1,25 @@
-/*
- DVB device driver for em28xx
-
- (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
- - Fixes for the driver to properly work with HVR-950
- - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
- - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
-
- (c) 2008 Aidan Thornton <makosoft@googlemail.com>
-
- (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
- (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
- (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// DVB device driver for em28xx
+//
+// (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
+//
+// (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
+// - Fixes for the driver to properly work with HVR-950
+// - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
+// - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
+//
+// (c) 2008 Aidan Thornton <makosoft@googlemail.com>
+//
+// (c) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
+// (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+// (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation version 2 of the License.
#include "em28xx.h"
@@ -64,7 +64,7 @@
#include "qm1d1c0042.h"
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface");
MODULE_VERSION(EM28XX_VERSION);
@@ -96,7 +96,7 @@ struct em28xx_dvb {
struct dvb_net net;
/* Due to DRX-K - probably need changes */
- int (*gate_ctrl)(struct dvb_frontend *, int);
+ int (*gate_ctrl)(struct dvb_frontend *fe, int gate);
struct semaphore pll_mutex;
bool dont_attach_fe1;
int lna_gpio;
@@ -199,7 +199,6 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb)
int rc;
struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv;
struct em28xx *dev = i2c_bus->dev;
- struct usb_device *udev = interface_to_usbdev(dev->intf);
int dvb_max_packet_size, packet_multiplier, dvb_alt;
if (dev->dvb_xfer_bulk) {
@@ -218,7 +217,6 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb)
dvb_alt = dev->dvb_alt_isoc;
}
- usb_set_interface(udev, dev->ifnum, dvb_alt);
rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
if (rc < 0)
return rc;
@@ -278,14 +276,13 @@ static int em28xx_stop_feed(struct dvb_demux_feed *feed)
mutex_lock(&dvb->lock);
dvb->nfeeds--;
- if (0 == dvb->nfeeds)
+ if (!dvb->nfeeds)
err = em28xx_stop_streaming(dvb);
mutex_unlock(&dvb->lock);
return err;
}
-
/* ------------------------------------------------------------------ */
static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
{
@@ -358,7 +355,7 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
.gpio = S5H1409_GPIO_OFF,
.inversion = S5H1409_INVERSION_OFF,
.status_mode = S5H1409_DEMODLOCKING,
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+ .mpeg_timing = S5H1409_MPEGTIMING_CONTINUOUS_NONINVERTING_CLOCK
};
static struct tda18271_std_map kworld_a340_std_map = {
@@ -514,14 +511,15 @@ static void hauppauge_hvr930c_init(struct em28xx *dev)
em28xx_gpio_set(dev, hauppauge_hvr930c_init);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
- msleep(10);
+ usleep_range(10000, 11000);
dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
for (i = 0; i < ARRAY_SIZE(regs); i++)
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
+ i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+ regs[i].r, regs[i].len);
em28xx_gpio_set(dev, hauppauge_hvr930c_end);
msleep(100);
@@ -530,8 +528,7 @@ static void hauppauge_hvr930c_init(struct em28xx *dev)
msleep(30);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
- msleep(10);
-
+ usleep_range(10000, 11000);
}
static void terratec_h5_init(struct em28xx *dev)
@@ -571,14 +568,15 @@ static void terratec_h5_init(struct em28xx *dev)
em28xx_gpio_set(dev, terratec_h5_init);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
- msleep(10);
+ usleep_range(10000, 11000);
dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
for (i = 0; i < ARRAY_SIZE(regs); i++)
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
+ i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+ regs[i].r, regs[i].len);
em28xx_gpio_set(dev, terratec_h5_end);
};
@@ -624,14 +622,15 @@ static void terratec_htc_stick_init(struct em28xx *dev)
em28xx_gpio_set(dev, terratec_htc_stick_init);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
- msleep(10);
+ usleep_range(10000, 11000);
dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
for (i = 0; i < ARRAY_SIZE(regs); i++)
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
+ i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+ regs[i].r, regs[i].len);
em28xx_gpio_set(dev, terratec_htc_stick_end);
};
@@ -682,14 +681,15 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev)
em28xx_gpio_set(dev, terratec_htc_usb_xs_init);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
- msleep(10);
+ usleep_range(10000, 11000);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
- msleep(10);
+ usleep_range(10000, 11000);
dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1;
for (i = 0; i < ARRAY_SIZE(regs); i++)
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
+ i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+ regs[i].r, regs[i].len);
em28xx_gpio_set(dev, terratec_htc_usb_xs_end);
};
@@ -718,7 +718,8 @@ static void pctv_520e_init(struct em28xx *dev)
dev->i2c_client[dev->def_i2c_bus].addr = 0x82 >> 1; /* 0x41 */
for (i = 0; i < ARRAY_SIZE(regs); i++)
- i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], regs[i].r, regs[i].len);
+ i2c_master_send(&dev->i2c_client[dev->def_i2c_bus],
+ regs[i].r, regs[i].len);
};
static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe)
@@ -780,7 +781,7 @@ static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
static u8 tuner_go[] = { TUNER_GO, 0x01};
mt352_write(fe, clock_config, sizeof(clock_config));
- udelay(200);
+ usleep_range(200, 250);
mt352_write(fe, reset, sizeof(reset));
mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
mt352_write(fe, agc_cfg, sizeof(agc_cfg));
@@ -840,8 +841,8 @@ static void px_bcud_init(struct em28xx *dev)
/* sleeping ISDB-T */
dev->dvb->i2c_client_demod->addr = 0x14;
for (i = 0; i < ARRAY_SIZE(regs1); i++)
- i2c_master_send(dev->dvb->i2c_client_demod, regs1[i].r,
- regs1[i].len);
+ i2c_master_send(dev->dvb->i2c_client_demod,
+ regs1[i].r, regs1[i].len);
/* sleeping ISDB-S */
dev->dvb->i2c_client_demod->addr = 0x15;
for (i = 0; i < ARRAY_SIZE(regs2); i++)
@@ -934,7 +935,7 @@ static struct lgdt3306a_config hauppauge_01595_lgdt3306a_config = {
/* ------------------------------------------------------------------ */
-static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
+static noinline_for_stack int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
{
struct dvb_frontend *fe;
struct xc2028_config cfg;
@@ -1077,7 +1078,7 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
/* If the analog part won't create RF connectors, DVB will do it */
- if (!dev->has_video || (dev->tuner_type == TUNER_ABSENT))
+ if (!dev->has_video || dev->tuner_type == TUNER_ABSENT)
create_rf_connector = true;
result = dvb_create_media_graph(&dvb->adapter, create_rf_connector);
@@ -1126,10 +1127,285 @@ static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
dvb_unregister_adapter(&dvb->adapter);
}
+static int em28174_dvb_init_pctv_460e(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct tda10071_platform_data tda10071_pdata = {};
+ struct a8293_platform_data a8293_pdata = {};
+
+ /* attach demod + tuner combo */
+ tda10071_pdata.clk = 40444000; /* 40.444 MHz */
+ tda10071_pdata.i2c_wr_max = 64;
+ tda10071_pdata.ts_mode = TDA10071_TS_SERIAL;
+ tda10071_pdata.pll_multiplier = 20;
+ tda10071_pdata.tuner_i2c_addr = 0x14;
+
+ dvb->i2c_client_demod = dvb_module_probe("tda10071", "tda10071_cx24118",
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x55, &tda10071_pdata);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ dvb->fe[0] = tda10071_pdata.get_dvb_frontend(dvb->i2c_client_demod);
+
+ /* attach SEC */
+ a8293_pdata.dvb_frontend = dvb->fe[0];
+
+ dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x08, &a8293_pdata);
+ if (!dvb->i2c_client_sec) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int em28178_dvb_init_pctv_461e(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct i2c_adapter *i2c_adapter;
+ struct m88ds3103_platform_data m88ds3103_pdata = {};
+ struct ts2020_config ts2020_config = {};
+ struct a8293_platform_data a8293_pdata = {};
+
+ /* attach demod */
+ m88ds3103_pdata.clk = 27000000;
+ m88ds3103_pdata.i2c_wr_max = 33;
+ m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
+ m88ds3103_pdata.ts_clk = 16000;
+ m88ds3103_pdata.ts_clk_pol = 1;
+ m88ds3103_pdata.agc = 0x99;
+
+ dvb->i2c_client_demod = dvb_module_probe("m88ds3103", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x68, &m88ds3103_pdata);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(dvb->i2c_client_demod);
+ i2c_adapter = m88ds3103_pdata.get_i2c_adapter(dvb->i2c_client_demod);
+
+ /* attach tuner */
+ ts2020_config.fe = dvb->fe[0];
+
+ dvb->i2c_client_tuner = dvb_module_probe("ts2020", "ts2022",
+ i2c_adapter,
+ 0x60, &ts2020_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ /* delegate signal strength measurement to tuner */
+ dvb->fe[0]->ops.read_signal_strength =
+ dvb->fe[0]->ops.tuner_ops.get_rf_strength;
+
+ /* attach SEC */
+ a8293_pdata.dvb_frontend = dvb->fe[0];
+ dvb->i2c_client_sec = dvb_module_probe("a8293", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x08, &a8293_pdata);
+ if (!dvb->i2c_client_sec) {
+ dvb_module_release(dvb->i2c_client_tuner);
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int em28178_dvb_init_pctv_292e(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct i2c_adapter *adapter;
+ struct si2168_config si2168_config = {};
+ struct si2157_config si2157_config = {};
+
+ /* attach demod */
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &dvb->fe[0];
+ si2168_config.ts_mode = SI2168_TS_PARALLEL;
+ si2168_config.spectral_inversion = true;
+
+ dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x64, &si2168_config);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ /* attach tuner */
+ si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 1;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+ si2157_config.mdev = dev->media_dev;
+#endif
+ dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
+ adapter,
+ 0x60, &si2157_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+ dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
+
+ return 0;
+}
+
+static int em28178_dvb_init_terratec_t2_stick_hd(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct i2c_adapter *adapter;
+ struct si2168_config si2168_config = {};
+ struct si2157_config si2157_config = {};
+
+ /* attach demod */
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &dvb->fe[0];
+ si2168_config.ts_mode = SI2168_TS_PARALLEL;
+
+ dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x64, &si2168_config);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 0;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+ si2157_config.mdev = dev->media_dev;
+#endif
+ dvb->i2c_client_tuner = dvb_module_probe("si2157", "si2146",
+ adapter,
+ 0x60, &si2157_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int em28178_dvb_init_plex_px_bcud(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct tc90522_config tc90522_config = {};
+ struct qm1d1c0042_config qm1d1c0042_config = {};
+
+ /* attach demod */
+ dvb->i2c_client_demod = dvb_module_probe("tc90522", "tc90522sat",
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x15, &tc90522_config);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ /* attach tuner */
+ qm1d1c0042_config.fe = tc90522_config.fe;
+ qm1d1c0042_config.lpf = 1;
+
+ dvb->i2c_client_tuner = dvb_module_probe("qm1d1c0042", NULL,
+ tc90522_config.tuner_i2c,
+ 0x61, &qm1d1c0042_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ dvb->fe[0] = tc90522_config.fe;
+ px_bcud_init(dev);
+
+ return 0;
+}
+
+static int em28174_dvb_init_hauppauge_wintv_dualhd_dvb(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct i2c_adapter *adapter;
+ struct si2168_config si2168_config = {};
+ struct si2157_config si2157_config = {};
+ unsigned char addr;
+
+ /* attach demod */
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &dvb->fe[0];
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ si2168_config.spectral_inversion = true;
+ addr = (dev->ts == PRIMARY_TS) ? 0x64 : 0x67;
+
+ dvb->i2c_client_demod = dvb_module_probe("si2168", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ addr, &si2168_config);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 1;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+ si2157_config.mdev = dev->media_dev;
+#endif
+ addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x63;
+
+ dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
+ adapter,
+ addr, &si2157_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int em28174_dvb_init_hauppauge_wintv_dualhd_01595(struct em28xx *dev)
+{
+ struct em28xx_dvb *dvb = dev->dvb;
+ struct i2c_adapter *adapter;
+ struct lgdt3306a_config lgdt3306a_config = {};
+ struct si2157_config si2157_config = {};
+ unsigned char addr;
+
+ /* attach demod */
+ lgdt3306a_config = hauppauge_01595_lgdt3306a_config;
+ lgdt3306a_config.fe = &dvb->fe[0];
+ lgdt3306a_config.i2c_adapter = &adapter;
+ addr = (dev->ts == PRIMARY_TS) ? 0x59 : 0x0e;
+
+ dvb->i2c_client_demod = dvb_module_probe("lgdt3306a", NULL,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ addr, &lgdt3306a_config);
+ if (!dvb->i2c_client_demod)
+ return -ENODEV;
+
+ /* attach tuner */
+ si2157_config.fe = dvb->fe[0];
+ si2157_config.if_port = 1;
+ si2157_config.inversion = 1;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+ si2157_config.mdev = dev->media_dev;
+#endif
+ addr = (dev->ts == PRIMARY_TS) ? 0x60 : 0x62;
+
+ dvb->i2c_client_tuner = dvb_module_probe("si2157", NULL,
+ adapter,
+ 0x60, &si2157_config);
+ if (!dvb->i2c_client_tuner) {
+ dvb_module_release(dvb->i2c_client_demod);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int em28xx_dvb_init(struct em28xx *dev)
{
- int result = 0;
+ int result = 0, dvb_alt = 0;
struct em28xx_dvb *dvb;
+ struct usb_device *udev;
if (dev->is_audio_only) {
/* Shouldn't initialize IR for this interface */
@@ -1143,12 +1419,13 @@ static int em28xx_dvb_init(struct em28xx *dev)
dev_info(&dev->intf->dev, "Binding DVB extension\n");
- dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
+ dvb = kzalloc(sizeof(*dvb), GFP_KERNEL);
if (!dvb)
return -ENOMEM;
dev->dvb = dvb;
- dvb->fe[0] = dvb->fe[1] = NULL;
+ dvb->fe[0] = NULL;
+ dvb->fe[1] = NULL;
/* pre-allocate DVB usb transfer buffers */
if (dev->dvb_xfer_bulk) {
@@ -1178,7 +1455,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
switch (dev->model) {
case EM2874_BOARD_LEADERSHIP_ISDBT:
dvb->fe[0] = dvb_attach(s921_attach,
- &sharp_isdbt, &dev->i2c_adap[dev->def_i2c_bus]);
+ &sharp_isdbt,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (!dvb->fe[0]) {
result = -EINVAL;
@@ -1191,8 +1469,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
dvb->fe[0] = dvb_attach(lgdt330x_attach,
- &em2880_lgdt3303_dev,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &em2880_lgdt3303_dev,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
@@ -1200,8 +1478,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2880_BOARD_KWORLD_DVB_310U:
dvb->fe[0] = dvb_attach(zl10353_attach,
- &em28xx_zl10353_with_xc3028,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &em28xx_zl10353_with_xc3028,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
@@ -1211,8 +1489,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
case EM2882_BOARD_TERRATEC_HYBRID_XS:
case EM2880_BOARD_EMPIRE_DUAL_TV:
dvb->fe[0] = dvb_attach(zl10353_attach,
- &em28xx_zl10353_xc3028_no_i2c_gate,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &em28xx_zl10353_xc3028_no_i2c_gate,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
@@ -1223,16 +1501,17 @@ static int em28xx_dvb_init(struct em28xx *dev)
case EM2881_BOARD_PINNACLE_HYBRID_PRO:
case EM2882_BOARD_DIKOM_DK300:
case EM2882_BOARD_KWORLD_VS_DVBT:
+ /*
+ * Those boards could have either a zl10353 or a mt352.
+ * If the chip id isn't for zl10353, try mt352.
+ */
dvb->fe[0] = dvb_attach(zl10353_attach,
- &em28xx_zl10353_xc3028_no_i2c_gate,
- &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] == NULL) {
- /* This board could have either a zl10353 or a mt352.
- If the chip id isn't for zl10353, try mt352 */
+ &em28xx_zl10353_xc3028_no_i2c_gate,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (!dvb->fe[0])
dvb->fe[0] = dvb_attach(mt352_attach,
- &terratec_xs_mt352_cfg,
- &dev->i2c_adap[dev->def_i2c_bus]);
- }
+ &terratec_xs_mt352_cfg,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
@@ -1241,27 +1520,28 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2870_BOARD_TERRATEC_XS_MT2060:
dvb->fe[0] = dvb_attach(zl10353_attach,
- &em28xx_zl10353_no_i2c_gate_dev,
- &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL) {
+ &em28xx_zl10353_no_i2c_gate_dev,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (dvb->fe[0]) {
dvb_attach(mt2060_attach, dvb->fe[0],
- &dev->i2c_adap[dev->def_i2c_bus],
- &em28xx_mt2060_config, 1220);
+ &dev->i2c_adap[dev->def_i2c_bus],
+ &em28xx_mt2060_config, 1220);
}
break;
case EM2870_BOARD_KWORLD_355U:
dvb->fe[0] = dvb_attach(zl10353_attach,
- &em28xx_zl10353_no_i2c_gate_dev,
- &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL)
+ &em28xx_zl10353_no_i2c_gate_dev,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (dvb->fe[0])
dvb_attach(qt1010_attach, dvb->fe[0],
- &dev->i2c_adap[dev->def_i2c_bus], &em28xx_qt1010_config);
+ &dev->i2c_adap[dev->def_i2c_bus],
+ &em28xx_qt1010_config);
break;
case EM2883_BOARD_KWORLD_HYBRID_330U:
case EM2882_BOARD_EVGA_INDTUBE:
dvb->fe[0] = dvb_attach(s5h1409_attach,
- &em28xx_s5h1409_with_xc3028,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &em28xx_s5h1409_with_xc3028,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (em28xx_attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
@@ -1269,9 +1549,9 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2882_BOARD_KWORLD_ATSC_315U:
dvb->fe[0] = dvb_attach(lgdt330x_attach,
- &em2880_lgdt3303_dev,
- &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL) {
+ &em2880_lgdt3303_dev,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (dvb->fe[0]) {
if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
&dev->i2c_adap[dev->def_i2c_bus],
0x61, TUNER_THOMSON_DTT761X)) {
@@ -1293,8 +1573,9 @@ static int em28xx_dvb_init(struct em28xx *dev)
case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
/* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
dvb->fe[0] = dvb_attach(tda10023_attach,
- &em28xx_tda10023_config,
- &dev->i2c_adap[dev->def_i2c_bus], 0x48);
+ &em28xx_tda10023_config,
+ &dev->i2c_adap[dev->def_i2c_bus],
+ 0x48);
if (dvb->fe[0]) {
if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
&dev->i2c_adap[dev->def_i2c_bus],
@@ -1306,18 +1587,18 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2870_BOARD_KWORLD_A340:
dvb->fe[0] = dvb_attach(lgdt3305_attach,
- &em2870_lgdt3304_dev,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &em2870_lgdt3304_dev,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (!dvb->fe[0]) {
result = -EINVAL;
goto out_free;
}
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
&dev->i2c_adap[dev->def_i2c_bus],
- &kworld_a340_config)) {
- dvb_frontend_detach(dvb->fe[0]);
- result = -EINVAL;
- goto out_free;
+ &kworld_a340_config)) {
+ dvb_frontend_detach(dvb->fe[0]);
+ result = -EINVAL;
+ goto out_free;
}
break;
case EM28174_BOARD_PCTV_290E:
@@ -1335,7 +1616,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
0x60,
&dev->i2c_adap[dev->def_i2c_bus],
&em28xx_cxd2820r_tda18271_config)) {
-
dvb_frontend_detach(dvb->fe[0]);
result = -EINVAL;
goto out_free;
@@ -1360,12 +1640,13 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
{
- struct xc5000_config cfg;
+ struct xc5000_config cfg = {};
hauppauge_hvr930c_init(dev);
dvb->fe[0] = dvb_attach(drxk_attach,
- &hauppauge_930c_drxk, &dev->i2c_adap[dev->def_i2c_bus]);
+ &hauppauge_930c_drxk,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (!dvb->fe[0]) {
result = -EINVAL;
goto out_free;
@@ -1377,14 +1658,13 @@ static int em28xx_dvb_init(struct em28xx *dev)
dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
/* Attach xc5000 */
- memset(&cfg, 0, sizeof(cfg));
cfg.i2c_address = 0x61;
cfg.if_khz = 4000;
if (dvb->fe[0]->ops.i2c_gate_ctrl)
dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
- if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus],
- &cfg)) {
+ if (!dvb_attach(xc5000_attach, dvb->fe[0],
+ &dev->i2c_adap[dev->def_i2c_bus], &cfg)) {
result = -EINVAL;
goto out_free;
}
@@ -1396,7 +1676,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
case EM2884_BOARD_TERRATEC_H5:
terratec_h5_init(dev);
- dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap[dev->def_i2c_bus]);
+ dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk,
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (!dvb->fe[0]) {
result = -EINVAL;
goto out_free;
@@ -1410,7 +1691,8 @@ static int em28xx_dvb_init(struct em28xx *dev)
/* Attach tda18271 to DVB-C frontend */
if (dvb->fe[0]->ops.i2c_gate_ctrl)
dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
- if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], 0x60)) {
+ if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0],
+ &dev->i2c_adap[dev->def_i2c_bus], 0x60)) {
result = -EINVAL;
goto out_free;
}
@@ -1420,72 +1702,23 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2884_BOARD_C3TECH_DIGITAL_DUO:
dvb->fe[0] = dvb_attach(mb86a20s_attach,
- &c3tech_duo_mb86a20s_config,
- &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL)
+ &c3tech_duo_mb86a20s_config,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (dvb->fe[0])
dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
&dev->i2c_adap[dev->def_i2c_bus],
&c3tech_duo_tda18271_config);
break;
- case EM28174_BOARD_PCTV_460E: {
- struct i2c_client *client;
- struct i2c_board_info board_info;
- struct tda10071_platform_data tda10071_pdata = {};
- struct a8293_platform_data a8293_pdata = {};
-
- /* attach demod + tuner combo */
- tda10071_pdata.clk = 40444000, /* 40.444 MHz */
- tda10071_pdata.i2c_wr_max = 64,
- tda10071_pdata.ts_mode = TDA10071_TS_SERIAL,
- tda10071_pdata.pll_multiplier = 20,
- tda10071_pdata.tuner_i2c_addr = 0x14,
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE);
- board_info.addr = 0x55;
- board_info.platform_data = &tda10071_pdata;
- request_module("tda10071");
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
+ case EM28174_BOARD_PCTV_460E:
+ result = em28174_dvb_init_pctv_460e(dev);
+ if (result)
goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
- dvb->fe[0] = tda10071_pdata.get_dvb_frontend(client);
- dvb->i2c_client_demod = client;
-
- /* attach SEC */
- a8293_pdata.dvb_frontend = dvb->fe[0];
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
- board_info.addr = 0x08;
- board_info.platform_data = &a8293_pdata;
- request_module("a8293");
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- dvb->i2c_client_sec = client;
break;
- }
case EM2874_BOARD_DELOCK_61959:
case EM2874_BOARD_MAXMEDIA_UB425_TC:
/* attach demodulator */
dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (dvb->fe[0]) {
/* disable I2C-gate */
@@ -1507,7 +1740,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
/* attach demodulator */
dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk,
- &dev->i2c_adap[dev->def_i2c_bus]);
+ &dev->i2c_adap[dev->def_i2c_bus]);
if (dvb->fe[0]) {
/* attach tuner */
@@ -1579,13 +1812,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
break;
case EM2874_BOARD_KWORLD_UB435Q_V3:
{
- struct i2c_client *client;
struct i2c_adapter *adapter = &dev->i2c_adap[dev->def_i2c_bus];
- struct i2c_board_info board_info = {
- .type = "tda18212",
- .addr = 0x60,
- .platform_data = &kworld_ub435q_v3_config,
- };
dvb->fe[0] = dvb_attach(lgdt3305_attach,
&em2874_lgdt3305_nogate_dev,
@@ -1597,28 +1824,23 @@ static int em28xx_dvb_init(struct em28xx *dev)
/* attach tuner */
kworld_ub435q_v3_config.fe = dvb->fe[0];
- request_module("tda18212");
- client = i2c_new_device(adapter, &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- dvb_frontend_detach(dvb->fe[0]);
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
+ dvb->i2c_client_tuner = dvb_module_probe("tda18212", NULL,
+ adapter, 0x60,
+ &kworld_ub435q_v3_config);
+ if (!dvb->i2c_client_tuner) {
dvb_frontend_detach(dvb->fe[0]);
result = -ENODEV;
goto out_free;
}
-
- dvb->i2c_client_tuner = client;
break;
}
case EM2874_BOARD_PCTV_HD_MINI_80E:
- dvb->fe[0] = dvb_attach(drx39xxj_attach, &dev->i2c_adap[dev->def_i2c_bus]);
- if (dvb->fe[0] != NULL) {
- dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+ dvb->fe[0] = dvb_attach(drx39xxj_attach,
+ &dev->i2c_adap[dev->def_i2c_bus]);
+ if (dvb->fe[0]) {
+ dvb->fe[0] = dvb_attach(tda18271_attach, dvb->fe[0],
+ 0x60,
&dev->i2c_adap[dev->def_i2c_bus],
&pinnacle_80e_dvb_config);
if (!dvb->fe[0]) {
@@ -1627,410 +1849,42 @@ static int em28xx_dvb_init(struct em28xx *dev)
}
}
break;
- case EM28178_BOARD_PCTV_461E: {
- struct i2c_client *client;
- struct i2c_adapter *i2c_adapter;
- struct i2c_board_info board_info;
- struct m88ds3103_platform_data m88ds3103_pdata = {};
- struct ts2020_config ts2020_config = {};
- struct a8293_platform_data a8293_pdata = {};
-
- /* attach demod */
- m88ds3103_pdata.clk = 27000000;
- m88ds3103_pdata.i2c_wr_max = 33;
- m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
- m88ds3103_pdata.ts_clk = 16000;
- m88ds3103_pdata.ts_clk_pol = 1;
- m88ds3103_pdata.agc = 0x99;
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
- board_info.addr = 0x68;
- board_info.platform_data = &m88ds3103_pdata;
- request_module("m88ds3103");
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
- dvb->fe[0] = m88ds3103_pdata.get_dvb_frontend(client);
- i2c_adapter = m88ds3103_pdata.get_i2c_adapter(client);
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- ts2020_config.fe = dvb->fe[0];
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE);
- board_info.addr = 0x60;
- board_info.platform_data = &ts2020_config;
- request_module("ts2020");
- client = i2c_new_device(i2c_adapter, &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- dvb->i2c_client_tuner = client;
- /* delegate signal strength measurement to tuner */
- dvb->fe[0]->ops.read_signal_strength =
- dvb->fe[0]->ops.tuner_ops.get_rf_strength;
-
- /* attach SEC */
- a8293_pdata.dvb_frontend = dvb->fe[0];
- memset(&board_info, 0, sizeof(board_info));
- strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
- board_info.addr = 0x08;
- board_info.platform_data = &a8293_pdata;
- request_module("a8293");
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &board_info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_tuner->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_tuner);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_tuner->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_tuner);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
+ case EM28178_BOARD_PCTV_461E:
+ result = em28178_dvb_init_pctv_461e(dev);
+ if (result)
goto out_free;
- }
- dvb->i2c_client_sec = client;
break;
- }
case EM28178_BOARD_PCTV_292E:
- {
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &dvb->fe[0];
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = dvb->fe[0];
- si2157_config.if_port = 1;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
- si2157_config.mdev = dev->media_dev;
-#endif
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module(info.type);
- client = i2c_new_device(adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_tuner = client;
- dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
- }
+ result = em28178_dvb_init_pctv_292e(dev);
+ if (result)
+ goto out_free;
break;
case EM28178_BOARD_TERRATEC_T2_STICK_HD:
- {
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &dvb->fe[0];
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = dvb->fe[0];
- si2157_config.if_port = 0;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
- si2157_config.mdev = dev->media_dev;
-#endif
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2146", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module("si2157");
- client = i2c_new_device(adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_tuner = client;
- }
+ result = em28178_dvb_init_terratec_t2_stick_hd(dev);
+ if (result)
+ goto out_free;
break;
-
case EM28178_BOARD_PLEX_PX_BCUD:
- {
- struct i2c_client *client;
- struct i2c_board_info info;
- struct tc90522_config tc90522_config;
- struct qm1d1c0042_config qm1d1c0042_config;
-
- /* attach demod */
- memset(&tc90522_config, 0, sizeof(tc90522_config));
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "tc90522sat", I2C_NAME_SIZE);
- info.addr = 0x15;
- info.platform_data = &tc90522_config;
- request_module("tc90522");
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
- dvb->i2c_client_demod = client;
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- /* attach tuner */
- memset(&qm1d1c0042_config, 0,
- sizeof(qm1d1c0042_config));
- qm1d1c0042_config.fe = tc90522_config.fe;
- qm1d1c0042_config.lpf = 1;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "qm1d1c0042", I2C_NAME_SIZE);
- info.addr = 0x61;
- info.platform_data = &qm1d1c0042_config;
- request_module(info.type);
- client = i2c_new_device(tc90522_config.tuner_i2c,
- &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- dvb->i2c_client_tuner = client;
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- dvb->fe[0] = tc90522_config.fe;
- px_bcud_init(dev);
- }
+ result = em28178_dvb_init_plex_px_bcud(dev);
+ if (result)
+ goto out_free;
break;
case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB:
- {
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &dvb->fe[0];
- si2168_config.ts_mode = SI2168_TS_SERIAL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = dvb->fe[0];
- si2157_config.if_port = 1;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
- si2157_config.mdev = dev->media_dev;
-#endif
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module(info.type);
- client = i2c_new_device(adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_tuner = client;
-
- }
+ result = em28174_dvb_init_hauppauge_wintv_dualhd_dvb(dev);
+ if (result)
+ goto out_free;
break;
case EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595:
- {
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info = {};
- struct lgdt3306a_config lgdt3306a_config;
- struct si2157_config si2157_config = {};
-
- /* attach demod */
- lgdt3306a_config = hauppauge_01595_lgdt3306a_config;
- lgdt3306a_config.fe = &dvb->fe[0];
- lgdt3306a_config.i2c_adapter = &adapter;
- strlcpy(info.type, "lgdt3306a", sizeof(info.type));
- info.addr = 0x59;
- info.platform_data = &lgdt3306a_config;
- request_module(info.type);
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus],
- &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- si2157_config.fe = dvb->fe[0];
- si2157_config.if_port = 1;
- si2157_config.inversion = 1;
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
- si2157_config.mdev = dev->media_dev;
-#endif
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", sizeof(info.type));
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module(info.type);
-
- client = i2c_new_device(adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_tuner = client;
- }
+ result = em28174_dvb_init_hauppauge_wintv_dualhd_01595(dev);
+ if (result)
+ goto out_free;
break;
default:
dev_err(&dev->intf->dev,
"The frontend of your DVB/ATSC card isn't supported yet\n");
break;
}
- if (NULL == dvb->fe[0]) {
+ if (!dvb->fe[0]) {
dev_err(&dev->intf->dev, "frontend initialization failed\n");
result = -EINVAL;
goto out_free;
@@ -2046,6 +1900,14 @@ static int em28xx_dvb_init(struct em28xx *dev)
if (result < 0)
goto out_free;
+ if (dev->dvb_xfer_bulk) {
+ dvb_alt = 0;
+ } else { /* isoc */
+ dvb_alt = dev->dvb_alt_isoc;
+ }
+
+ udev = interface_to_usbdev(dev->intf);
+ usb_set_interface(udev, dev->ifnum, dvb_alt);
dev_info(&dev->intf->dev, "DVB extension successfully initialized\n");
kref_get(&dev->ref);
@@ -2071,7 +1933,6 @@ static inline void prevent_sleep(struct dvb_frontend_ops *ops)
static int em28xx_dvb_fini(struct em28xx *dev)
{
struct em28xx_dvb *dvb;
- struct i2c_client *client;
if (dev->is_audio_only) {
/* Shouldn't initialize IR for this interface */
@@ -2093,8 +1954,10 @@ static int em28xx_dvb_fini(struct em28xx *dev)
em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
if (dev->disconnected) {
- /* We cannot tell the device to sleep
- * once it has been unplugged. */
+ /*
+ * We cannot tell the device to sleep
+ * once it has been unplugged.
+ */
if (dvb->fe[0]) {
prevent_sleep(&dvb->fe[0]->ops);
dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED;
@@ -2107,26 +1970,10 @@ static int em28xx_dvb_fini(struct em28xx *dev)
em28xx_unregister_dvb(dvb);
- /* remove I2C SEC */
- client = dvb->i2c_client_sec;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C tuner */
- client = dvb->i2c_client_tuner;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C demod */
- client = dvb->i2c_client_demod;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
+ /* release I2C module bindings */
+ dvb_module_release(dvb->i2c_client_sec);
+ dvb_module_release(dvb->i2c_client_tuner);
+ dvb_module_release(dvb->i2c_client_demod);
kfree(dvb);
dev->dvb = NULL;
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 9bf49d6..9151bcc 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -1,26 +1,22 @@
-/*
- em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
- Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- Markus Rechberger <mrechberger@gmail.com>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Sascha Sommer <saschasommer@freenet.de>
- Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+//
+// Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+// Markus Rechberger <mrechberger@gmail.com>
+// Mauro Carvalho Chehab <mchehab@infradead.org>
+// Sascha Sommer <saschasommer@freenet.de>
+// Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -50,6 +46,35 @@ MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I
"i2c: %s: " fmt, __func__, ## arg); \
} while (0)
+/*
+ * Time in msecs to wait for i2c xfers to finish.
+ * 35ms is the maximum time a SMBUS device could wait when
+ * clock stretching is used. As the transfer itself will take
+ * some time to happen, set it to 35 ms.
+ *
+ * Ok, I2C doesn't specify any limit. So, eventually, we may need
+ * to increase this timeout.
+ */
+#define EM28XX_I2C_XFER_TIMEOUT 35 /* ms */
+
+static int em28xx_i2c_timeout(struct em28xx *dev)
+{
+ int time = EM28XX_I2C_XFER_TIMEOUT;
+
+ switch (dev->i2c_speed & 0x03) {
+ case EM28XX_I2C_FREQ_25_KHZ:
+ time += 4; /* Assume 4 ms for transfers */
+ break;
+ case EM28XX_I2C_FREQ_100_KHZ:
+ case EM28XX_I2C_FREQ_400_KHZ:
+ time += 1; /* Assume 1 ms for transfers */
+ break;
+ default: /* EM28XX_I2C_FREQ_1_5_MHZ */
+ break;
+ }
+
+ return msecs_to_jiffies(time);
+}
/*
* em2800_i2c_send_bytes()
@@ -57,14 +82,13 @@ MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I
*/
static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
{
- unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
+ unsigned long timeout = jiffies + em28xx_i2c_timeout(dev);
int ret;
u8 b2[6];
if (len < 1 || len > 4)
return -EOPNOTSUPP;
- BUG_ON(len < 1 || len > 4);
b2[5] = 0x80 + len - 1;
b2[4] = addr;
b2[3] = buf[0];
@@ -98,7 +122,7 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
ret);
return ret;
}
- msleep(5);
+ usleep_range(5000, 6000);
}
dprintk(0, "write to i2c device at 0x%x timed out\n", addr);
return -ETIMEDOUT;
@@ -110,7 +134,7 @@ static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
*/
static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
{
- unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
+ unsigned long timeout = jiffies + em28xx_i2c_timeout(dev);
u8 buf2[4];
int ret;
int i;
@@ -145,14 +169,13 @@ static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
ret);
return ret;
}
- msleep(5);
+ usleep_range(5000, 6000);
}
- if (ret != 0x84 + len - 1) {
+ if (ret != 0x84 + len - 1)
dprintk(0, "read from i2c device at 0x%x timed out\n", addr);
- }
/* get the received message */
- ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
+ ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4 - len, buf2, len);
if (ret != len) {
dev_warn(&dev->intf->dev,
"reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
@@ -186,7 +209,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
u16 len, int stop)
{
- unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
+ unsigned long timeout = jiffies + em28xx_i2c_timeout(dev);
int ret;
if (len < 1 || len > 64)
@@ -204,12 +227,11 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
"writing to i2c device at 0x%x failed (error=%i)\n",
addr, ret);
return ret;
- } else {
- dev_warn(&dev->intf->dev,
- "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
- len, addr, ret);
- return -EIO;
}
+ dev_warn(&dev->intf->dev,
+ "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
+ len, addr, ret);
+ return -EIO;
}
/* wait for completion */
@@ -228,7 +250,7 @@ static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
ret);
return ret;
}
- msleep(5);
+ usleep_range(5000, 6000);
/*
* NOTE: do we really have to wait for success ?
* Never seen anything else than 0x00 or 0x10
@@ -351,12 +373,12 @@ static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
"writing to i2c device at 0x%x failed (error=%i)\n",
addr, ret);
return ret;
- } else {
- dev_warn(&dev->intf->dev,
- "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
- len, addr, ret);
- return -EIO;
}
+
+ dev_warn(&dev->intf->dev,
+ "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
+ len, addr, ret);
+ return -EIO;
}
/* Check success */
ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
@@ -366,7 +388,8 @@ static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
*/
if (!ret)
return len;
- else if (ret > 0) {
+
+ if (ret > 0) {
dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
return -ENXIO;
}
@@ -420,7 +443,8 @@ static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
*/
if (!ret)
return len;
- else if (ret > 0) {
+
+ if (ret > 0) {
dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
return -ENXIO;
}
@@ -508,13 +532,15 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
{
struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
struct em28xx *dev = i2c_bus->dev;
- unsigned bus = i2c_bus->bus;
+ unsigned int bus = i2c_bus->bus;
int addr, rc, i;
u8 reg;
- /* prevent i2c xfer attempts after device is disconnected
- some fe's try to do i2c writes/reads from their release
- interfaces when called in disconnect path */
+ /*
+ * prevent i2c xfer attempts after device is disconnected
+ * some fe's try to do i2c writes/reads from their release
+ * interfaces when called in disconnect path
+ */
if (dev->disconnected)
return -ENODEV;
@@ -597,12 +623,13 @@ static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
if (len == length) {
c = (char)len;
len = -1;
- } else
+ } else {
c = *buf++;
+ }
l = (l << 8) | c;
len++;
if ((len & (32 / 8 - 1)) == 0)
- hash = ((hash^l) * 0x9e370001UL);
+ hash = ((hash ^ l) * 0x9e370001UL);
} while (len);
return (hash >> (32 - bits)) & 0xffffffffUL;
@@ -612,7 +639,7 @@ static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
* Helper function to read data blocks from i2c clients with 8 or 16 bit
* address width, 8 bit register width and auto incrementation been activated
*/
-static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
+static int em28xx_i2c_read_block(struct em28xx *dev, unsigned int bus, u16 addr,
bool addr_w16, u16 len, u8 *data)
{
int remain = len, rsize, rsize_max, ret;
@@ -624,7 +651,8 @@ static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
/* Select address */
buf[0] = addr >> 8;
buf[1] = addr & 0xff;
- ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
+ ret = i2c_master_send(&dev->i2c_client[bus],
+ buf + !addr_w16, 1 + addr_w16);
if (ret < 0)
return ret;
/* Read data */
@@ -649,7 +677,7 @@ static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
return len;
}
-static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
+static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned int bus,
u8 **eedata, u16 *eedata_len)
{
const u16 len = 256;
@@ -677,7 +705,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
}
data = kzalloc(len, GFP_KERNEL);
- if (data == NULL)
+ if (!data)
return -ENOMEM;
/* Read EEPROM content */
@@ -710,8 +738,8 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
mc_start = (data[1] << 8) + 4; /* usually 0x0004 */
dev_info(&dev->intf->dev,
- "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
- data[0], data[1], data[2], data[3], dev->hash);
+ "EEPROM ID = %4ph, EEPROM hash = 0x%08lx\n",
+ data, dev->hash);
dev_info(&dev->intf->dev,
"EEPROM info:\n");
dev_info(&dev->intf->dev,
@@ -769,15 +797,18 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
return 0;
}
- /* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
+ /*
+ * TODO: decrypt eeprom data for camera bridges
+ * (em25xx, em276x+)
+ */
} else if (!dev->eeprom_addrwidth_16bit &&
data[0] == 0x1a && data[1] == 0xeb &&
data[2] == 0x67 && data[3] == 0x95) {
dev->hash = em28xx_hash_mem(data, len, 32);
dev_info(&dev->intf->dev,
- "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
- data[0], data[1], data[2], data[3], dev->hash);
+ "EEPROM ID = %4ph, EEPROM hash = 0x%08lx\n",
+ data, dev->hash);
dev_info(&dev->intf->dev,
"EEPROM info:\n");
} else {
@@ -859,8 +890,8 @@ static u32 functionality(struct i2c_adapter *i2c_adap)
{
struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
- if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
- (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
+ if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX ||
+ i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B) {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800) {
return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
@@ -893,7 +924,7 @@ static const struct i2c_client em28xx_client_template = {
* incomplete list of known devices
*/
static char *i2c_devs[128] = {
- [0x1c >> 1] = "lgdt330x",
+ [0x1c >> 1] = "lgdt330x",
[0x3e >> 1] = "remote IR sensor",
[0x4a >> 1] = "saa7113h",
[0x52 >> 1] = "drxk",
@@ -916,7 +947,7 @@ static char *i2c_devs[128] = {
* do_i2c_scan()
* check i2c address range for devices
*/
-void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
+void em28xx_do_i2c_scan(struct em28xx *dev, unsigned int bus)
{
u8 i2c_devicelist[128];
unsigned char buf;
@@ -944,13 +975,14 @@ void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
* em28xx_i2c_register()
* register i2c bus
*/
-int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
+int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
enum em28xx_i2c_algo_type algo_type)
{
int retval;
- BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
- BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
+ if (WARN_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg ||
+ !dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req))
+ return -ENODEV;
if (bus >= NUM_I2C_BUSES)
return -ENODEV;
@@ -977,8 +1009,9 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
/* Up to now, all eeproms are at bus 0 */
if (!bus) {
- retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
- if ((retval < 0) && (retval != -ENODEV)) {
+ retval = em28xx_i2c_eeprom(dev, bus,
+ &dev->eedata, &dev->eedata_len);
+ if (retval < 0 && retval != -ENODEV) {
dev_err(&dev->intf->dev,
"%s: em28xx_i2_eeprom failed! retval [%d]\n",
__func__, retval);
@@ -995,7 +1028,7 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
* em28xx_i2c_unregister()
* unregister i2c_bus
*/
-int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
+int em28xx_i2c_unregister(struct em28xx *dev, unsigned int bus)
{
if (bus >= NUM_I2C_BUSES)
return -ENODEV;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 046223d..2dc1be0 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -1,25 +1,21 @@
-/*
- handle em28xx IR remotes via linux kernel input layer.
-
- Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- Markus Rechberger <mrechberger@gmail.com>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Sascha Sommer <saschasommer@freenet.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// handle em28xx IR remotes via linux kernel input layer.
+//
+// Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+// Markus Rechberger <mrechberger@gmail.com>
+// Mauro Carvalho Chehab <mchehab@infradead.org>
+// Sascha Sommer <saschasommer@freenet.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -41,15 +37,15 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define MODULE_NAME "em28xx"
-#define dprintk( fmt, arg...) do { \
+#define dprintk(fmt, arg...) do { \
if (ir_debug) \
dev_printk(KERN_DEBUG, &ir->dev->intf->dev, \
"input: %s: " fmt, __func__, ## arg); \
} while (0)
-/**********************************************************
- Polling structure used by em28xx IR's
- **********************************************************/
+/*
+ * Polling structure used by em28xx IR's
+ */
struct em28xx_ir_poll_result {
unsigned int toggle_bit:1;
@@ -76,24 +72,31 @@ struct em28xx_IR {
int (*get_key_i2c)(struct i2c_client *ir, enum rc_proto *protocol,
u32 *scancode);
- int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
+ int (*get_key)(struct em28xx_IR *ir, struct em28xx_ir_poll_result *r);
};
-/**********************************************************
- I2C IR based get keycodes - should be used with ir-kbd-i2c
- **********************************************************/
+/*
+ * I2C IR based get keycodes - should be used with ir-kbd-i2c
+ */
static int em28xx_get_key_terratec(struct i2c_client *i2c_dev,
enum rc_proto *protocol, u32 *scancode)
{
+ int rc;
unsigned char b;
/* poll IR chip */
- if (1 != i2c_master_recv(i2c_dev, &b, 1))
+ rc = i2c_master_recv(i2c_dev, &b, 1);
+ if (rc != 1) {
+ if (rc < 0)
+ return rc;
return -EIO;
+ }
- /* it seems that 0xFE indicates that a button is still hold
- down, while 0xff indicates that no button is hold down. */
+ /*
+ * it seems that 0xFE indicates that a button is still hold
+ * down, while 0xff indicates that no button is hold down.
+ */
if (b == 0xff)
return 0;
@@ -145,7 +148,7 @@ static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev,
/* poll IR chip */
- if (3 != i2c_master_recv(i2c_dev, buf, 3))
+ if (i2c_master_recv(i2c_dev, buf, 3) != 3)
return -EIO;
if (buf[0] != 0x00)
@@ -162,18 +165,28 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev,
{
unsigned char subaddr, keydetect, key;
- struct i2c_msg msg[] = { { .addr = i2c_dev->addr, .flags = 0, .buf = &subaddr, .len = 1},
- { .addr = i2c_dev->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} };
+ struct i2c_msg msg[] = {
+ {
+ .addr = i2c_dev->addr,
+ .flags = 0,
+ .buf = &subaddr, .len = 1
+ }, {
+ .addr = i2c_dev->addr,
+ .flags = I2C_M_RD,
+ .buf = &keydetect,
+ .len = 1
+ }
+ };
subaddr = 0x10;
- if (2 != i2c_transfer(i2c_dev->adapter, msg, 2))
+ if (i2c_transfer(i2c_dev->adapter, msg, 2) != 2)
return -EIO;
if (keydetect == 0x00)
return 0;
subaddr = 0x00;
msg[1].buf = &key;
- if (2 != i2c_transfer(i2c_dev->adapter, msg, 2))
+ if (i2c_transfer(i2c_dev->adapter, msg, 2) != 2)
return -EIO;
if (key == 0x00)
return 0;
@@ -183,9 +196,9 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev,
return 1;
}
-/**********************************************************
- Poll based get keycode functions
- **********************************************************/
+/*
+ * Poll based get keycode functions
+ */
/* This is for the em2860/em2880 */
static int default_polling_getkey(struct em28xx_IR *ir,
@@ -195,8 +208,9 @@ static int default_polling_getkey(struct em28xx_IR *ir,
int rc;
u8 msg[3] = { 0, 0, 0 };
- /* Read key toggle, brand, and key code
- on registers 0x45, 0x46 and 0x47
+ /*
+ * Read key toggle, brand, and key code
+ * on registers 0x45, 0x46 and 0x47
*/
rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR,
msg, sizeof(msg));
@@ -237,8 +251,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
int rc;
u8 msg[5] = { 0, 0, 0, 0, 0 };
- /* Read key toggle, brand, and key code
- on registers 0x51-55
+ /*
+ * Read key toggle, brand, and key code
+ * on registers 0x51-55
*/
rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR,
msg, sizeof(msg));
@@ -294,9 +309,9 @@ static int em2874_polling_getkey(struct em28xx_IR *ir,
return 0;
}
-/**********************************************************
- Polling code for em28xx
- **********************************************************/
+/*
+ * Polling code for em28xx
+ */
static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir)
{
@@ -347,11 +362,14 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir)
if (ir->dev->chip_id == CHIP_ID_EM2874 ||
ir->dev->chip_id == CHIP_ID_EM2884)
- /* The em2874 clears the readcount field every time the
- register is read. The em2860/2880 datasheet says that it
- is supposed to clear the readcount, but it doesn't. So with
- the em2874, we are looking for a non-zero read count as
- opposed to a readcount that is incrementing */
+ /*
+ * The em2874 clears the readcount field every time the
+ * register is read. The em2860/2880 datasheet says
+ * that it is supposed to clear the readcount, but it
+ * doesn't. So with the em2874, we are looking for a
+ * non-zero read count as opposed to a readcount
+ * that is incrementing
+ */
ir->last_readcount = 0;
else
ir->last_readcount = poll_result.read_count;
@@ -476,15 +494,18 @@ static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 *rc_proto)
static int em28xx_probe_i2c_ir(struct em28xx *dev)
{
int i = 0;
- /* Leadtek winfast tv USBII deluxe can find a non working IR-device */
- /* at address 0x18, so if that address is needed for another board in */
- /* the future, please put it after 0x1f. */
+ /*
+ * Leadtek winfast tv USBII deluxe can find a non working IR-device
+ * at address 0x18, so if that address is needed for another board in
+ * the future, please put it after 0x1f.
+ */
const unsigned short addr_list[] = {
0x1f, 0x30, 0x47, I2C_CLIENT_END
};
while (addr_list[i] != I2C_CLIENT_END) {
- if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus], addr_list[i]) == 1)
+ if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus],
+ addr_list[i]) == 1)
return addr_list[i];
i++;
}
@@ -492,9 +513,9 @@ static int em28xx_probe_i2c_ir(struct em28xx *dev)
return -ENODEV;
}
-/**********************************************************
- Handle buttons
- **********************************************************/
+/*
+ * Handle buttons
+ */
static void em28xx_query_buttons(struct work_struct *work)
{
@@ -515,7 +536,10 @@ static void em28xx_query_buttons(struct work_struct *work)
j = 0;
while (dev->board.buttons[j].role >= 0 &&
dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) {
- struct em28xx_button *button = &dev->board.buttons[j];
+ const struct em28xx_button *button;
+
+ button = &dev->board.buttons[j];
+
/* Check if button uses the current address */
if (button->reg_r != dev->button_polling_addresses[i]) {
j++;
@@ -618,7 +642,8 @@ static void em28xx_init_buttons(struct em28xx *dev)
dev->button_polling_interval = EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL;
while (dev->board.buttons[i].role >= 0 &&
dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) {
- struct em28xx_button *button = &dev->board.buttons[i];
+ const struct em28xx_button *button = &dev->board.buttons[i];
+
/* Check if polling address is already on the list */
addr_new = true;
for (j = 0; j < dev->num_button_polling_addresses; j++) {
@@ -649,6 +674,7 @@ static void em28xx_init_buttons(struct em28xx *dev)
/* Add read address to list of polling addresses */
if (addr_new) {
unsigned int index = dev->num_button_polling_addresses;
+
dev->button_polling_addresses[index] = button->reg_r;
dev->num_button_polling_addresses++;
}
@@ -677,7 +703,7 @@ static void em28xx_shutdown_buttons(struct em28xx *dev)
/* Clear polling addresses list */
dev->num_button_polling_addresses = 0;
/* Deregister input devices */
- if (dev->sbutton_input_dev != NULL) {
+ if (dev->sbutton_input_dev) {
dev_info(&dev->intf->dev, "Deregistering snapshot button\n");
input_unregister_device(dev->sbutton_input_dev);
dev->sbutton_input_dev = NULL;
@@ -714,7 +740,7 @@ static int em28xx_ir_init(struct em28xx *dev)
}
}
- if (dev->board.ir_codes == NULL && !dev->board.has_ir_i2c) {
+ if (!dev->board.ir_codes && !dev->board.has_ir_i2c) {
/* No remote control support */
dev_warn(&dev->intf->dev,
"Remote control support is not available for this card.\n");
@@ -764,7 +790,7 @@ static int em28xx_ir_init(struct em28xx *dev)
goto error;
}
- ir->i2c_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ ir->i2c_client = kzalloc(sizeof(*ir->i2c_client), GFP_KERNEL);
if (!ir->i2c_client)
goto error;
ir->i2c_client->adapter = &ir->dev->i2c_adap[dev->def_i2c_bus];
@@ -881,9 +907,11 @@ static int em28xx_ir_suspend(struct em28xx *dev)
if (ir)
cancel_delayed_work_sync(&ir->work);
cancel_delayed_work_sync(&dev->buttons_query_work);
- /* is canceling delayed work sufficient or does the rc event
- kthread needs stopping? kthread is stopped in
- ir_raw_event_unregister() */
+ /*
+ * is canceling delayed work sufficient or does the rc event
+ * kthread needs stopping? kthread is stopped in
+ * ir_raw_event_unregister()
+ */
return 0;
}
@@ -895,8 +923,10 @@ static int em28xx_ir_resume(struct em28xx *dev)
return 0;
dev_info(&dev->intf->dev, "Resuming input extension\n");
- /* if suspend calls ir_raw_event_unregister(), the should call
- ir_raw_event_register() */
+ /*
+ * if suspend calls ir_raw_event_unregister(), the should call
+ * ir_raw_event_register()
+ */
if (ir)
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
if (dev->num_button_polling_addresses)
@@ -924,7 +954,7 @@ static void __exit em28xx_rc_unregister(void)
em28xx_unregister_extension(&rc_ops);
}
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_DESCRIPTION(DRIVER_DESC " - input interface");
MODULE_VERSION(EM28XX_VERSION);
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 9e5cdfb..f53afe1 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -1,17 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#define EM_GPIO_0 (1 << 0)
-#define EM_GPIO_1 (1 << 1)
-#define EM_GPIO_2 (1 << 2)
-#define EM_GPIO_3 (1 << 3)
-#define EM_GPIO_4 (1 << 4)
-#define EM_GPIO_5 (1 << 5)
-#define EM_GPIO_6 (1 << 6)
-#define EM_GPIO_7 (1 << 7)
-
-#define EM_GPO_0 (1 << 0)
-#define EM_GPO_1 (1 << 1)
-#define EM_GPO_2 (1 << 2)
-#define EM_GPO_3 (1 << 3)
+
+/*
+ * em28xx-reg.h - Register definitions for em28xx driver
+ */
+
+#define EM_GPIO_0 ((unsigned char)BIT(0))
+#define EM_GPIO_1 ((unsigned char)BIT(1))
+#define EM_GPIO_2 ((unsigned char)BIT(2))
+#define EM_GPIO_3 ((unsigned char)BIT(3))
+#define EM_GPIO_4 ((unsigned char)BIT(4))
+#define EM_GPIO_5 ((unsigned char)BIT(5))
+#define EM_GPIO_6 ((unsigned char)BIT(6))
+#define EM_GPIO_7 ((unsigned char)BIT(7))
+
+#define EM_GPO_0 ((unsigned char)BIT(0))
+#define EM_GPO_1 ((unsigned char)BIT(1))
+#define EM_GPO_2 ((unsigned char)BIT(2))
+#define EM_GPO_3 ((unsigned char)BIT(3))
/* em28xx endpoints */
/* 0x82: (always ?) analog */
@@ -203,10 +208,11 @@
#define EM28XX_R43_AC97BUSY 0x43
#define EM28XX_R45_IR 0x45
- /* 0x45 bit 7 - parity bit
- bits 6-0 - count
- 0x46 IR brand
- 0x47 IR data
+ /*
+ * 0x45 bit 7 - parity bit
+ * bits 6-0 - count
+ * 0x46 IR brand
+ * 0x47 IR data
*/
/* em2874 registers */
@@ -249,12 +255,12 @@
#define EM2874_IR_RC6_MODE_6A 0x0b
/* em2874 Transport Stream Enable Register (0x5f) */
-#define EM2874_TS1_CAPTURE_ENABLE (1 << 0)
-#define EM2874_TS1_FILTER_ENABLE (1 << 1)
-#define EM2874_TS1_NULL_DISCARD (1 << 2)
-#define EM2874_TS2_CAPTURE_ENABLE (1 << 4)
-#define EM2874_TS2_FILTER_ENABLE (1 << 5)
-#define EM2874_TS2_NULL_DISCARD (1 << 6)
+#define EM2874_TS1_CAPTURE_ENABLE ((unsigned char)BIT(0))
+#define EM2874_TS1_FILTER_ENABLE ((unsigned char)BIT(1))
+#define EM2874_TS1_NULL_DISCARD ((unsigned char)BIT(2))
+#define EM2874_TS2_CAPTURE_ENABLE ((unsigned char)BIT(4))
+#define EM2874_TS2_FILTER_ENABLE ((unsigned char)BIT(5))
+#define EM2874_TS2_NULL_DISCARD ((unsigned char)BIT(6))
/* register settings */
#define EM2800_AUDIO_SRC_TUNER 0x0d
diff --git a/drivers/media/usb/em28xx/em28xx-v4l.h b/drivers/media/usb/em28xx/em28xx-v4l.h
index 9c411aa..1788dbf 100644
--- a/drivers/media/usb/em28xx/em28xx-v4l.h
+++ b/drivers/media/usb/em28xx/em28xx-v4l.h
@@ -1,17 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
- video capture devices
-
- Copyright (C) 2013-2014 Mauro Carvalho Chehab <m.chehab@samsung.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ * em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+ * video capture devices
+ *
+ * Copyright (C) 2013-2014 Mauro Carvalho Chehab <m.chehab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count);
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index f512365..63c4836 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -1,25 +1,20 @@
-/*
- em28xx-vbi.c - VBI driver for em28xx
-
- Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
-
- This work was sponsored by EyeMagnet Limited.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-vbi.c - VBI driver for em28xx
+//
+// Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
+//
+// This work was sponsored by EyeMagnet Limited.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index a2ba2d9..d70ee13 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -1,30 +1,26 @@
-/*
- em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
- video capture devices
-
- Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- Markus Rechberger <mrechberger@gmail.com>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Sascha Sommer <saschasommer@freenet.de>
- Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- Some parts based on SN9C10x PC Camera Controllers GPL driver made
- by Luca Risolia <luca.risolia@studio.unibo.it>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+// video capture devices
+//
+// Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+// Markus Rechberger <mrechberger@gmail.com>
+// Mauro Carvalho Chehab <mchehab@infradead.org>
+// Sascha Sommer <saschasommer@freenet.de>
+// Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+//
+// Some parts based on SN9C10x PC Camera Controllers GPL driver made
+// by Luca Risolia <luca.risolia@studio.unibo.it>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "em28xx.h"
@@ -77,7 +73,7 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_VERSION(EM28XX_VERSION);
#define EM25XX_FRMDATAHDR_BYTE1 0x02
@@ -148,7 +144,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev)
{
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
return v4l2->sensor_xres;
if (dev->board.max_range_640_480)
@@ -161,7 +157,7 @@ static inline unsigned int norm_maxh(struct em28xx *dev)
{
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
return v4l2->sensor_yres;
if (dev->board.max_range_640_480)
@@ -176,7 +172,7 @@ static int em28xx_vbi_supported(struct em28xx *dev)
if (disable_vbi == 1)
return 0;
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
return 0;
/* FIXME: check subdevices for VBI support */
@@ -250,7 +246,8 @@ static int em28xx_set_outfmt(struct em28xx *dev)
if (em28xx_vbi_supported(dev) == 1) {
vinctrl |= EM28XX_VINCTRL_VBI_RAW;
em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
- em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, v4l2->vbi_width/4);
+ em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH,
+ v4l2->vbi_width / 4);
em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, v4l2->vbi_height);
if (v4l2->norm & V4L2_STD_525_60) {
/* NTSC */
@@ -320,8 +317,10 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
buf[0] = v;
buf[1] = v >> 8;
em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
- /* it seems that both H and V scalers must be active
- to work correctly */
+ /*
+ * it seems that both H and V scalers must be active
+ * to work correctly
+ */
mode = (h || v) ? 0x30 : 0x00;
}
return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
@@ -345,13 +344,15 @@ static int em28xx_resolution_set(struct em28xx *dev)
em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
- /* If we don't set the start position to 2 in VBI mode, we end up
- with line 20/21 being YUYV encoded instead of being in 8-bit
- greyscale. The core of the issue is that line 21 (and line 23 for
- PAL WSS) are inside of active video region, and as a result they
- get the pixelformatting associated with that area. So by cropping
- it out, we end up with the same format as the rest of the VBI
- region */
+ /*
+ * If we don't set the start position to 2 in VBI mode, we end up
+ * with line 20/21 being YUYV encoded instead of being in 8-bit
+ * greyscale. The core of the issue is that line 21 (and line 23 for
+ * PAL WSS) are inside of active video region, and as a result they
+ * get the pixelformatting associated with that area. So by cropping
+ * it out, we end up with the same format as the rest of the VBI
+ * region
+ */
if (em28xx_vbi_supported(dev) == 1)
em28xx_capture_area_set(dev, 0, 2, width, height);
else
@@ -365,14 +366,16 @@ static int em28xx_set_alternate(struct em28xx *dev)
{
struct em28xx_v4l2 *v4l2 = dev->v4l2;
struct usb_device *udev = interface_to_usbdev(dev->intf);
- int errCode;
+ int err;
int i;
unsigned int min_pkt_size = v4l2->width * 2 + 4;
- /* NOTE: for isoc transfers, only alt settings > 0 are allowed
- bulk transfers seem to work only with alt=0 ! */
+ /*
+ * NOTE: for isoc transfers, only alt settings > 0 are allowed
+ * bulk transfers seem to work only with alt=0 !
+ */
dev->alt = 0;
- if ((alt > 0) && (alt < dev->num_alt)) {
+ if (alt > 0 && alt < dev->num_alt) {
em28xx_videodbg("alternate forced to %d\n", dev->alt);
dev->alt = alt;
goto set_alt;
@@ -380,9 +383,10 @@ static int em28xx_set_alternate(struct em28xx *dev)
if (dev->analog_xfer_bulk)
goto set_alt;
- /* When image size is bigger than a certain value,
- the frame size should be increased, otherwise, only
- green screen will be received.
+ /*
+ * When image size is bigger than a certain value,
+ * the frame size should be increased, otherwise, only
+ * green screen will be received.
*/
if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
min_pkt_size *= 2;
@@ -392,18 +396,22 @@ static int em28xx_set_alternate(struct em28xx *dev)
if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
dev->alt = i;
break;
- /* otherwise make sure that we end up with the maximum bandwidth
- because the min_pkt_size equation might be wrong...
- */
+ /*
+ * otherwise make sure that we end up with the maximum
+ * bandwidth because the min_pkt_size equation might be wrong.
+ *
+ */
} else if (dev->alt_max_pkt_size_isoc[i] >
dev->alt_max_pkt_size_isoc[dev->alt])
dev->alt = i;
}
set_alt:
- /* NOTE: for bulk transfers, we need to call usb_set_interface()
+ /*
+ * NOTE: for bulk transfers, we need to call usb_set_interface()
* even if the previous settings were the same. Otherwise streaming
- * fails with all urbs having status = -EOVERFLOW ! */
+ * fails with all urbs having status = -EOVERFLOW !
+ */
if (dev->analog_xfer_bulk) {
dev->max_pkt_size = 512; /* USB 2.0 spec */
dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
@@ -416,19 +424,19 @@ set_alt:
}
em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
dev->alt, dev->max_pkt_size);
- errCode = usb_set_interface(udev, dev->ifnum, dev->alt);
- if (errCode < 0) {
+ err = usb_set_interface(udev, dev->ifnum, dev->alt);
+ if (err < 0) {
dev_err(&dev->intf->dev,
"cannot change alternate number to %d (error=%i)\n",
- dev->alt, errCode);
- return errCode;
+ dev->alt, err);
+ return err;
}
return 0;
}
-/* ------------------------------------------------------------------
- DMA and thread functions
- ------------------------------------------------------------------*/
+/*
+ * DMA and thread functions
+ */
/*
* Finish the current buffer
@@ -514,8 +522,9 @@ static void em28xx_copy_video(struct em28xx *dev,
em28xx_isocdbg("Overflow of %zu bytes past buffer end(2)\n",
((char *)startwrite + lencopy) -
((char *)buf->vb_buf + buf->length));
- lencopy = remain = (char *)buf->vb_buf + buf->length -
- (char *)startwrite;
+ remain = (char *)buf->vb_buf + buf->length -
+ (char *)startwrite;
+ lencopy = remain;
}
if (lencopy <= 0)
break;
@@ -623,11 +632,11 @@ finish_field_prepare_next(struct em28xx *dev,
struct em28xx_v4l2 *v4l2 = dev->v4l2;
if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */
- if (buf != NULL)
+ if (buf)
finish_buffer(dev, buf);
buf = get_next_buf(dev, dma_q);
}
- if (buf != NULL) {
+ if (buf) {
buf->top_field = v4l2->top_field;
buf->pos = 0;
}
@@ -648,13 +657,17 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
struct em28xx_dmaqueue *dma_q = &dev->vidq;
struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
- /* capture type 0 = vbi start
- capture type 1 = vbi in progress
- capture type 2 = video start
- capture type 3 = video in progress */
+ /*
+ * capture type 0 = vbi start
+ * capture type 1 = vbi in progress
+ * capture type 2 = video start
+ * capture type 3 = video in progress
+ */
if (data_len >= 4) {
- /* NOTE: Headers are always 4 bytes and
- * never split across packets */
+ /*
+ * NOTE: Headers are always 4 bytes and
+ * never split across packets
+ */
if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
data_pkt[2] == 0x88 && data_pkt[3] == 0x88) {
/* Continuation */
@@ -677,8 +690,10 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
data_len -= 4;
}
}
- /* NOTE: With bulk transfers, intermediate data packets
- * have no continuation header */
+ /*
+ * NOTE: With bulk transfers, intermediate data packets
+ * have no continuation header
+ */
if (v4l2->capture_type == 0) {
vbi_buf = finish_field_prepare_next(dev, vbi_buf, vbi_dma_q);
@@ -692,7 +707,7 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
(vbi_size - v4l2->vbi_read) : data_len;
/* Copy VBI data */
- if (vbi_buf != NULL)
+ if (vbi_buf)
em28xx_copy_vbi(dev, vbi_buf, data_pkt, vbi_data_len);
v4l2->vbi_read += vbi_data_len;
@@ -710,7 +725,7 @@ static inline void process_frame_data_em28xx(struct em28xx *dev,
v4l2->capture_type = 3;
}
- if (v4l2->capture_type == 3 && buf != NULL && data_len > 0)
+ if (v4l2->capture_type == 3 && buf && data_len > 0)
em28xx_copy_video(dev, buf, data_pkt, data_len);
}
@@ -727,8 +742,10 @@ static inline void process_frame_data_em25xx(struct em28xx *dev,
bool frame_end = false;
/* Check for header */
- /* NOTE: at least with bulk transfers, only the first packet
- * has a header and has always set the FRAME_END bit */
+ /*
+ * NOTE: at least with bulk transfers, only the first packet
+ * has a header and has always set the FRAME_END bit
+ */
if (data_len >= 2) { /* em25xx header is only 2 bytes long */
if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
@@ -745,14 +762,15 @@ static inline void process_frame_data_em25xx(struct em28xx *dev,
buf = finish_field_prepare_next(dev, buf, dmaq);
dev->usb_ctl.vid_buf = buf;
}
- /* NOTE: in ISOC mode when a new frame starts and buf==NULL,
+ /*
+ * NOTE: in ISOC mode when a new frame starts and buf==NULL,
* we COULD already prepare a buffer here to avoid skipping the
* first frame.
*/
}
/* Copy data */
- if (buf != NULL && data_len > 0)
+ if (buf && data_len > 0)
em28xx_copy_video(dev, buf, data_pkt, data_len);
/* Finish frame (ISOC only) => avoids lag of 1 frame */
@@ -761,14 +779,17 @@ static inline void process_frame_data_em25xx(struct em28xx *dev,
dev->usb_ctl.vid_buf = buf;
}
- /* NOTE: Tested with USB bulk transfers only !
+ /*
+ * NOTES:
+ *
+ * 1) Tested with USB bulk transfers only !
* The wording in the datasheet suggests that isoc might work different.
* The current code assumes that with isoc transfers each packet has a
* header like with the other em28xx devices.
+ *
+ * 2) Support for interlaced mode is pure theory. It has not been
+ * tested and it is unknown if these devices actually support it.
*/
- /* NOTE: Support for interlaced mode is pure theory. It has not been
- * tested and it is unknown if these devices actually support it. */
- /* NOTE: No VBI support yet (these chips likely do not support VBI). */
}
/* Processes and copies the URB data content (video and VBI data) */
@@ -829,12 +850,11 @@ static inline int em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
else
process_frame_data_em28xx(dev,
usb_data_pkt, usb_data_len);
-
}
return 1;
}
-static int get_ressource(enum v4l2_buf_type f_type)
+static int get_resource(enum v4l2_buf_type f_type)
{
switch (f_type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -842,14 +862,15 @@ static int get_ressource(enum v4l2_buf_type f_type)
case V4L2_BUF_TYPE_VBI_CAPTURE:
return EM28XX_RESOURCE_VBI;
default:
- BUG();
+ WARN_ON(1);
+ return -1; /* Indicate that device is busy */
}
}
/* Usage lock check functions */
static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
{
- int res_type = get_ressource(f_type);
+ int res_type = get_resource(f_type);
/* is it free? */
if (dev->resources & res_type) {
@@ -865,7 +886,7 @@ static int res_get(struct em28xx *dev, enum v4l2_buf_type f_type)
static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
{
- int res_type = get_ressource(f_type);
+ int res_type = get_resource(f_type);
dev->resources &= ~res_type;
em28xx_videodbg("res: put %d\n", res_type);
@@ -937,10 +958,11 @@ static int em28xx_enable_analog_tuner(struct em28xx *dev)
flags ? "enabled" : "disabled",
ret);
return ret;
- } else
- em28xx_videodbg("link %s->%s was %s\n",
- source->name, sink->name,
- flags ? "ENABLED" : "disabled");
+ }
+
+ em28xx_videodbg("link %s->%s was %s\n",
+ source->name, sink->name,
+ flags ? "ENABLED" : "disabled");
}
#endif
return 0;
@@ -976,7 +998,7 @@ static void em28xx_v4l2_create_entities(struct em28xx *dev)
}
/* Webcams don't have input connectors */
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
return;
/* Create entities for each input connector */
@@ -1016,10 +1038,9 @@ static void em28xx_v4l2_create_entities(struct em28xx *dev)
#endif
}
-
-/* ------------------------------------------------------------------
- Videobuf2 operations
- ------------------------------------------------------------------*/
+/*
+ * Videobuf2 operations
+ */
static int queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
@@ -1072,8 +1093,10 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
em28xx_videodbg("%s\n", __func__);
- /* Make sure streaming is not already in progress for this type
- of filehandle (e.g. video, vbi) */
+ /*
+ * Make sure streaming is not already in progress for this type
+ * of filehandle (e.g. video, vbi)
+ */
rc = res_get(dev, vq->type);
if (rc)
return rc;
@@ -1084,9 +1107,10 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
/* Allocate the USB bandwidth */
em28xx_set_alternate(dev);
- /* Needed, since GPIO might have disabled power of
- some i2c device
- */
+ /*
+ * Needed, since GPIO might have disabled power of
+ * some i2c device
+ */
em28xx_wake_i2c(dev);
v4l2->capture_type = -1;
@@ -1145,7 +1169,7 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
}
spin_lock_irqsave(&dev->slock, flags);
- if (dev->usb_ctl.vid_buf != NULL) {
+ if (dev->usb_ctl.vid_buf) {
vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
dev->usb_ctl.vid_buf = NULL;
@@ -1180,7 +1204,7 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
}
spin_lock_irqsave(&dev->slock, flags);
- if (dev->usb_ctl.vbi_buf != NULL) {
+ if (dev->usb_ctl.vbi_buf) {
vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
VB2_BUF_STATE_ERROR);
dev->usb_ctl.vbi_buf = NULL;
@@ -1261,7 +1285,9 @@ static int em28xx_vb2_setup(struct em28xx *dev)
return 0;
}
-/********************* v4l2 interface **************************************/
+/*
+ * v4l2 interface
+ */
static void video_mux(struct em28xx *dev, int index)
{
@@ -1277,7 +1303,7 @@ static void video_mux(struct em28xx *dev, int index)
v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
INPUT(index)->vmux, 0, 0);
- if (dev->board.has_msp34xx) {
+ if (dev->has_msp34xx) {
if (dev->i2s_speed) {
v4l2_device_call_all(v4l2_dev, 0, audio,
s_i2s_clock_freq, dev->i2s_speed);
@@ -1394,9 +1420,9 @@ static void scale_to_size(struct em28xx *dev,
*height = 1;
}
-/* ------------------------------------------------------------------
- IOCTL vidioc handling
- ------------------------------------------------------------------*/
+/*
+ * IOCTL vidioc handling
+ */
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
@@ -1462,8 +1488,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
if (width == maxw && height == maxh)
width /= 2;
} else {
- /* width must even because of the YUYV format
- height must be even because of interlacing */
+ /*
+ * width must even because of the YUYV format
+ * height must be even because of interlacing
+ */
v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1, 0);
}
@@ -1493,7 +1521,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
}
static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
- unsigned width, unsigned height)
+ unsigned int width, unsigned int height)
{
struct em28xx_fmt *fmt;
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1582,17 +1610,26 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
static int vidioc_g_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{
+ struct v4l2_subdev_frame_interval ival = { 0 };
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
int rc = 0;
+ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ return -EINVAL;
+
p->parm.capture.readbuffers = EM28XX_MIN_BUF;
- if (dev->board.is_webcam)
+ p->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ if (dev->is_webcam) {
rc = v4l2_device_call_until_err(&v4l2->v4l2_dev, 0,
- video, g_parm, p);
- else
+ video, g_frame_interval, &ival);
+ if (!rc)
+ p->parm.capture.timeperframe = ival.interval;
+ } else {
v4l2_video_std_frame_period(v4l2->norm,
&p->parm.capture.timeperframe);
+ }
return rc;
}
@@ -1601,10 +1638,27 @@ static int vidioc_s_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{
struct em28xx *dev = video_drvdata(file);
+ struct v4l2_subdev_frame_interval ival = {
+ 0,
+ p->parm.capture.timeperframe
+ };
+ int rc = 0;
+
+ if (!dev->is_webcam)
+ return -ENOTTY;
+
+ if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ return -EINVAL;
+ memset(&p->parm, 0, sizeof(p->parm));
p->parm.capture.readbuffers = EM28XX_MIN_BUF;
- return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev,
- 0, video, s_parm, p);
+ p->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+ rc = v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, 0,
+ video, s_frame_interval, &ival);
+ if (!rc)
+ p->parm.capture.timeperframe = ival.interval;
+ return rc;
}
static int vidioc_enum_input(struct file *file, void *priv,
@@ -1616,20 +1670,19 @@ static int vidioc_enum_input(struct file *file, void *priv,
n = i->index;
if (n >= MAX_EM28XX_INPUT)
return -EINVAL;
- if (0 == INPUT(n)->type)
+ if (!INPUT(n)->type)
return -EINVAL;
- i->index = n;
i->type = V4L2_INPUT_TYPE_CAMERA;
strcpy(i->name, iname[INPUT(n)->type]);
- if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type))
+ if (INPUT(n)->type == EM28XX_VMUX_TELEVISION)
i->type = V4L2_INPUT_TYPE_TUNER;
i->std = dev->v4l2->vdev.tvnorms;
/* webcams do not have the STD API */
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
i->capabilities = 0;
return 0;
@@ -1650,7 +1703,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
if (i >= MAX_EM28XX_INPUT)
return -EINVAL;
- if (0 == INPUT(i)->type)
+ if (!INPUT(i)->type)
return -EINVAL;
video_mux(dev, i);
@@ -1696,13 +1749,14 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
return 0;
}
-static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *priv,
+ const struct v4l2_audio *a)
{
struct em28xx *dev = video_drvdata(file);
if (a->index >= MAX_EM28XX_INPUT)
return -EINVAL;
- if (0 == INPUT(a->index)->type)
+ if (!INPUT(a->index)->type)
return -EINVAL;
dev->ctl_ainput = INPUT(a->index)->amux;
@@ -1719,7 +1773,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
{
struct em28xx *dev = video_drvdata(file);
- if (0 != t->index)
+ if (t->index != 0)
return -EINVAL;
strcpy(t->name, "Tuner");
@@ -1733,7 +1787,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
{
struct em28xx *dev = video_drvdata(file);
- if (0 != t->index)
+ if (t->index != 0)
return -EINVAL;
v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
@@ -1746,7 +1800,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- if (0 != f->tuner)
+ if (f->tuner != 0)
return -EINVAL;
f->frequency = v4l2->frequency;
@@ -1760,7 +1814,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- if (0 != f->tuner)
+ if (f->tuner != 0)
return -EINVAL;
v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, f);
@@ -1884,8 +1938,9 @@ static int vidioc_querycap(struct file *file, void *priv,
if (dev->tuner_type != TUNER_ABSENT)
cap->device_caps |= V4L2_CAP_TUNER;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
- V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+ cap->capabilities = cap->device_caps |
+ V4L2_CAP_DEVICE_CAPS | V4L2_CAP_READWRITE |
+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
if (video_is_registered(&v4l2->vbi_dev))
cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
if (video_is_registered(&v4l2->radio_dev))
@@ -1978,9 +2033,9 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
return 0;
}
-/* ----------------------------------------------------------- */
-/* RADIO ESPECIFIC IOCTLS */
-/* ----------------------------------------------------------- */
+/*
+ * RADIO ESPECIFIC IOCTLS
+ */
static int radio_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
@@ -2002,7 +2057,7 @@ static int radio_s_tuner(struct file *file, void *priv,
{
struct em28xx *dev = video_drvdata(file);
- if (0 != t->index)
+ if (t->index != 0)
return -EINVAL;
v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, s_tuner, t);
@@ -2097,7 +2152,7 @@ static int em28xx_v4l2_open(struct file *filp)
* em28xx_v4l2_fini()
* unregisters the v4l2,i2c and usb devices
* called when the device gets disconected or at module unload
-*/
+ */
static int em28xx_v4l2_fini(struct em28xx *dev)
{
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -2112,7 +2167,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
return 0;
}
- if (v4l2 == NULL)
+ if (!v4l2)
return 0;
dev_info(&dev->intf->dev, "Closing video extension\n");
@@ -2127,17 +2182,17 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
if (video_is_registered(&v4l2->radio_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
- video_device_node_name(&v4l2->radio_dev));
+ video_device_node_name(&v4l2->radio_dev));
video_unregister_device(&v4l2->radio_dev);
}
if (video_is_registered(&v4l2->vbi_dev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
- video_device_node_name(&v4l2->vbi_dev));
+ video_device_node_name(&v4l2->vbi_dev));
video_unregister_device(&v4l2->vbi_dev);
}
if (video_is_registered(&v4l2->vdev)) {
dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
- video_device_node_name(&v4l2->vdev));
+ video_device_node_name(&v4l2->vdev));
video_unregister_device(&v4l2->vdev);
}
@@ -2189,7 +2244,7 @@ static int em28xx_v4l2_close(struct file *filp)
struct em28xx *dev = video_drvdata(filp);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
struct usb_device *udev = interface_to_usbdev(dev->intf);
- int errCode;
+ int err;
em28xx_videodbg("users=%d\n", v4l2->users);
@@ -2202,7 +2257,7 @@ static int em28xx_v4l2_close(struct file *filp)
goto exit;
/* Save some power by putting tuner to sleep */
- v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
+ v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, standby);
/* do this before setting alternate! */
em28xx_set_mode(dev, EM28XX_SUSPEND);
@@ -2210,11 +2265,11 @@ static int em28xx_v4l2_close(struct file *filp)
/* set alternate 0 */
dev->alt = 0;
em28xx_videodbg("setting alternate 0\n");
- errCode = usb_set_interface(udev, 0, 0);
- if (errCode < 0) {
+ err = usb_set_interface(udev, 0, 0);
+ if (err < 0) {
dev_err(&dev->intf->dev,
"cannot change alternate number to 0 (error=%i)\n",
- errCode);
+ err);
}
}
@@ -2343,7 +2398,7 @@ static void em28xx_vdev_init(struct em28xx *dev,
*vfd = *template;
vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
vfd->lock = &dev->lock;
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
vfd->tvnorms = 0;
snprintf(vfd->name, sizeof(vfd->name), "%s %s",
@@ -2372,7 +2427,7 @@ static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
0, tuner, s_type_addr, &tun_setup);
}
- if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
+ if (dev->tuner_type != TUNER_ABSENT && dev->tuner_type) {
tun_setup.type = dev->tuner_type;
tun_setup.addr = tuner_addr;
@@ -2435,7 +2490,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
mutex_lock(&dev->lock);
- v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
+ v4l2 = kzalloc(sizeof(*v4l2), GFP_KERNEL);
if (!v4l2) {
mutex_unlock(&dev->lock);
return -ENOMEM;
@@ -2458,7 +2513,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
v4l2_ctrl_handler_init(hdl, 8);
v4l2->v4l2_dev.ctrl_handler = hdl;
- if (dev->board.is_webcam)
+ if (dev->is_webcam)
v4l2->progressive = true;
/*
@@ -2470,7 +2525,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
/* request some modules */
- if (dev->board.has_msp34xx)
+ if (dev->has_msp34xx)
v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
&dev->i2c_adap[dev->def_i2c_bus],
"msp3400", 0, msp3400_addrs);
@@ -2559,7 +2614,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
INIT_LIST_HEAD(&dev->vidq.active);
INIT_LIST_HEAD(&dev->vbiq.active);
- if (dev->board.has_msp34xx) {
+ if (dev->has_msp34xx) {
/* Send a reset to other chips via gpio */
ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
if (ret < 0) {
@@ -2568,7 +2623,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
__func__, ret);
goto unregister_dev;
}
- msleep(3);
+ usleep_range(10000, 11000);
ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
if (ret < 0) {
@@ -2577,7 +2632,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
__func__, ret);
goto unregister_dev;
}
- msleep(3);
+ usleep_range(10000, 11000);
}
/* set default norm */
@@ -2589,8 +2644,10 @@ static int em28xx_v4l2_init(struct em28xx *dev)
v4l2->format = &format[0];
maxw = norm_maxw(dev);
- /* MaxPacketSize for em2800 is too small to capture at full resolution
- * use half of maxw as the scaler can only scale to 50% */
+ /*
+ * MaxPacketSize for em2800 is too small to capture at full resolution
+ * use half of maxw as the scaler can only scale to 50%
+ */
if (dev->board.is_em2800)
maxw /= 2;
@@ -2611,29 +2668,33 @@ static int em28xx_v4l2_init(struct em28xx *dev)
em28xx_set_outfmt(dev);
/* Add image controls */
- /* NOTE: at this point, the subdevices are already registered, so bridge
- * controls are only added/enabled when no subdevice provides them */
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
+
+ /*
+ * NOTE: at this point, the subdevices are already registered, so
+ * bridge controls are only added/enabled when no subdevice provides
+ * them
+ */
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_CONTRAST))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_CONTRAST,
0, 0x1f, 1, CONTRAST_DEFAULT);
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_BRIGHTNESS))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_BRIGHTNESS,
-0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_SATURATION))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_SATURATION,
0, 0x1f, 1, SATURATION_DEFAULT);
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_BLUE_BALANCE))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_BLUE_BALANCE,
-0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_RED_BALANCE))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_RED_BALANCE,
-0x30, 0x30, 1, RED_BALANCE_DEFAULT);
- if (NULL == v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
+ if (!v4l2_ctrl_find(hdl, V4L2_CID_SHARPNESS))
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
V4L2_CID_SHARPNESS,
0, 0x0f, 1, SHARPNESS_DEFAULT);
@@ -2653,7 +2714,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
v4l2->vdev.queue->lock = &v4l2->vb_queue_lock;
/* disable inapplicable ioctls */
- if (dev->board.is_webcam) {
+ if (dev->is_webcam) {
v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_QUERYSTD);
v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_STD);
v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_STD);
@@ -2683,7 +2744,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
/* Allocate and fill vbi video_device struct */
if (em28xx_vbi_supported(dev) == 1) {
em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template,
- "vbi");
+ "vbi");
v4l2->vbi_dev.queue = &v4l2->vb_vbiq;
v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock;
@@ -2713,7 +2774,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
em28xx_vdev_init(dev, &v4l2->radio_dev, &em28xx_radio_template,
- "radio");
+ "radio");
ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
radio_nr[dev->devno]);
if (ret < 0) {
@@ -2749,7 +2810,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
video_device_node_name(&v4l2->vbi_dev));
/* Save some power by putting tuner to sleep */
- v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
+ v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, standby);
/* initialize videobuf2 stuff */
em28xx_vb2_setup(dev);
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 88084f2..63c7c61 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -1,31 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
/*
- em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
- Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
- Ludovico Cavedon <cavedon@sssup.it>
- Mauro Carvalho Chehab <mchehab@infradead.org>
- Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
-
- Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
+ *
+ * Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
+ * Ludovico Cavedon <cavedon@sssup.it>
+ * Mauro Carvalho Chehab <mchehab@infradead.org>
+ * Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com>
+ *
+ * Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
#ifndef _EM28XX_H
#define _EM28XX_H
+#include <linux/bitfield.h>
+
#define EM28XX_VERSION "0.2.2"
#define DRIVER_DESC "Empia em28xx device driver"
@@ -166,7 +165,7 @@
#define EM28XX_STOP_AUDIO 0
/* maximum number of em28xx boards */
-#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
+#define EM28XX_MAXBOARDS DVB_MAX_ADAPTERS /* All adapters could be em28xx */
/* maximum number of frames that can be queued */
#define EM28XX_NUM_FRAMES 5
@@ -180,43 +179,32 @@
/* max number of I2C buses on em28xx devices */
#define NUM_I2C_BUSES 2
-/* isoc transfers: number of packets for each buffer
- windows requests only 64 packets .. so we better do the same
- this is what I found out for all alternate numbers there!
+/*
+ * isoc transfers: number of packets for each buffer
+ * windows requests only 64 packets .. so we better do the same
+ * this is what I found out for all alternate numbers there!
*/
#define EM28XX_NUM_ISOC_PACKETS 64
#define EM28XX_DVB_NUM_ISOC_PACKETS 64
-/* bulk transfers: transfer buffer size = packet size * packet multiplier
- USB 2.0 spec says bulk packet size is always 512 bytes
+/*
+ * bulk transfers: transfer buffer size = packet size * packet multiplier
+ * USB 2.0 spec says bulk packet size is always 512 bytes
*/
#define EM28XX_BULK_PACKET_MULTIPLIER 384
-#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 384
+#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 94
#define EM28XX_INTERLACED_DEFAULT 1
-/*
- * Time in msecs to wait for i2c xfers to finish.
- * 35ms is the maximum time a SMBUS device could wait when
- * clock stretching is used. As the transfer itself will take
- * some time to happen, set it to 35 ms.
- *
- * Ok, I2C doesn't specify any limit. So, eventually, we may need
- * to increase this timeout.
- *
- * FIXME: this assumes that an I2C message is not longer than 1ms.
- * This is actually dependent on the I2C bus speed, although most
- * devices use a 100kHz clock. So, this assumtion is true most of
- * the time.
- */
-#define EM28XX_I2C_XFER_TIMEOUT 36
-
/* time in msecs to wait for AC97 xfers to finish */
#define EM28XX_AC97_XFER_TIMEOUT 100
/* max. number of button state polling addresses */
#define EM28XX_NUM_BUTTON_ADDRESSES_MAX 5
+#define PRIMARY_TS 0
+#define SECONDARY_TS 1
+
enum em28xx_mode {
EM28XX_SUSPEND,
EM28XX_ANALOG_MODE,
@@ -225,64 +213,83 @@ enum em28xx_mode {
struct em28xx;
+/**
+ * struct em28xx_usb_bufs - Contains URB-related buffer data
+ *
+ * @max_pkt_size: max packet size of isoc transaction
+ * @num_packets: number of packets in each buffer
+ * @num_bufs: number of allocated urb
+ * @urb: urb for isoc/bulk transfers
+ * @buf: transfer buffers for isoc/bulk transfer
+ */
struct em28xx_usb_bufs {
- /* max packet size of isoc transaction */
int max_pkt_size;
-
- /* number of packets in each buffer */
int num_packets;
-
- /* number of allocated urbs */
int num_bufs;
-
- /* urb for isoc/bulk transfers */
struct urb **urb;
-
- /* transfer buffers for isoc/bulk transfer */
- char **transfer_buffer;
+ char **buf;
};
+/**
+ * struct em28xx_usb_ctl - Contains URB-related buffer data
+ *
+ * @analog_bufs: isoc/bulk transfer buffers for analog mode
+ * @digital_bufs: isoc/bulk transfer buffers for digital mode
+ * @vid_buf: Stores already requested video buffers
+ * @vbi_buf: Stores already requested VBI buffers
+ * @urb_data_copy: copy data from URB
+ */
struct em28xx_usb_ctl {
- /* isoc/bulk transfer buffers for analog mode */
struct em28xx_usb_bufs analog_bufs;
-
- /* isoc/bulk transfer buffers for digital mode */
struct em28xx_usb_bufs digital_bufs;
-
- /* Stores already requested buffers */
struct em28xx_buffer *vid_buf;
struct em28xx_buffer *vbi_buf;
-
- /* copy data from URB */
int (*urb_data_copy)(struct em28xx *dev, struct urb *urb);
-
};
-/* Struct to enumberate video formats */
+/**
+ * struct em28xx_fmt - Struct to enumberate video formats
+ *
+ * @name: Name for the video standard
+ * @fourcc: v4l2 format id
+ * @depth: mean number of bits to represent a pixel
+ * @reg: em28xx register value to set it
+ */
struct em28xx_fmt {
- char *name;
- u32 fourcc; /* v4l2 format id */
- int depth;
- int reg;
+ char *name;
+ u32 fourcc;
+ int depth;
+ int reg;
};
-/* buffer for one video frame */
+/**
+ * struct em28xx_buffer- buffer for storing one video frame
+ *
+ * @vb: common v4l buffer stuff
+ * @list: List to associate it with the other buffers
+ * @mem: pointer to the buffer, as returned by vb2_plane_vaddr()
+ * @length: length of the buffer, as returned by vb2_plane_size()
+ * @top_field: If non-zero, indicate that the buffer is the top field
+ * @pos: Indicate the next position of the buffer to be filled.
+ * @vb_buf: pointer to vmalloc memory address in vb
+ *
+ * .. note::
+ *
+ * in interlaced mode, @pos is reset to zero at the start of each new
+ * field (not frame !)
+ */
struct em28xx_buffer {
- /* common v4l buffer stuff -- must be first */
- struct vb2_v4l2_buffer vb;
- struct list_head list;
+ struct vb2_v4l2_buffer vb; /* must be first */
- void *mem;
- unsigned int length;
- int top_field;
+ struct list_head list;
- /* counter to control buffer fill */
- unsigned int pos;
- /* NOTE; in interlaced mode, this value is reset to zero at
- * the start of each new field (not frame !) */
+ void *mem;
+ unsigned int length;
+ int top_field;
- /* pointer to vmalloc memory address in vb */
- char *vb_buf;
+ unsigned int pos;
+
+ char *vb_buf;
};
struct em28xx_dmaqueue {
@@ -324,20 +331,48 @@ enum em28xx_usb_audio_type {
EM28XX_USB_AUDIO_VENDOR,
};
-/* em28xx has two audio inputs: tuner and line in.
- However, on most devices, an auxiliary AC97 codec device is used.
- The AC97 device may have several different inputs and outputs,
- depending on their model. So, it is possible to use AC97 mixer to
- address more than two different entries.
+/**
+ * em28xx_amux - describes the type of audio input used by em28xx
+ *
+ * @EM28XX_AMUX_VIDEO:
+ * On devices without AC97, this is the only value that it is currently
+ * allowed.
+ * On devices with AC97, it corresponds to the AC97 mixer "Video" control.
+ * @EM28XX_AMUX_LINE_IN:
+ * Only for devices with AC97. Corresponds to AC97 mixer "Line In".
+ * @EM28XX_AMUX_VIDEO2:
+ * Only for devices with AC97. It means that em28xx should use "Line In"
+ * And AC97 should use the "Video" mixer control.
+ * @EM28XX_AMUX_PHONE:
+ * Only for devices with AC97. Corresponds to AC97 mixer "Phone".
+ * @EM28XX_AMUX_MIC:
+ * Only for devices with AC97. Corresponds to AC97 mixer "Mic".
+ * @EM28XX_AMUX_CD:
+ * Only for devices with AC97. Corresponds to AC97 mixer "CD".
+ * @EM28XX_AMUX_AUX:
+ * Only for devices with AC97. Corresponds to AC97 mixer "Aux".
+ * @EM28XX_AMUX_PCM_OUT:
+ * Only for devices with AC97. Corresponds to AC97 mixer "PCM out".
+ *
+ * The em28xx chip itself has only two audio inputs: tuner and line in.
+ * On almost all devices, only the tuner input is used.
+ *
+ * However, on most devices, an auxiliary AC97 codec device is used,
+ * usually connected to the em28xx tuner input (except for
+ * @EM28XX_AMUX_LINE_IN).
+ *
+ * The AC97 device typically have several different inputs and outputs.
+ * The exact number and description depends on their model.
+ *
+ * It is possible to AC97 to mixer more than one different entries at the
+ * same time, via the alsa mux.
*/
enum em28xx_amux {
- /* This is the only entry for em28xx tuner input */
- EM28XX_AMUX_VIDEO, /* em28xx tuner, AC97 mixer Video */
-
- EM28XX_AMUX_LINE_IN, /* AC97 mixer Line In */
+ EM28XX_AMUX_VIDEO,
+ EM28XX_AMUX_LINE_IN,
/* Some less-common mixer setups */
- EM28XX_AMUX_VIDEO2, /* em28xx Line in, AC97 mixer Video */
+ EM28XX_AMUX_VIDEO2,
EM28XX_AMUX_PHONE,
EM28XX_AMUX_MIC,
EM28XX_AMUX_CD,
@@ -347,14 +382,14 @@ enum em28xx_amux {
enum em28xx_aout {
/* AC97 outputs */
- EM28XX_AOUT_MASTER = 1 << 0,
- EM28XX_AOUT_LINE = 1 << 1,
- EM28XX_AOUT_MONO = 1 << 2,
- EM28XX_AOUT_LFE = 1 << 3,
- EM28XX_AOUT_SURR = 1 << 4,
+ EM28XX_AOUT_MASTER = BIT(0),
+ EM28XX_AOUT_LINE = BIT(1),
+ EM28XX_AOUT_MONO = BIT(2),
+ EM28XX_AOUT_LFE = BIT(3),
+ EM28XX_AOUT_SURR = BIT(4),
/* PCM IN Mixer - used by AC97_RECORD_SELECT register */
- EM28XX_AOUT_PCM_IN = 1 << 7,
+ EM28XX_AOUT_PCM_IN = BIT(7),
/* Bits 10-8 are used to indicate the PCM IN record select */
EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
@@ -383,7 +418,7 @@ struct em28xx_input {
unsigned int vmux;
enum em28xx_amux amux;
enum em28xx_aout aout;
- struct em28xx_reg_seq *gpio;
+ const struct em28xx_reg_seq *gpio;
};
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
@@ -441,22 +476,23 @@ struct em28xx_board {
int vchannels;
int tuner_type;
int tuner_addr;
- unsigned def_i2c_bus; /* Default I2C bus */
+ unsigned int def_i2c_bus; /* Default I2C bus */
/* i2c flags */
unsigned int tda9887_conf;
/* GPIO sequences */
- struct em28xx_reg_seq *dvb_gpio;
- struct em28xx_reg_seq *suspend_gpio;
- struct em28xx_reg_seq *tuner_gpio;
- struct em28xx_reg_seq *mute_gpio;
+ const struct em28xx_reg_seq *dvb_gpio;
+ const struct em28xx_reg_seq *suspend_gpio;
+ const struct em28xx_reg_seq *tuner_gpio;
+ const struct em28xx_reg_seq *mute_gpio;
unsigned int is_em2800:1;
unsigned int has_msp34xx:1;
unsigned int mts_firmware:1;
unsigned int max_range_640_480:1;
unsigned int has_dvb:1;
+ unsigned int has_dual_ts:1;
unsigned int is_webcam:1;
unsigned int valid:1;
unsigned int has_ir_i2c:1;
@@ -476,7 +512,7 @@ struct em28xx_board {
struct em28xx_led *leds;
/* Buttons */
- struct em28xx_button *buttons;
+ const struct em28xx_button *buttons;
};
struct em28xx_eeprom {
@@ -519,8 +555,8 @@ struct em28xx_v4l2 {
/* Videobuf2 */
struct vb2_queue vb_vidq;
struct vb2_queue vb_vbiq;
- struct mutex vb_queue_lock;
- struct mutex vb_vbi_queue_lock;
+ struct mutex vb_queue_lock; /* Protects vb_vidq */
+ struct mutex vb_vbi_queue_lock; /* Protects vb_vbiq */
u8 vinmode;
u8 vinctl;
@@ -546,8 +582,8 @@ struct em28xx_v4l2 {
/* Frame properties */
int width; /* current frame width */
int height; /* current frame height */
- unsigned hscale; /* horizontal scale factor (see datasheet) */
- unsigned vscale; /* vertical scale factor (see datasheet) */
+ unsigned int hscale; /* horizontal scale factor (see datasheet) */
+ unsigned int vscale; /* vertical scale factor (see datasheet) */
unsigned int vbi_width;
unsigned int vbi_height; /* lines per field */
@@ -565,7 +601,7 @@ struct em28xx_v4l2 {
struct em28xx_audio {
char name[50];
- unsigned num_urb;
+ unsigned int num_urb;
char **transfer_buffer;
struct urb **urb;
struct usb_device *udev;
@@ -578,7 +614,7 @@ struct em28xx_audio {
size_t period;
int users;
- spinlock_t slock;
+ spinlock_t slock; /* Protects struct em28xx_audio */
/* Controls streaming */
struct work_struct wq_trigger; /* trigger to start/stop audio */
@@ -596,7 +632,7 @@ enum em28xx_i2c_algo_type {
struct em28xx_i2c_bus {
struct em28xx *dev;
- unsigned bus;
+ unsigned int bus;
enum em28xx_i2c_algo_type algo_type;
};
@@ -604,102 +640,111 @@ struct em28xx_i2c_bus {
struct em28xx {
struct kref ref;
- /* Sub-module data */
+ // Sub-module data
struct em28xx_v4l2 *v4l2;
struct em28xx_dvb *dvb;
struct em28xx_audio adev;
struct em28xx_IR *ir;
- /* generic device properties */
- int model; /* index in the device_data struct */
- int devno; /* marks the number of this device */
+ // generic device properties
+ int model; // index in the device_data struct
+ int devno; // marks the number of this device
enum em28xx_chip_id chip_id;
- unsigned int is_em25xx:1; /* em25xx/em276x/7x/8x family bridge */
- unsigned char disconnected:1; /* device has been diconnected */
+ unsigned int is_em25xx:1; // em25xx/em276x/7x/8x family bridge
+ unsigned int disconnected:1; // device has been diconnected
unsigned int has_video:1;
unsigned int is_audio_only:1;
+ unsigned int is_webcam:1;
+ unsigned int has_msp34xx:1;
+ unsigned int i2c_speed:2;
enum em28xx_int_audio_type int_audio_type;
enum em28xx_usb_audio_type usb_audio_type;
+ unsigned char name[32];
struct em28xx_board board;
- enum em28xx_sensor em28xx_sensor; /* camera specific */
+ enum em28xx_sensor em28xx_sensor; // camera specific
- /* Some older em28xx chips needs a waiting time after writing */
+ // Some older em28xx chips needs a waiting time after writing
unsigned int wait_after_write;
struct list_head devlist;
- u32 i2s_speed; /* I2S speed for audio digital stream */
+ u32 i2s_speed; // I2S speed for audio digital stream
struct em28xx_audio_mode audio_mode;
- int tuner_type; /* type of the tuner */
+ int tuner_type; // type of the tuner
- /* i2c i/o */
+ // i2c i/o
struct i2c_adapter i2c_adap[NUM_I2C_BUSES];
struct i2c_client i2c_client[NUM_I2C_BUSES];
struct em28xx_i2c_bus i2c_bus[NUM_I2C_BUSES];
unsigned char eeprom_addrwidth_16bit:1;
- unsigned def_i2c_bus; /* Default I2C bus */
- unsigned cur_i2c_bus; /* Current I2C bus */
+ unsigned int def_i2c_bus; // Default I2C bus
+ unsigned int cur_i2c_bus; // Current I2C bus
struct rt_mutex i2c_bus_lock;
- /* video for linux */
- unsigned int ctl_input; /* selected input */
- unsigned int ctl_ainput;/* selected audio input */
- unsigned int ctl_aoutput;/* selected audio output */
+ // video for linux
+ unsigned int ctl_input; // selected input
+ unsigned int ctl_ainput;// selected audio input
+ unsigned int ctl_aoutput;// selected audio output
int mute;
int volume;
- unsigned long hash; /* eeprom hash - for boards with generic ID */
- unsigned long i2c_hash; /* i2c devicelist hash -
- for boards with generic ID */
+ unsigned long hash; // eeprom hash - for boards with generic ID
+ unsigned long i2c_hash; // i2c devicelist hash -
+ // for boards with generic ID
struct work_struct request_module_wk;
- /* locks */
- struct mutex lock;
+ // locks
+ struct mutex lock; /* protects em28xx struct */
struct mutex ctrl_urb_lock; /* protects urb_buf */
- /* resources in use */
+ // resources in use
unsigned int resources;
- /* eeprom content */
+ // eeprom content
u8 *eedata;
u16 eedata_len;
- /* Isoc control struct */
+ // Isoc control struct
struct em28xx_dmaqueue vidq;
struct em28xx_dmaqueue vbiq;
struct em28xx_usb_ctl usb_ctl;
- spinlock_t slock;
-
- /* usb transfer */
- struct usb_interface *intf; /* the usb interface */
- u8 ifnum; /* number of the assigned usb interface */
- u8 analog_ep_isoc; /* address of isoc endpoint for analog */
- u8 analog_ep_bulk; /* address of bulk endpoint for analog */
- u8 dvb_ep_isoc; /* address of isoc endpoint for DVB */
- u8 dvb_ep_bulk; /* address of bulk endpoint for DVB */
- int alt; /* alternate setting */
- int max_pkt_size; /* max packet size of the selected ep at alt */
- int packet_multiplier; /* multiplier for wMaxPacketSize, used for
- URB buffer size definition */
- int num_alt; /* number of alternative settings */
- unsigned int *alt_max_pkt_size_isoc; /* array of isoc wMaxPacketSize */
- unsigned int analog_xfer_bulk:1; /* use bulk instead of isoc
- transfers for analog */
- int dvb_alt_isoc; /* alternate setting for DVB isoc transfers */
- unsigned int dvb_max_pkt_size_isoc; /* isoc max packet size of the
- selected DVB ep at dvb_alt */
- unsigned int dvb_xfer_bulk:1; /* use bulk instead of isoc
- transfers for DVB */
- char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
-
- /* helper funcs that call usb_control_msg */
+
+ spinlock_t slock; /* Protects em28xx video/vbi/dvb IRQ stream data */
+
+ // usb transfer
+ struct usb_interface *intf; // the usb interface
+ u8 ifnum; // number of the assigned usb interface
+ u8 analog_ep_isoc; // address of isoc endpoint for analog
+ u8 analog_ep_bulk; // address of bulk endpoint for analog
+ u8 dvb_ep_isoc_ts2; // address of isoc endpoint for DVB TS2
+ u8 dvb_ep_bulk_ts2; // address of bulk endpoint for DVB TS2
+ u8 dvb_ep_isoc; // address of isoc endpoint for DVB
+ u8 dvb_ep_bulk; // address of bulk endpoint for DVB
+ int alt; // alternate setting
+ int max_pkt_size; // max packet size of the selected ep at alt
+ int packet_multiplier; // multiplier for wMaxPacketSize, used for
+ // URB buffer size definition
+ int num_alt; // number of alternative settings
+ unsigned int *alt_max_pkt_size_isoc; // array of isoc wMaxPacketSize
+ unsigned int analog_xfer_bulk:1; // use bulk instead of isoc
+ // transfers for analog
+ int dvb_alt_isoc; // alternate setting for DVB isoc transfers
+ unsigned int dvb_max_pkt_size_isoc; // isoc max packet size of the
+ // selected DVB ep at dvb_alt
+ unsigned int dvb_max_pkt_size_isoc_ts2; // isoc max packet size of the
+ // selected DVB ep at dvb_alt
+ unsigned int dvb_xfer_bulk:1; // use bulk instead of isoc
+ // transfers for DVB
+ char urb_buf[URB_MAX_CTRL_SIZE]; // urb control msg buffer
+
+ // helper funcs that call usb_control_msg
int (*em28xx_write_regs)(struct em28xx *dev, u16 reg,
char *buf, int len);
int (*em28xx_read_reg)(struct em28xx *dev, u16 reg);
@@ -711,14 +756,14 @@ struct em28xx {
enum em28xx_mode mode;
- /* Button state polling */
+ // Button state polling
struct delayed_work buttons_query_work;
u8 button_polling_addresses[EM28XX_NUM_BUTTON_ADDRESSES_MAX];
u8 button_polling_last_values[EM28XX_NUM_BUTTON_ADDRESSES_MAX];
u8 num_button_polling_addresses;
- u16 button_polling_interval; /* [ms] */
- /* Snapshot button input device */
- char snapshot_button_path[30]; /* path of the input dev */
+ u16 button_polling_interval; // [ms]
+ // Snapshot button input device
+ char snapshot_button_path[30]; // path of the input dev
struct input_dev *sbutton_input_dev;
#ifdef CONFIG_MEDIA_CONTROLLER
@@ -726,6 +771,9 @@ struct em28xx {
struct media_entity input_ent[MAX_EM28XX_INPUT];
struct media_pad input_pad[MAX_EM28XX_INPUT];
#endif
+
+ struct em28xx *dev_next;
+ int ts;
};
#define kref_to_dev(d) container_of(d, struct em28xx, ref)
@@ -734,17 +782,17 @@ struct em28xx_ops {
struct list_head next;
char *name;
int id;
- int (*init)(struct em28xx *);
- int (*fini)(struct em28xx *);
- int (*suspend)(struct em28xx *);
- int (*resume)(struct em28xx *);
+ int (*init)(struct em28xx *dev);
+ int (*fini)(struct em28xx *dev);
+ int (*suspend)(struct em28xx *dev);
+ int (*resume)(struct em28xx *dev);
};
/* Provided by em28xx-i2c.c */
-void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus);
-int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
+void em28xx_do_i2c_scan(struct em28xx *dev, unsigned int bus);
+int em28xx_i2c_register(struct em28xx *dev, unsigned int bus,
enum em28xx_i2c_algo_type algo_type);
-int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus);
+int em28xx_i2c_unregister(struct em28xx *dev, unsigned int bus);
/* Provided by em28xx-core.c */
int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
@@ -778,7 +826,7 @@ int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
void em28xx_uninit_usb_xfer(struct em28xx *dev, enum em28xx_mode mode);
void em28xx_stop_urbs(struct em28xx *dev);
int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
-int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
+int em28xx_gpio_set(struct em28xx *dev, const struct em28xx_reg_seq *gpio);
int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev);
void em28xx_init_extension(struct em28xx *dev);
@@ -787,7 +835,7 @@ int em28xx_suspend_extension(struct em28xx *dev);
int em28xx_resume_extension(struct em28xx *dev);
/* Provided by em28xx-cards.c */
-extern struct em28xx_board em28xx_boards[];
+extern const struct em28xx_board em28xx_boards[];
extern struct usb_device_id em28xx_id_table[];
int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl);
OpenPOWER on IntegriCloud