summaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/Kconfig14
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/dsbr100.c41
-rw-r--r--drivers/media/radio/radio-aimslab.c34
-rw-r--r--drivers/media/radio/radio-aztech.c40
-rw-r--r--drivers/media/radio/radio-cadet.c1
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c42
-rw-r--r--drivers/media/radio/radio-gemtek.c37
-rw-r--r--drivers/media/radio/radio-maestro.c34
-rw-r--r--drivers/media/radio/radio-maxiradio.c40
-rw-r--r--drivers/media/radio/radio-mr800.c628
-rw-r--r--drivers/media/radio/radio-rtrack2.c34
-rw-r--r--drivers/media/radio/radio-sf16fmi.c34
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c34
-rw-r--r--drivers/media/radio/radio-si470x.c258
-rw-r--r--drivers/media/radio/radio-terratec.c34
-rw-r--r--drivers/media/radio/radio-trust.c17
-rw-r--r--drivers/media/radio/radio-typhoon.c35
-rw-r--r--drivers/media/radio/radio-zoltrix.c51
19 files changed, 1071 insertions, 338 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 1b41b3f77cf9..04cd7c04bdde 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -359,6 +359,18 @@ config USB_SI470X
computer's USB port.
To compile this driver as a module, choose M here: the
- module will be called radio-silabs.
+ module will be called radio-si470x.
+
+config USB_MR800
+ tristate "AverMedia MR 800 USB FM radio support"
+ depends on USB && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to connect this type of radio to your
+ computer's USB port. Note that the audio is not digital, and
+ you must connect the line out connector to a sound card or a
+ set of speakers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-mr800.
endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 7ca71ab96b43..240ec63cdafc 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -18,5 +18,6 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_SI470X) += radio-si470x.o
+obj-$(CONFIG_USB_MR800) += radio-mr800.o
EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 70c65a745923..78f56944e640 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -274,7 +274,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -306,18 +306,18 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
radio->curfreq = f->frequency;
if (dsbr100_setfreq(radio, radio->curfreq)==-1)
- warn("Set frequency failed");
+ dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = radio->curfreq;
@@ -342,7 +342,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -355,16 +355,22 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value) {
- if (dsbr100_stop(radio)==-1)
- warn("Radio did not respond properly");
+ if (dsbr100_stop(radio) == -1) {
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
+ return -EBUSY;
+ }
} else {
- if (dsbr100_start(radio)==-1)
- warn("Radio did not respond properly");
+ if (dsbr100_start(radio) == -1) {
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not respond properly\n");
+ return -EBUSY;
+ }
}
return 0;
}
@@ -405,23 +411,27 @@ static int vidioc_s_audio(struct file *file, void *priv,
static int usb_dsbr100_open(struct inode *inode, struct file *file)
{
- struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
+ lock_kernel();
radio->users = 1;
radio->muted = 1;
if (dsbr100_start(radio)<0) {
- warn("Radio did not start up properly");
+ dev_warn(&radio->usbdev->dev,
+ "Radio did not start up properly\n");
radio->users = 0;
+ unlock_kernel();
return -EIO;
}
dsbr100_setfreq(radio, radio->curfreq);
+ unlock_kernel();
return 0;
}
static int usb_dsbr100_close(struct inode *inode, struct file *file)
{
- struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+ struct dsbr100_device *radio = video_drvdata(file);
if (!radio)
return -ENODEV;
@@ -494,7 +504,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->curfreq = FREQ_MIN*FREQ_MUL;
video_set_drvdata(radio->videodev, radio);
if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
- warn("Could not register video device");
+ dev_warn(&intf->dev, "Could not register video device\n");
video_device_release(radio->videodev);
kfree(radio->transfer_buffer);
kfree(radio);
@@ -507,7 +517,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
static int __init dsbr100_init(void)
{
int retval = usb_register(&usb_dsbr100_driver);
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 1f064f4b32df..9305e958fc66 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -51,6 +51,7 @@ static struct mutex lock;
struct rt_device
{
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -245,8 +246,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -273,8 +273,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
rt->curfreq = f->frequency;
rt_setfreq(rt, rt->curfreq);
@@ -284,8 +283,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
@@ -310,8 +308,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -327,8 +324,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -378,10 +374,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack_unit;
+static int rtrack_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rtrack_unit.in_use);
+ return 0;
+}
+
static const struct file_operations rtrack_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = rtrack_exclusive_open,
+ .release = rtrack_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -408,6 +415,7 @@ static struct video_device rtrack_radio = {
.name = "RadioTrack radio",
.fops = &rtrack_fops,
.ioctl_ops = &rtrack_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init rtrack_init(void)
@@ -424,7 +432,7 @@ static int __init rtrack_init(void)
return -EBUSY;
}
- rtrack_radio.priv=&rtrack_unit;
+ video_set_drvdata(&rtrack_radio, &rtrack_unit);
if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 628c689e3ffe..d78489573230 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -70,6 +70,7 @@ static struct mutex lock;
struct az_device
{
+ unsigned long in_use;
int curvol;
unsigned long curfreq;
int stereo;
@@ -195,8 +196,7 @@ static int vidioc_querycap (struct file *file, void *priv,
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -264,8 +264,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
static int vidioc_s_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
az->curfreq = f->frequency;
az_setfreq(az, az->curfreq);
@@ -275,8 +274,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = az->curfreq;
@@ -302,8 +300,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -322,8 +319,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct az_device *az = dev->priv;
+ struct az_device *az = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -342,10 +338,21 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
static struct az_device aztech_unit;
+static int aztech_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
+}
+
+static int aztech_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &aztech_unit.in_use);
+ return 0;
+}
+
static const struct file_operations aztech_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = aztech_exclusive_open,
+ .release = aztech_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -369,9 +376,10 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
};
static struct video_device aztech_radio = {
- .name = "Aztech radio",
- .fops = &aztech_fops,
- .ioctl_ops = &aztech_ioctl_ops,
+ .name = "Aztech radio",
+ .fops = &aztech_fops,
+ .ioctl_ops = &aztech_ioctl_ops,
+ .release = video_device_release_empty,
};
module_param_named(debug,aztech_radio.debug, int, 0644);
@@ -392,7 +400,7 @@ static int __init aztech_init(void)
}
mutex_init(&lock);
- aztech_radio.priv=&aztech_unit;
+ video_set_drvdata(&aztech_radio, &aztech_unit);
if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io,2);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 04c3698d32e4..0490a1fa999d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -589,6 +589,7 @@ static struct video_device cadet_radio = {
.name = "Cadet radio",
.fops = &cadet_fops,
.ioctl_ops = &cadet_ioctl_ops,
+ .release = video_device_release_empty,
};
#ifdef CONFIG_PNP
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 5cd7f032298d..e15bee6d7cfc 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -100,9 +100,8 @@ struct gemtek_pci_card {
u8 mute;
};
-static const char rcsid[] = "$Id: radio-gemtek-pci.c,v 1.1 2001/07/23 08:08:16 ted Exp ted $";
-
static int nr_radio = -1;
+static unsigned long in_use;
static inline u8 gemtek_pci_out( u16 value, u32 port )
{
@@ -205,8 +204,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -233,8 +231,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) ||
(f->frequency > GEMTEK_PCI_RANGE_HIGH) )
@@ -248,8 +245,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = card->current_frequency;
@@ -273,8 +269,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -293,8 +288,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_pci_card *card = dev->priv;
+ struct gemtek_pci_card *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -364,10 +358,21 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
static int mx = 1;
+static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations gemtek_pci_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = gemtek_pci_exclusive_open,
+ .release = gemtek_pci_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -391,9 +396,10 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
};
static struct video_device vdev_template = {
- .name = "Gemtek PCI Radio",
- .fops = &gemtek_pci_fops,
- .ioctl_ops = &gemtek_pci_ioctl_ops,
+ .name = "Gemtek PCI Radio",
+ .fops = &gemtek_pci_fops,
+ .ioctl_ops = &gemtek_pci_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
@@ -431,7 +437,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
}
card->videodev = devradio;
- devradio->priv = card;
+ video_set_drvdata(devradio, card);
gemtek_pci_mute( card );
printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 0a0f956bb308..d131a5d38128 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -57,6 +57,7 @@ static int shutdown = 1;
static int keepmuted = 1;
static int initmute = 1;
static int radio_nr = -1;
+static unsigned long in_use;
module_param(io, int, 0444);
MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
@@ -393,10 +394,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
}
};
+static int gemtek_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int gemtek_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations gemtek_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = gemtek_exclusive_open,
+ .release = gemtek_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -447,8 +459,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
gemtek_setfreq(rt, f->frequency);
@@ -458,8 +469,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->lastfreq;
@@ -483,8 +493,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -503,8 +512,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct gemtek_device *rt = dev->priv;
+ struct gemtek_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -569,9 +577,10 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
};
static struct video_device gemtek_radio = {
- .name = "GemTek Radio card",
- .fops = &gemtek_fops,
- .ioctl_ops = &gemtek_ioctl_ops,
+ .name = "GemTek Radio card",
+ .fops = &gemtek_fops,
+ .ioctl_ops = &gemtek_ioctl_ops,
+ .release = video_device_release_empty,
};
/*
@@ -610,7 +619,7 @@ static int __init gemtek_init(void)
return -EINVAL;
}
- gemtek_radio.priv = &gemtek_unit;
+ video_set_drvdata(&gemtek_radio, &gemtek_unit);
if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 1);
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 9ef0a763eeb7..4bf4d007bcfa 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -75,7 +75,21 @@ static struct v4l2_queryctrl radio_qctrl[] = {
static int radio_nr = -1;
module_param(radio_nr, int, 0);
+static unsigned long in_use;
+
static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+static int maestro_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maestro_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static void maestro_remove(struct pci_dev *pdev);
static struct pci_device_id maestro_r_pci_tbl[] = {
@@ -98,8 +112,8 @@ static struct pci_driver maestro_r_driver = {
static const struct file_operations maestro_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = maestro_exclusive_open,
+ .release = maestro_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -196,8 +210,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -229,8 +242,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
return -EINVAL;
@@ -241,8 +253,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = BITS2FREQ(radio_bits_get(card));
@@ -267,8 +278,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -281,8 +291,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card = video_get_drvdata(dev);
+ struct radio_device *card = video_drvdata(file);
register u16 io = card->io;
register u16 omask = inw(io + IO_MASK);
@@ -374,6 +383,7 @@ static struct video_device maestro_radio = {
.name = "Maestro radio",
.fops = &maestro_fops,
.ioctl_ops = &maestro_ioctl_ops,
+ .release = video_device_release,
};
static int __devinit maestro_probe(struct pci_dev *pdev,
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 0cc6fcb041fd..c777a17b00bc 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -85,6 +85,7 @@ static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16 ;
static int radio_nr = -1;
module_param(radio_nr, int, 0);
+static unsigned long in_use;
#define FREQ_LO 50*16000
#define FREQ_HI 150*16000
@@ -99,10 +100,21 @@ module_param(radio_nr, int, 0);
#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
+static int maxiradio_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int maxiradio_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations maxiradio_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = maxiradio_exclusive_open,
+ .release = maxiradio_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -219,8 +231,7 @@ static int vidioc_querycap (struct file *file, void *priv,
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -290,8 +301,7 @@ static int vidioc_s_audio (struct file *file, void *priv,
static int vidioc_s_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
dprintk(1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
@@ -312,8 +322,7 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = card->freq;
@@ -343,8 +352,7 @@ static int vidioc_queryctrl (struct file *file, void *priv,
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -358,8 +366,7 @@ static int vidioc_g_ctrl (struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -390,9 +397,10 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
};
static struct video_device maxiradio_radio = {
- .name = "Maxi Radio FM2000 radio",
- .fops = &maxiradio_fops,
- .ioctl_ops = &maxiradio_ioctl_ops,
+ .name = "Maxi Radio FM2000 radio",
+ .fops = &maxiradio_fops,
+ .ioctl_ops = &maxiradio_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -408,7 +416,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d
radio_unit.io = pci_resource_start(pdev, 0);
mutex_init(&radio_unit.lock);
- maxiradio_radio.priv = &radio_unit;
+ video_set_drvdata(&maxiradio_radio, &radio_unit);
if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
printk("radio-maxiradio: can't register device!");
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
new file mode 100644
index 000000000000..a33717c48003
--- /dev/null
+++ b/drivers/media/radio/radio-mr800.c
@@ -0,0 +1,628 @@
+/*
+ * A driver for the AverMedia MR 800 USB FM radio. This device plugs
+ * into both the USB and an analog audio input, so this thing
+ * only deals with initialization and frequency setting, the
+ * audio data has to be handled by a sound driver.
+ *
+ * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Big thanks to authors of dsbr100.c and radio-si470x.c
+ *
+ * When work was looked pretty good, i discover this:
+ * http://av-usbradio.sourceforge.net/index.php
+ * http://sourceforge.net/projects/av-usbradio/
+ * Latest release of theirs project was in 2005.
+ * Probably, this driver could be improved trough using their
+ * achievements (specifications given).
+ * So, we have smth to begin with.
+ *
+ * History:
+ * Version 0.01: First working version.
+ * It's required to blacklist AverMedia USB Radio
+ * in usbhid/hid-quirks.c
+ *
+ * Many things to do:
+ * - Correct power managment of device (suspend & resume)
+ * - Make x86 independance (little-endian and big-endian stuff)
+ * - Add code for scanning and smooth tuning
+ * - Checked and add stereo&mono stuff
+ * - Add code for sensitivity value
+ * - Correct mistakes
+ * - In Japan another FREQ_MIN and FREQ_MAX
+ */
+
+/* kernel includes */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/usb.h>
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+
+/* driver and module definitions */
+#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
+#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
+#define DRIVER_VERSION "0.01"
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define USB_AMRADIO_VENDOR 0x07ca
+#define USB_AMRADIO_PRODUCT 0xb800
+
+/* Probably USB_TIMEOUT should be modified in module parameter */
+#define BUFFER_LENGTH 8
+#define USB_TIMEOUT 500
+
+/* Frequency limits in MHz -- these are European values. For Japanese
+devices, that would be 76 and 91. */
+#define FREQ_MIN 87.5
+#define FREQ_MAX 108.0
+#define FREQ_MUL 16000
+
+/* module parameter */
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+static struct v4l2_queryctrl radio_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+/* HINT: the disabled controls are only here to satify kradio and such apps */
+ { .id = V4L2_CID_AUDIO_VOLUME,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_BASS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+ {
+ .id = V4L2_CID_AUDIO_LOUDNESS,
+ .flags = V4L2_CTRL_FLAG_DISABLED,
+ },
+};
+
+static int usb_amradio_probe(struct usb_interface *intf,
+ const struct usb_device_id *id);
+static void usb_amradio_disconnect(struct usb_interface *intf);
+static int usb_amradio_open(struct inode *inode, struct file *file);
+static int usb_amradio_close(struct inode *inode, struct file *file);
+static int usb_amradio_suspend(struct usb_interface *intf,
+ pm_message_t message);
+static int usb_amradio_resume(struct usb_interface *intf);
+
+/* Data for one (physical) device */
+struct amradio_device {
+ /* reference to USB and video device */
+ struct usb_device *usbdev;
+ struct video_device *videodev;
+
+ unsigned char *buffer;
+ struct mutex lock; /* buffer locking */
+ int curfreq;
+ int stereo;
+ int users;
+ int removed;
+ int muted;
+};
+
+/* USB Device ID List */
+static struct usb_device_id usb_amradio_device_table[] = {
+ {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
+ USB_CLASS_HID, 0, 0) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
+
+/* USB subsystem interface */
+static struct usb_driver usb_amradio_driver = {
+ .name = "radio-mr800",
+ .probe = usb_amradio_probe,
+ .disconnect = usb_amradio_disconnect,
+ .suspend = usb_amradio_suspend,
+ .resume = usb_amradio_resume,
+ .reset_resume = usb_amradio_resume,
+ .id_table = usb_amradio_device_table,
+ .supports_autosuspend = 1,
+};
+
+/* switch on radio. Send 8 bytes to device. */
+static int amradio_start(struct amradio_device *radio)
+{
+ int retval;
+ int size;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0xab;
+ radio->buffer[5] = 0x00;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->muted = 0;
+
+ return retval;
+}
+
+/* switch off radio */
+static int amradio_stop(struct amradio_device *radio)
+{
+ int retval;
+ int size;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0xab;
+ radio->buffer[5] = 0x01;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->muted = 1;
+
+ return retval;
+}
+
+/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static int amradio_setfreq(struct amradio_device *radio, int freq)
+{
+ int retval;
+ int size;
+ unsigned short freq_send = 0x13 + (freq >> 3) / 25;
+
+ mutex_lock(&radio->lock);
+
+ radio->buffer[0] = 0x00;
+ radio->buffer[1] = 0x55;
+ radio->buffer[2] = 0xaa;
+ radio->buffer[3] = 0x03;
+ radio->buffer[4] = 0xa4;
+ radio->buffer[5] = 0x00;
+ radio->buffer[6] = 0x00;
+ radio->buffer[7] = 0x08;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ /* frequency is calculated from freq_send and placed in first 2 bytes */
+ radio->buffer[0] = (freq_send >> 8) & 0xff;
+ radio->buffer[1] = freq_send & 0xff;
+ radio->buffer[2] = 0x01;
+ radio->buffer[3] = 0x00;
+ radio->buffer[4] = 0x00;
+ /* 5 and 6 bytes of buffer already = 0x00 */
+ radio->buffer[7] = 0x00;
+
+ retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
+ (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
+
+ if (retval) {
+ mutex_unlock(&radio->lock);
+ return retval;
+ }
+
+ mutex_unlock(&radio->lock);
+
+ radio->stereo = 0;
+
+ return retval;
+}
+
+/* USB subsystem interface begins here */
+
+/* handle unplugging of the device, release data structures
+if nothing keeps us from doing it. If something is still
+keeping us busy, the release callback of v4l will take care
+of releasing it. */
+static void usb_amradio_disconnect(struct usb_interface *intf)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (radio) {
+ video_unregister_device(radio->videodev);
+ radio->videodev = NULL;
+ if (radio->users) {
+ kfree(radio->buffer);
+ kfree(radio);
+ } else {
+ radio->removed = 1;
+ }
+ }
+}
+
+/* vidioc_querycap - query device capabilities */
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
+ strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
+ sprintf(v->bus_info, "USB");
+ v->version = RADIO_VERSION;
+ v->capabilities = V4L2_CAP_TUNER;
+ return 0;
+}
+
+/* vidioc_g_tuner - get tuner attributes */
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ if (v->index > 0)
+ return -EINVAL;
+
+/* TODO: Add function which look is signal stereo or not
+ * amradio_getstat(radio);
+ */
+ radio->stereo = -1;
+ strcpy(v->name, "FM");
+ v->type = V4L2_TUNER_RADIO;
+ v->rangelow = FREQ_MIN * FREQ_MUL;
+ v->rangehigh = FREQ_MAX * FREQ_MUL;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ v->capability = V4L2_TUNER_CAP_LOW;
+ if (radio->stereo)
+ v->audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ v->signal = 0xffff; /* Can't get the signal strength, sad.. */
+ v->afc = 0; /* Don't know what is this */
+ return 0;
+}
+
+/* vidioc_s_tuner - set tuner attributes */
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ if (v->index > 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* vidioc_s_frequency - set tuner radio frequency */
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ radio->curfreq = f->frequency;
+ if (amradio_setfreq(radio, radio->curfreq) < 0)
+ warn("Set frequency failed");
+ return 0;
+}
+
+/* vidioc_g_frequency - get tuner radio frequency */
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = radio->curfreq;
+ return 0;
+}
+
+/* vidioc_queryctrl - enumerate control items */
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+ if (qc->id && qc->id == radio_qctrl[i].id) {
+ memcpy(qc, &(radio_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+/* vidioc_g_ctrl - get the value of a control */
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = radio->muted;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/* vidioc_s_ctrl - set the value of a control */
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value) {
+ if (amradio_stop(radio) < 0) {
+ warn("amradio_stop() failed");
+ return -1;
+ }
+ } else {
+ if (amradio_start(radio) < 0) {
+ warn("amradio_start() failed");
+ return -1;
+ }
+ }
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/* vidioc_g_audio - get audio attributes */
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index > 1)
+ return -EINVAL;
+
+ strcpy(a->name, "Radio");
+ a->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
+
+/* vidioc_s_audio - set audio attributes */
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* vidioc_g_input - get input */
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+/* vidioc_s_input - set input */
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* open device - amradio_start() and amradio_setfreq() */
+static int usb_amradio_open(struct inode *inode, struct file *file)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ radio->users = 1;
+ radio->muted = 1;
+
+ if (amradio_start(radio) < 0) {
+ warn("Radio did not start up properly");
+ radio->users = 0;
+ return -EIO;
+ }
+ if (amradio_setfreq(radio, radio->curfreq) < 0)
+ warn("Set frequency failed");
+ return 0;
+}
+
+/*close device - free driver structures */
+static int usb_amradio_close(struct inode *inode, struct file *file)
+{
+ struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+ if (!radio)
+ return -ENODEV;
+ radio->users = 0;
+ if (radio->removed) {
+ kfree(radio->buffer);
+ kfree(radio);
+ }
+ return 0;
+}
+
+/* Suspend device - stop device. Need to be checked and fixed */
+static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ if (amradio_stop(radio) < 0)
+ warn("amradio_stop() failed");
+
+ info("radio-mr800: Going into suspend..");
+
+ return 0;
+}
+
+/* Resume device - start device. Need to be checked and fixed */
+static int usb_amradio_resume(struct usb_interface *intf)
+{
+ struct amradio_device *radio = usb_get_intfdata(intf);
+
+ if (amradio_start(radio) < 0)
+ warn("amradio_start() failed");
+
+ info("radio-mr800: Coming out of suspend..");
+
+ return 0;
+}
+
+/* File system interface */
+static const struct file_operations usb_amradio_fops = {
+ .owner = THIS_MODULE,
+ .open = usb_amradio_open,
+ .release = usb_amradio_close,
+ .ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = v4l_compat_ioctl32,
+#endif
+ .llseek = no_llseek,
+};
+
+static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+};
+
+/* V4L2 interface */
+static struct video_device amradio_videodev_template = {
+ .name = "AverMedia MR 800 USB FM Radio",
+ .fops = &usb_amradio_fops,
+ .ioctl_ops = &usb_amradio_ioctl_ops,
+ .release = video_device_release,
+};
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_amradio_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct amradio_device *radio;
+
+ radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
+
+ if (!(radio))
+ return -ENOMEM;
+
+ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
+
+ if (!(radio->buffer)) {
+ kfree(radio);
+ return -ENOMEM;
+ }
+
+ radio->videodev = video_device_alloc();
+
+ if (!(radio->videodev)) {
+ kfree(radio->buffer);
+ kfree(radio);
+ return -ENOMEM;
+ }
+
+ memcpy(radio->videodev, &amradio_videodev_template,
+ sizeof(amradio_videodev_template));
+
+ radio->removed = 0;
+ radio->users = 0;
+ radio->usbdev = interface_to_usbdev(intf);
+ radio->curfreq = 95.16 * FREQ_MUL;
+
+ mutex_init(&radio->lock);
+
+ video_set_drvdata(radio->videodev, radio);
+ if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
+ warn("Could not register video device");
+ video_device_release(radio->videodev);
+ kfree(radio->buffer);
+ kfree(radio);
+ return -EIO;
+ }
+
+ usb_set_intfdata(intf, radio);
+ return 0;
+}
+
+static int __init amradio_init(void)
+{
+ int retval = usb_register(&usb_amradio_driver);
+
+ info(DRIVER_VERSION " " DRIVER_DESC);
+ if (retval)
+ err("usb_register failed. Error number %d", retval);
+ return retval;
+}
+
+static void __exit amradio_exit(void)
+{
+ usb_deregister(&usb_amradio_driver);
+}
+
+module_init(amradio_init);
+module_exit(amradio_exit);
+
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 6d820e2481e7..a67079777419 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -52,6 +52,7 @@ static spinlock_t lock;
struct rt_device
{
+ unsigned long in_use;
int port;
unsigned long curfreq;
int muted;
@@ -153,8 +154,7 @@ static int rt_getsigstr(struct rt_device *dev)
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -173,8 +173,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
rt->curfreq = f->frequency;
rt_setfreq(rt, rt->curfreq);
@@ -184,8 +183,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
@@ -210,8 +208,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -230,8 +227,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct rt_device *rt = dev->priv;
+ struct rt_device *rt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack2_unit;
+static int rtrack2_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int rtrack2_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &rtrack2_unit.in_use);
+ return 0;
+}
+
static const struct file_operations rtrack2_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = rtrack2_exclusive_open,
+ .release = rtrack2_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device rtrack2_radio = {
.name = "RadioTrack II radio",
.fops = &rtrack2_fops,
.ioctl_ops = &rtrack2_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init rtrack2_init(void)
@@ -329,7 +337,7 @@ static int __init rtrack2_init(void)
return -EBUSY;
}
- rtrack2_radio.priv=&rtrack2_unit;
+ video_set_drvdata(&rtrack2_radio, &rtrack2_unit);
spin_lock_init(&lock);
if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 0d478f54a907..329c90bddadd 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -45,6 +45,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
struct fmi_device
{
+ unsigned long in_use;
int port;
int curvol; /* 1 or 0 */
unsigned long curfreq; /* freq in kHz */
@@ -146,8 +147,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
int mult;
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -175,8 +175,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
f->frequency *= 1000;
@@ -193,8 +192,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = fmi->curfreq;
@@ -221,8 +219,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -235,8 +232,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmi_device *fmi = dev->priv;
+ struct fmi_device *fmi = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -284,10 +280,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmi_device fmi_unit;
+static int fmi_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmi_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &fmi_unit.in_use);
+ return 0;
+}
+
static const struct file_operations fmi_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = fmi_exclusive_open,
+ .release = fmi_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -314,6 +321,7 @@ static struct video_device fmi_radio = {
.name = "SF16FMx radio",
.fops = &fmi_fops,
.ioctl_ops = &fmi_ioctl_ops,
+ .release = video_device_release_empty,
};
/* ladis: this is my card. does any other types exist? */
@@ -373,7 +381,7 @@ static int __init fmi_init(void)
fmi_unit.curvol = 0;
fmi_unit.curfreq = 0;
fmi_unit.flags = V4L2_TUNER_CAP_LOW;
- fmi_radio.priv = &fmi_unit;
+ video_set_drvdata(&fmi_radio, &fmi_unit);
mutex_init(&lock);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 6290553d24be..b1f47c322e02 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -64,6 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
/* this should be static vars for module size */
struct fmr2_device
{
+ unsigned long in_use;
int port;
int curvol; /* 0-15 */
int mute;
@@ -229,8 +230,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
int mult;
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -262,8 +262,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
f->frequency *= 1000;
@@ -286,8 +285,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = fmr2->curfreq;
@@ -313,8 +311,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +327,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct fmr2_device *fmr2 = dev->priv;
+ struct fmr2_device *fmr2 = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -400,10 +396,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmr2_device fmr2_unit;
+static int fmr2_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
+}
+
+static int fmr2_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &fmr2_unit.in_use);
+ return 0;
+}
+
static const struct file_operations fmr2_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = fmr2_exclusive_open,
+ .release = fmr2_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -430,6 +437,7 @@ static struct video_device fmr2_radio = {
.name = "SF16FMR2 radio",
.fops = &fmr2_fops,
.ioctl_ops = &fmr2_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init fmr2_init(void)
@@ -441,7 +449,7 @@ static int __init fmr2_init(void)
fmr2_unit.stereo = 1;
fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
fmr2_unit.card_type = 0;
- fmr2_radio.priv = &fmr2_unit;
+ video_set_drvdata(&fmr2_radio, &fmr2_unit);
mutex_init(&lock);
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 16c7ef20265c..5920cd306975 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -104,6 +104,7 @@
* - hardware frequency seek support
* - afc indication
* - more safety checks, let si470x_get_freq return errno
+ * - vidioc behavior corrected according to v4l2 spec
*
* ToDo:
* - add firmware download/update support
@@ -141,9 +142,9 @@
/* USB Device ID List */
static struct usb_device_id si470x_usb_driver_id_table[] = {
/* Silicon Labs USB FM Radio Reference Design */
- { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
- { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
/* Terminating entry */
{ }
};
@@ -157,7 +158,7 @@ MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
/* Radio Nr */
static int radio_nr = -1;
-module_param(radio_nr, int, 0);
+module_param(radio_nr, int, 0444);
MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* Spacing (kHz) */
@@ -165,42 +166,42 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* 1: 100 kHz (Europe, Japan) */
/* 2: 50 kHz */
static unsigned short space = 2;
-module_param(space, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
+module_param(space, ushort, 0444);
+MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*");
/* Bottom of Band (MHz) */
/* 0: 87.5 - 108 MHz (USA, Europe)*/
/* 1: 76 - 108 MHz (Japan wide band) */
/* 2: 76 - 90 MHz (Japan) */
static unsigned short band = 1;
-module_param(band, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
+module_param(band, ushort, 0444);
+MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz");
/* De-emphasis */
/* 0: 75 us (USA) */
/* 1: 50 us (Europe, Australia, Japan) */
static unsigned short de = 1;
-module_param(de, ushort, 0);
-MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*");
+module_param(de, ushort, 0444);
+MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*");
/* USB timeout */
static unsigned int usb_timeout = 500;
-module_param(usb_timeout, uint, 0);
+module_param(usb_timeout, uint, 0644);
MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*");
/* Tune timeout */
static unsigned int tune_timeout = 3000;
-module_param(tune_timeout, uint, 0);
+module_param(tune_timeout, uint, 0644);
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
/* Seek timeout */
static unsigned int seek_timeout = 5000;
-module_param(seek_timeout, uint, 0);
+module_param(seek_timeout, uint, 0644);
MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
/* RDS buffer blocks */
static unsigned int rds_buf = 100;
-module_param(rds_buf, uint, 0);
+module_param(rds_buf, uint, 0444);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
/* RDS maximum block errors */
@@ -209,7 +210,7 @@ static unsigned short max_rds_errors = 1;
/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
/* 2 means 3-5 errors requiring correction */
/* 3 means 6+ errors or errors in checkword, correction not possible */
-module_param(max_rds_errors, ushort, 0);
+module_param(max_rds_errors, ushort, 0644);
MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
/* RDS poll frequency */
@@ -218,7 +219,7 @@ static unsigned int rds_poll_time = 40;
/* 50 is used by radio-cadet */
/* 75 should be okay */
/* 80 is the usual RDS receive interval */
-module_param(rds_poll_time, uint, 0);
+module_param(rds_poll_time, uint, 0644);
MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
@@ -667,23 +668,29 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
int retval;
/* Spacing (kHz) */
- switch (space) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
+ case 0:
+ spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
+ case 1:
+ spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
+ default:
+ spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
- switch (band) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+ case 0:
+ band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
+ default:
+ band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
+ case 2:
+ band_bottom = 76 * FREQ_MUL; break;
};
/* read channel */
@@ -706,23 +713,29 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
unsigned short chan;
/* Spacing (kHz) */
- switch (space) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) {
/* 0: 200 kHz (USA, Australia) */
- case 0 : spacing = 0.200 * FREQ_MUL; break;
+ case 0:
+ spacing = 0.200 * FREQ_MUL; break;
/* 1: 100 kHz (Europe, Japan) */
- case 1 : spacing = 0.100 * FREQ_MUL; break;
+ case 1:
+ spacing = 0.100 * FREQ_MUL; break;
/* 2: 50 kHz */
- default: spacing = 0.050 * FREQ_MUL; break;
+ default:
+ spacing = 0.050 * FREQ_MUL; break;
};
/* Bottom of Band (MHz) */
- switch (band) {
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe) */
- case 0 : band_bottom = 87.5 * FREQ_MUL; break;
+ case 0:
+ band_bottom = 87.5 * FREQ_MUL; break;
/* 1: 76 - 108 MHz (Japan wide band) */
- default: band_bottom = 76 * FREQ_MUL; break;
+ default:
+ band_bottom = 76 * FREQ_MUL; break;
/* 2: 76 - 90 MHz (Japan) */
- case 2 : band_bottom = 76 * FREQ_MUL; break;
+ case 2:
+ band_bottom = 76 * FREQ_MUL; break;
};
/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
@@ -986,7 +999,7 @@ static void si470x_work(struct work_struct *work)
static ssize_t si470x_fops_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
unsigned int block_count = 0;
@@ -1047,7 +1060,7 @@ done:
static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* switch on rds reception */
@@ -1071,9 +1084,10 @@ static unsigned int si470x_fops_poll(struct file *file,
*/
static int si470x_fops_open(struct inode *inode, struct file *file)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval;
+ lock_kernel();
radio->users++;
retval = usb_autopm_get_interface(radio->intf);
@@ -1090,6 +1104,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
}
done:
+ unlock_kernel();
return retval;
}
@@ -1099,7 +1114,7 @@ done:
*/
static int si470x_fops_release(struct inode *inode, struct file *file)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety check */
@@ -1162,7 +1177,6 @@ static const struct file_operations si470x_fops = {
* si470x_v4l2_queryctrl - query control
*/
static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
-/* HINT: the disabled controls are only here to satify kradio and such apps */
{
.id = V4L2_CID_AUDIO_VOLUME,
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -1173,18 +1187,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
.default_value = 15,
},
{
- .id = V4L2_CID_AUDIO_BALANCE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_BASS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
- .id = V4L2_CID_AUDIO_TREBLE,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
- {
.id = V4L2_CID_AUDIO_MUTE,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Mute",
@@ -1193,10 +1195,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
.step = 1,
.default_value = 1,
},
- {
- .id = V4L2_CID_AUDIO_LOUDNESS,
- .flags = V4L2_CTRL_FLAG_DISABLED,
- },
};
@@ -1218,56 +1216,34 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
/*
- * si470x_vidioc_g_input - get input
- */
-static int si470x_vidioc_g_input(struct file *file, void *priv,
- unsigned int *i)
-{
- *i = 0;
-
- return 0;
-}
-
-
-/*
- * si470x_vidioc_s_input - set input
- */
-static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
- int retval = 0;
-
- /* safety checks */
- if (i != 0)
- retval = -EINVAL;
-
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": set input failed with %d\n", retval);
- return retval;
-}
-
-
-/*
* si470x_vidioc_queryctrl - enumerate control items
*/
static int si470x_vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
- unsigned char i;
+ unsigned char i = 0;
int retval = -EINVAL;
- /* safety checks */
- if (!qc->id)
+ /* abort if qc->id is below V4L2_CID_BASE */
+ if (qc->id < V4L2_CID_BASE)
goto done;
+ /* search video control */
for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
if (qc->id == si470x_v4l2_queryctrl[i].id) {
memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
- retval = 0;
+ retval = 0; /* found */
break;
}
}
+ /* disable unsupported base controls */
+ /* to satisfy kradio and such apps */
+ if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
+ qc->flags = V4L2_CTRL_FLAG_DISABLED;
+ retval = 0;
+ }
+
done:
if (retval < 0)
printk(KERN_WARNING DRIVER_NAME
@@ -1282,7 +1258,7 @@ done:
static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1318,7 +1294,7 @@ done:
static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1358,44 +1334,13 @@ done:
static int si470x_vidioc_g_audio(struct file *file, void *priv,
struct v4l2_audio *audio)
{
- int retval = 0;
-
- /* safety checks */
- if (audio->index != 0) {
- retval = -EINVAL;
- goto done;
- }
-
+ /* driver constants */
+ audio->index = 0;
strcpy(audio->name, "Radio");
audio->capability = V4L2_AUDCAP_STEREO;
+ audio->mode = 0;
-done:
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": get audio failed with %d\n", retval);
- return retval;
-}
-
-
-/*
- * si470x_vidioc_s_audio - set audio attributes
- */
-static int si470x_vidioc_s_audio(struct file *file, void *priv,
- struct v4l2_audio *audio)
-{
- int retval = 0;
-
- /* safety checks */
- if (audio->index != 0) {
- retval = -EINVAL;
- goto done;
- }
-
-done:
- if (retval < 0)
- printk(KERN_WARNING DRIVER_NAME
- ": set audio failed with %d\n", retval);
- return retval;
+ return 0;
}
@@ -1405,7 +1350,7 @@ done:
static int si470x_vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1413,7 +1358,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
+ if (tuner->index != 0) {
retval = -EINVAL;
goto done;
}
@@ -1422,8 +1367,13 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
if (retval < 0)
goto done;
+ /* driver constants */
strcpy(tuner->name, "FM");
- switch (band) {
+ tuner->type = V4L2_TUNER_RADIO;
+ tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+
+ /* range limits */
+ switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
/* 0: 87.5 - 108 MHz (USA, Europe, default) */
default:
tuner->rangelow = 87.5 * FREQ_MUL;
@@ -1440,14 +1390,18 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
tuner->rangehigh = 90 * FREQ_MUL;
break;
};
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- tuner->capability = V4L2_TUNER_CAP_LOW;
- /* Stereo indicator == Stereo (instead of Mono) */
+ /* stereo indicator == stereo (instead of mono) */
if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
- tuner->audmode = V4L2_TUNER_MODE_STEREO;
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
else
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+ /* mono/stereo selector */
+ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
tuner->audmode = V4L2_TUNER_MODE_MONO;
+ else
+ tuner->audmode = V4L2_TUNER_MODE_STEREO;
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
@@ -1471,23 +1425,28 @@ done:
static int si470x_vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *tuner)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
- int retval = 0;
+ struct si470x_device *radio = video_drvdata(file);
+ int retval = -EINVAL;
/* safety checks */
if (radio->disconnected) {
retval = -EIO;
goto done;
}
- if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
- retval = -EINVAL;
+ if (tuner->index != 0)
goto done;
- }
- if (tuner->audmode == V4L2_TUNER_MODE_MONO)
+ /* mono/stereo selector */
+ switch (tuner->audmode) {
+ case V4L2_TUNER_MODE_MONO:
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
- else
+ break;
+ case V4L2_TUNER_MODE_STEREO:
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
+ break;
+ default:
+ goto done;
+ }
retval = si470x_set_register(radio, POWERCFG);
@@ -1505,7 +1464,7 @@ done:
static int si470x_vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1513,11 +1472,12 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
+ freq->type = V4L2_TUNER_RADIO;
retval = si470x_get_freq(radio, &freq->frequency);
done:
@@ -1534,7 +1494,7 @@ done:
static int si470x_vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *freq)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1542,7 +1502,7 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
+ if (freq->tuner != 0) {
retval = -EINVAL;
goto done;
}
@@ -1563,7 +1523,7 @@ done:
static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
struct v4l2_hw_freq_seek *seek)
{
- struct si470x_device *radio = video_get_drvdata(video_devdata(file));
+ struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* safety checks */
@@ -1571,7 +1531,7 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
retval = -EIO;
goto done;
}
- if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
+ if (seek->tuner != 0) {
retval = -EINVAL;
goto done;
}
@@ -1586,15 +1546,16 @@ done:
return retval;
}
+
+/*
+ * si470x_ioctl_ops - video device ioctl operations
+ */
static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
.vidioc_querycap = si470x_vidioc_querycap,
- .vidioc_g_input = si470x_vidioc_g_input,
- .vidioc_s_input = si470x_vidioc_s_input,
.vidioc_queryctrl = si470x_vidioc_queryctrl,
.vidioc_g_ctrl = si470x_vidioc_g_ctrl,
.vidioc_s_ctrl = si470x_vidioc_s_ctrl,
.vidioc_g_audio = si470x_vidioc_g_audio,
- .vidioc_s_audio = si470x_vidioc_s_audio,
.vidioc_g_tuner = si470x_vidioc_g_tuner,
.vidioc_s_tuner = si470x_vidioc_s_tuner,
.vidioc_g_frequency = si470x_vidioc_g_frequency,
@@ -1602,14 +1563,15 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
.vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
};
+
/*
- * si470x_viddev_tamples - video device interface
+ * si470x_viddev_template - video device interface
*/
static struct video_device si470x_viddev_template = {
.fops = &si470x_fops,
- .ioctl_ops = &si470x_ioctl_ops,
.name = DRIVER_NAME,
.release = video_device_release,
+ .ioctl_ops = &si470x_ioctl_ops,
};
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 0876fecc5f27..0abb186a9473 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -79,6 +79,7 @@ static spinlock_t lock;
struct tt_device
{
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -220,8 +221,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -248,8 +248,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
tt->curfreq = f->frequency;
tt_setfreq(tt, tt->curfreq);
@@ -259,8 +258,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = tt->curfreq;
@@ -285,8 +283,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -305,8 +302,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct tt_device *tt = dev->priv;
+ struct tt_device *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -356,10 +352,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct tt_device terratec_unit;
+static int terratec_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
+}
+
+static int terratec_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &terratec_unit.in_use);
+ return 0;
+}
+
static const struct file_operations terratec_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = terratec_exclusive_open,
+ .release = terratec_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -386,6 +393,7 @@ static struct video_device terratec_radio = {
.name = "TerraTec ActiveRadio",
.fops = &terratec_fops,
.ioctl_ops = &terratec_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init terratec_init(void)
@@ -401,7 +409,7 @@ static int __init terratec_init(void)
return -EBUSY;
}
- terratec_radio.priv=&terratec_unit;
+ video_set_drvdata(&terratec_radio, &terratec_unit);
spin_lock_init(&lock);
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index 193161956253..e7b111fcd105 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -78,6 +78,7 @@ static __u16 curtreble;
static unsigned long curfreq;
static int curstereo;
static int curmute;
+static unsigned long in_use;
/* i2c addresses */
#define TDA7318_ADDR 0x88
@@ -336,10 +337,21 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
+static int trust_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
+}
+
+static int trust_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &in_use);
+ return 0;
+}
+
static const struct file_operations trust_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = trust_exclusive_open,
+ .release = trust_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -366,6 +378,7 @@ static struct video_device trust_radio = {
.name = "Trust FM Radio",
.fops = &trust_fops,
.ioctl_ops = &trust_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init trust_init(void)
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index f8d62cfea774..952ec35a8415 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -79,7 +79,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
#endif
struct typhoon_device {
- int users;
+ unsigned long in_use;
int iobase;
int curvol;
int muted;
@@ -223,8 +223,7 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
typhoon->curfreq = f->frequency;
typhoon_setfreq(typhoon, typhoon->curfreq);
@@ -234,8 +233,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = typhoon->curfreq;
@@ -261,8 +259,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -278,8 +275,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct typhoon_device *typhoon = dev->priv;
+ struct typhoon_device *typhoon = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -334,10 +330,21 @@ static struct typhoon_device typhoon_unit =
.mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ,
};
+static int typhoon_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
+}
+
+static int typhoon_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &typhoon_unit.in_use);
+ return 0;
+}
+
static const struct file_operations typhoon_fops = {
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = typhoon_exclusive_open,
+ .release = typhoon_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -364,6 +371,7 @@ static struct video_device typhoon_radio = {
.name = "Typhoon Radio",
.fops = &typhoon_fops,
.ioctl_ops = &typhoon_ioctl_ops,
+ .release = video_device_release_empty,
};
#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
@@ -446,9 +454,8 @@ static int __init typhoon_init(void)
return -EBUSY;
}
- typhoon_radio.priv = &typhoon_unit;
- if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) == -1)
- {
+ video_set_drvdata(&typhoon_radio, &typhoon_unit);
+ if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 8);
return -EINVAL;
}
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 51d57ed3b3e1..15b10bad6796 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -69,6 +69,7 @@ static int io = CONFIG_RADIO_ZOLTRIX_PORT;
static int radio_nr = -1;
struct zol_device {
+ unsigned long in_use;
int port;
int curvol;
unsigned long curfreq;
@@ -122,8 +123,11 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
unsigned int stereo = dev->stereo;
int i;
- if (freq == 0)
- return 1;
+ if (freq == 0) {
+ printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n");
+ return -EINVAL;
+ }
+
m = (freq / 160 - 8800) * 2;
f = (unsigned long long) m + 0x4d1c;
@@ -245,8 +249,7 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
if (v->index > 0)
return -EINVAL;
@@ -276,19 +279,20 @@ static int vidioc_s_tuner(struct file *file, void *priv,
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
zol->curfreq = f->frequency;
- zol_setfreq(zol, zol->curfreq);
+ if (zol_setfreq(zol, zol->curfreq) != 0) {
+ printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+ return -EINVAL;
+ }
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = zol->curfreq;
@@ -313,8 +317,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -330,8 +333,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct video_device *dev = video_devdata(file);
- struct zol_device *zol = dev->priv;
+ struct zol_device *zol = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -347,7 +349,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return 0;
}
zol->stereo = 1;
- zol_setfreq(zol, zol->curfreq);
+ if (zol_setfreq(zol, zol->curfreq) != 0) {
+ printk(KERN_WARNING "zoltrix: Set frequency failed.\n");
+ return -EINVAL;
+ }
#if 0
/* FIXME: Implement stereo/mono switch on V4L2 */
if (v->mode & VIDEO_SOUND_STEREO) {
@@ -396,11 +401,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct zol_device zoltrix_unit;
+static int zoltrix_exclusive_open(struct inode *inode, struct file *file)
+{
+ return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
+}
+
+static int zoltrix_exclusive_release(struct inode *inode, struct file *file)
+{
+ clear_bit(0, &zoltrix_unit.in_use);
+ return 0;
+}
+
static const struct file_operations zoltrix_fops =
{
.owner = THIS_MODULE,
- .open = video_exclusive_open,
- .release = video_exclusive_release,
+ .open = zoltrix_exclusive_open,
+ .release = zoltrix_exclusive_release,
.ioctl = video_ioctl2,
#ifdef CONFIG_COMPAT
.compat_ioctl = v4l_compat_ioctl32,
@@ -427,6 +443,7 @@ static struct video_device zoltrix_radio = {
.name = "Zoltrix Radio Plus",
.fops = &zoltrix_fops,
.ioctl_ops = &zoltrix_ioctl_ops,
+ .release = video_device_release_empty,
};
static int __init zoltrix_init(void)
@@ -440,7 +457,7 @@ static int __init zoltrix_init(void)
return -ENXIO;
}
- zoltrix_radio.priv = &zoltrix_unit;
+ video_set_drvdata(&zoltrix_radio, &zoltrix_unit);
if (!request_region(io, 2, "zoltrix")) {
printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
return -EBUSY;