The patch number 10892 was added via Hans Verkuil <[email protected]>
to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel
If anyone has any objections, please let us know by sending a message to:
Linux Media Mailing List <[email protected]>
------
From: Hans Verkuil <[email protected]>
radio-typhoon: convert to v4l2_device.
Priority: normal
Signed-off-by: Hans Verkuil <[email protected]>
---
linux/drivers/media/radio/radio-typhoon.c | 412 +++++++++-------------
1 file changed, 172 insertions(+), 240 deletions(-)
diff -r 71e70b2d2fd7 -r ef2edf459255 linux/drivers/media/radio/radio-typhoon.c
--- a/linux/drivers/media/radio/radio-typhoon.c Fri Mar 06 17:54:23 2009 +0100
+++ b/linux/drivers/media/radio/radio-typhoon.c Fri Mar 06 17:54:52 2009 +0100
@@ -34,38 +34,17 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
#include <linux/ioport.h> /* request_region */
-#include <linux/proc_fs.h> /* radio card status report */
-#include <linux/seq_file.h>
-#include <asm/io.h> /* outb, outb_p */
-#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+#include <linux/videodev2.h> /* kernel radio structs */
+#include <linux/io.h> /* outb, outb_p */
+#include <linux/uaccess.h> /* copy to/from user */
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
#include "compat.h"
-#include <linux/videodev2.h> /* kernel radio structs */
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#include <linux/version.h> /* for KERNEL_VERSION MACRO */
-#define RADIO_VERSION KERNEL_VERSION(0,1,1)
-#define BANNER "Typhoon Radio Card driver v0.1.1\n"
-
-static struct v4l2_queryctrl radio_qctrl[] = {
- {
- .id = V4L2_CID_AUDIO_MUTE,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .default_value = 1,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- },{
- .id = V4L2_CID_AUDIO_VOLUME,
- .name = "Volume",
- .minimum = 0,
- .maximum = 65535,
- .step = 1<<14,
- .default_value = 0xff,
- .type = V4L2_CTRL_TYPE_INTEGER,
- }
-};
-
+
+MODULE_AUTHOR("Dr. Henrik Seidel");
+MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
+MODULE_LICENSE("GPL");
#ifndef CONFIG_RADIO_TYPHOON_PORT
#define CONFIG_RADIO_TYPHOON_PORT -1
@@ -75,13 +54,26 @@ static struct v4l2_queryctrl radio_qctrl
#define CONFIG_RADIO_TYPHOON_MUTEFREQ 0
#endif
-#ifndef CONFIG_PROC_FS
-#undef CONFIG_RADIO_TYPHOON_PROC_FS
-#endif
-
-struct typhoon_device {
- unsigned long in_use;
- int iobase;
+static int io = CONFIG_RADIO_TYPHOON_PORT;
+static int radio_nr = -1;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
+
+module_param(radio_nr, int, 0);
+
+static unsigned long mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ;
+module_param(mutefreq, ulong, 0);
+MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
+
+#define RADIO_VERSION KERNEL_VERSION(0, 1, 1)
+
+#define BANNER "Typhoon Radio Card driver v0.1.1\n"
+
+struct typhoon {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ int io;
int curvol;
int muted;
unsigned long curfreq;
@@ -89,25 +81,19 @@ struct typhoon_device {
struct mutex lock;
};
-static void typhoon_setvol_generic(struct typhoon_device *dev, int vol);
-static int typhoon_setfreq_generic(struct typhoon_device *dev,
- unsigned long frequency);
-static int typhoon_setfreq(struct typhoon_device *dev, unsigned long
frequency);
-static void typhoon_mute(struct typhoon_device *dev);
-static void typhoon_unmute(struct typhoon_device *dev);
-static int typhoon_setvol(struct typhoon_device *dev, int vol);
-
-static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
+static struct typhoon typhoon_card;
+
+static void typhoon_setvol_generic(struct typhoon *dev, int vol)
{
mutex_lock(&dev->lock);
vol >>= 14; /* Map 16 bit to 2 bit */
vol &= 3;
- outb_p(vol / 2, dev->iobase); /* Set the volume, high bit. */
- outb_p(vol % 2, dev->iobase + 2); /* Set the volume, low bit. */
+ outb_p(vol / 2, dev->io); /* Set the volume, high bit. */
+ outb_p(vol % 2, dev->io + 2); /* Set the volume, low bit. */
mutex_unlock(&dev->lock);
}
-static int typhoon_setfreq_generic(struct typhoon_device *dev,
+static int typhoon_setfreq_generic(struct typhoon *dev,
unsigned long frequency)
{
unsigned long outval;
@@ -131,22 +117,22 @@ static int typhoon_setfreq_generic(struc
outval -= (10 * x * x + 10433) / 20866;
outval += 4 * x - 11505;
- outb_p((outval >> 8) & 0x01, dev->iobase + 4);
- outb_p(outval >> 9, dev->iobase + 6);
- outb_p(outval & 0xff, dev->iobase + 8);
+ outb_p((outval >> 8) & 0x01, dev->io + 4);
+ outb_p(outval >> 9, dev->io + 6);
+ outb_p(outval & 0xff, dev->io + 8);
mutex_unlock(&dev->lock);
return 0;
}
-static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency)
+static int typhoon_setfreq(struct typhoon *dev, unsigned long frequency)
{
typhoon_setfreq_generic(dev, frequency);
dev->curfreq = frequency;
return 0;
}
-static void typhoon_mute(struct typhoon_device *dev)
+static void typhoon_mute(struct typhoon *dev)
{
if (dev->muted == 1)
return;
@@ -155,7 +141,7 @@ static void typhoon_mute(struct typhoon_
dev->muted = 1;
}
-static void typhoon_unmute(struct typhoon_device *dev)
+static void typhoon_unmute(struct typhoon *dev)
{
if (dev->muted == 0)
return;
@@ -164,7 +150,7 @@ static void typhoon_unmute(struct typhoo
dev->muted = 0;
}
-static int typhoon_setvol(struct typhoon_device *dev, int vol)
+static int typhoon_setvol(struct typhoon *dev, int vol)
{
if (dev->muted && vol != 0) { /* user is unmuting the card */
dev->curvol = vol;
@@ -189,9 +175,9 @@ static int vidioc_querycap(struct file *
{
strlcpy(v->driver, "radio-typhoon", sizeof(v->driver));
strlcpy(v->card, "Typhoon Radio", sizeof(v->card));
- sprintf(v->bus_info, "ISA");
+ strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
v->version = RADIO_VERSION;
- v->capabilities = V4L2_CAP_TUNER;
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
return 0;
}
@@ -201,10 +187,10 @@ static int vidioc_g_tuner(struct file *f
if (v->index > 0)
return -EINVAL;
- strcpy(v->name, "FM");
+ strlcpy(v->name, "FM", sizeof(v->name));
v->type = V4L2_TUNER_RADIO;
- v->rangelow = (87.5*16000);
- v->rangehigh = (108*16000);
+ v->rangelow = 87.5 * 16000;
+ v->rangehigh = 108 * 16000;
v->rxsubchans = V4L2_TUNER_SUB_MONO;
v->capability = V4L2_TUNER_CAP_LOW;
v->audmode = V4L2_TUNER_MODE_MONO;
@@ -215,44 +201,37 @@ static int vidioc_s_tuner(struct file *f
static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- if (v->index > 0)
- return -EINVAL;
-
+ return v->index ? -EINVAL : 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct typhoon *dev = video_drvdata(file);
+
+ f->type = V4L2_TUNER_RADIO;
+ f->frequency = dev->curfreq;
return 0;
}
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct typhoon_device *typhoon = video_drvdata(file);
-
- typhoon->curfreq = f->frequency;
- typhoon_setfreq(typhoon, typhoon->curfreq);
- return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
-{
- struct typhoon_device *typhoon = video_drvdata(file);
-
- f->type = V4L2_TUNER_RADIO;
- f->frequency = typhoon->curfreq;
-
+ struct typhoon *dev = video_drvdata(file);
+
+ dev->curfreq = f->frequency;
+ typhoon_setfreq(dev, dev->curfreq);
return 0;
}
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;
- }
+ switch (qc->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+ case V4L2_CID_AUDIO_VOLUME:
+ return v4l2_ctrl_query_fill(qc, 0, 65535, 16384, 65535);
}
return -EINVAL;
}
@@ -260,14 +239,14 @@ static int vidioc_g_ctrl(struct file *fi
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct typhoon_device *typhoon = video_drvdata(file);
+ struct typhoon *dev = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
- ctrl->value = typhoon->muted;
+ ctrl->value = dev->muted;
return 0;
case V4L2_CID_AUDIO_VOLUME:
- ctrl->value = typhoon->curvol;
+ ctrl->value = dev->curvol;
return 0;
}
return -EINVAL;
@@ -276,80 +255,86 @@ static int vidioc_s_ctrl (struct file *f
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct typhoon_device *typhoon = video_drvdata(file);
+ struct typhoon *dev = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
if (ctrl->value)
- typhoon_mute(typhoon);
+ typhoon_mute(dev);
else
- typhoon_unmute(typhoon);
+ typhoon_unmute(dev);
return 0;
case V4L2_CID_AUDIO_VOLUME:
- typhoon_setvol(typhoon, ctrl->value);
+ typhoon_setvol(dev, ctrl->value);
return 0;
}
return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ return i ? -EINVAL : 0;
}
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->index = 0;
+ strlcpy(a->name, "Radio", sizeof(a->name));
a->capability = V4L2_AUDCAP_STEREO;
- return 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
-{
- if (i != 0)
- return -EINVAL;
return 0;
}
static int vidioc_s_audio(struct file *file, void *priv,
struct v4l2_audio *a)
{
- if (a->index != 0)
- return -EINVAL;
- return 0;
-}
-
-static struct typhoon_device typhoon_unit =
-{
- .iobase = CONFIG_RADIO_TYPHOON_PORT,
- .curfreq = CONFIG_RADIO_TYPHOON_MUTEFREQ,
- .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ,
-};
-
-static int typhoon_exclusive_open(struct file *file)
-{
- return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
-}
-
-static int typhoon_exclusive_release(struct file *file)
-{
- clear_bit(0, &typhoon_unit.in_use);
+ return a->index ? -EINVAL : 0;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct typhoon *dev = video_drvdata(file);
+ struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+
+ v4l2_info(v4l2_dev, BANNER);
+#ifdef MODULE
+ v4l2_info(v4l2_dev, "Load type: Driver loaded as a module\n\n");
+#else
+ v4l2_info(v4l2_dev, "Load type: Driver compiled into kernel\n\n");
+#endif
+ v4l2_info(v4l2_dev, "frequency = %lu kHz\n", dev->curfreq >> 4);
+ v4l2_info(v4l2_dev, "volume = %d\n", dev->curvol);
+ v4l2_info(v4l2_dev, "mute = %s\n", dev->muted ? "on" : "off");
+ v4l2_info(v4l2_dev, "io = 0x%x\n", dev->io);
+ v4l2_info(v4l2_dev, "mute frequency = %lu kHz\n", dev->mutefreq >> 4);
+ return 0;
+}
+
+static int typhoon_open(struct file *file)
+{
+ return 0;
+}
+
+static int typhoon_release(struct file *file)
+{
return 0;
}
static const struct v4l2_file_operations typhoon_fops = {
.owner = THIS_MODULE,
- .open = typhoon_exclusive_open,
- .release = typhoon_exclusive_release,
+ .open = typhoon_open,
+ .release = typhoon_release,
.ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
+ .vidioc_log_status = vidioc_log_status,
.vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
@@ -364,125 +349,72 @@ static const struct v4l2_ioctl_ops typho
.vidioc_s_ctrl = vidioc_s_ctrl,
};
-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
-
-static int typhoon_proc_show(struct seq_file *m, void *v)
-{
- #ifdef MODULE
- #define MODULEPROCSTRING "Driver loaded as a module"
- #else
- #define MODULEPROCSTRING "Driver compiled into kernel"
- #endif
-
- seq_puts(m, BANNER);
- seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
- seq_printf(m, "frequency = %lu kHz\n",
- typhoon_unit.curfreq >> 4);
- seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
- seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
- "on" : "off");
- seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
- seq_printf(m, "mute frequency = %lu kHz\n",
- typhoon_unit.mutefreq >> 4);
- return 0;
-}
-
-static int typhoon_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, typhoon_proc_show, NULL);
-}
-
-static const struct file_operations typhoon_proc_fops = {
- .owner = THIS_MODULE,
- .open = typhoon_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
-
-MODULE_AUTHOR("Dr. Henrik Seidel");
-MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
-MODULE_LICENSE("GPL");
-
-static int io = -1;
-static int radio_nr = -1;
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
-module_param(radio_nr, int, 0);
-
-#ifdef MODULE
-static unsigned long mutefreq;
-module_param(mutefreq, ulong, 0);
-MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
-#endif
-
static int __init typhoon_init(void)
{
-#ifdef MODULE
- if (io == -1) {
- printk(KERN_ERR "radio-typhoon: You must set an I/O address
with io=0x316 or io=0x336\n");
+ struct typhoon *dev = &typhoon_card;
+ struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+ int res;
+
+ strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
+ dev->io = io;
+ dev->curfreq = dev->mutefreq = mutefreq;
+
+ if (dev->io == -1) {
+ v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316
or io=0x336\n");
return -EINVAL;
}
- typhoon_unit.iobase = io;
-
- if (mutefreq < 87000 || mutefreq > 108500) {
- printk(KERN_ERR "radio-typhoon: You must set a frequency (in
kHz) used when muting the card,\n");
- printk(KERN_ERR "radio-typhoon: e.g. with \"mutefreq=87500\"
(87000 <= mutefreq <= 108500)\n");
+
+ if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+ v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when
muting the card,\n");
+ v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <=
mutefreq <= 108500)\n");
return -EINVAL;
}
- typhoon_unit.mutefreq = mutefreq;
-#endif /* MODULE */
-
- printk(KERN_INFO BANNER);
- mutex_init(&typhoon_unit.lock);
- io = typhoon_unit.iobase;
- if (!request_region(io, 8, "typhoon")) {
- printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
- typhoon_unit.iobase);
+
+ mutex_init(&dev->lock);
+ if (!request_region(dev->io, 8, "typhoon")) {
+ v4l2_err(v4l2_dev, "port 0x%x already in use\n",
+ dev->io);
return -EBUSY;
}
- video_set_drvdata(&typhoon_radio, &typhoon_unit);
- if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO, radio_nr) <
0) {
- release_region(io, 8);
+ res = v4l2_device_register(NULL, v4l2_dev);
+ if (res < 0) {
+ release_region(dev->io, 8);
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ return res;
+ }
+ v4l2_info(v4l2_dev, BANNER);
+
+ strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+ dev->vdev.v4l2_dev = v4l2_dev;
+ dev->vdev.fops = &typhoon_fops;
+ dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
+ dev->vdev.release = video_device_release_empty;
+ video_set_drvdata(&dev->vdev, dev);
+ if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_device_unregister(&dev->v4l2_dev);
+ release_region(dev->io, 8);
return -EINVAL;
}
- printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
- printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
- typhoon_unit.mutefreq);
- typhoon_unit.mutefreq <<= 4;
+ v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
+ v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
+ dev->mutefreq <<= 4;
/* mute card - prevents noisy bootups */
- typhoon_mute(&typhoon_unit);
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
- if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
- printk(KERN_ERR "radio-typhoon: registering
/proc/driver/radio-typhoon failed\n");
-#endif
-
- return 0;
-}
-
-static void __exit typhoon_cleanup_module(void)
-{
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
- remove_proc_entry("driver/radio-typhoon", NULL);
-#endif
-
- video_unregister_device(&typhoon_radio);
- release_region(io, 8);
+ typhoon_mute(dev);
+
+ return 0;
+}
+
+static void __exit typhoon_exit(void)
+{
+ struct typhoon *dev = &typhoon_card;
+
+ video_unregister_device(&dev->vdev);
+ v4l2_device_unregister(&dev->v4l2_dev);
+ release_region(dev->io, 8);
}
module_init(typhoon_init);
-module_exit(typhoon_cleanup_module);
-
+module_exit(typhoon_exit);
+
---
Patch is available at:
http://linuxtv.org/hg/v4l-dvb/rev/ef2edf4592554a93f8be6dd49f096826a78dd5f5
_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits