The patch number 10890 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-terratec: convert to v4l2_device.
Priority: normal
Signed-off-by: Hans Verkuil <[email protected]>
---
linux/drivers/media/radio/radio-terratec.c | 408 ++++++++++-----------
1 file changed, 196 insertions(+), 212 deletions(-)
diff -r 4e5213601949 -r 75182c7f36d4 linux/drivers/media/radio/radio-terratec.c
--- a/linux/drivers/media/radio/radio-terratec.c Fri Mar 06 17:53:26
2009 +0100
+++ b/linux/drivers/media/radio/radio-terratec.c Fri Mar 06 17:53:58
2009 +0100
@@ -28,16 +28,31 @@
#include <linux/init.h> /* Initdata */
#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
-#include <asm/io.h> /* outb, outb_p */
-#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/videodev2.h> /* kernel radio structs */
+#include <linux/mutex.h>
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+#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/spinlock.h>
-
-#include <linux/version.h> /* for KERNEL_VERSION MACRO */
-#define RADIO_VERSION KERNEL_VERSION(0,0,2)
+
+MODULE_AUTHOR("R.OFFERMANNS & others");
+MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio
card.");
+MODULE_LICENSE("GPL");
+
+#ifndef CONFIG_RADIO_TERRATEC_PORT
+#define CONFIG_RADIO_TERRATEC_PORT 0x590
+#endif
+
+static int io = CONFIG_RADIO_TERRATEC_PORT;
+static int radio_nr = -1;
+
+module_param(io, int, 0);
+MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or
0x591)");
+module_param(radio_nr, int, 0);
+
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
static struct v4l2_queryctrl radio_qctrl[] = {
{
@@ -58,13 +73,6 @@ static struct v4l2_queryctrl radio_qctrl
}
};
-#ifndef CONFIG_RADIO_TERRATEC_PORT
-#define CONFIG_RADIO_TERRATEC_PORT 0x590
-#endif
-
-/**************** this ones are for the terratec *******************/
-#define BASEPORT 0x590
-#define VOLPORT 0x591
#define WRT_DIS 0x00
#define CLK_OFF 0x00
#define IIC_DATA 0x01
@@ -72,138 +80,124 @@ static struct v4l2_queryctrl radio_qctrl
#define DATA 0x04
#define CLK_ON 0x08
#define WRT_EN 0x10
-/*******************************************************************/
-
-static int io = CONFIG_RADIO_TERRATEC_PORT;
-static int radio_nr = -1;
-static spinlock_t lock;
-
-struct tt_device
-{
- unsigned long in_use;
- int port;
+
+struct terratec
+{
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ int io;
int curvol;
unsigned long curfreq;
int muted;
+ struct mutex lock;
};
+static struct terratec terratec_card;
/* local things */
-static void cardWriteVol(int volume)
+static void tt_write_vol(struct terratec *tt, int volume)
{
int i;
- volume = volume+(volume * 32); // change both channels
- spin_lock(&lock);
- for (i=0;i<8;i++)
- {
- if (volume & (0x80>>i))
- outb(0x80, VOLPORT);
- else outb(0x00, VOLPORT);
- }
- spin_unlock(&lock);
-}
-
-
-
-static void tt_mute(struct tt_device *dev)
-{
- dev->muted = 1;
- cardWriteVol(0);
-}
-
-static int tt_setvol(struct tt_device *dev, int vol)
-{
-
-// printk(KERN_ERR "setvol called, vol = %d\n", vol);
-
- if(vol == dev->curvol) { /* requested volume = current */
- if (dev->muted) { /* user is unmuting the card */
- dev->muted = 0;
- cardWriteVol(vol); /* enable card */
+
+ volume = volume + (volume * 32); /* change both channels */
+ mutex_lock(&tt->lock);
+ for (i = 0; i < 8; i++) {
+ if (volume & (0x80 >> i))
+ outb(0x80, tt->io + 1);
+ else
+ outb(0x00, tt->io + 1);
+ }
+ mutex_unlock(&tt->lock);
+}
+
+
+
+static void tt_mute(struct terratec *tt)
+{
+ tt->muted = 1;
+ tt_write_vol(tt, 0);
+}
+
+static int tt_setvol(struct terratec *tt, int vol)
+{
+ if (vol == tt->curvol) { /* requested volume = current */
+ if (tt->muted) { /* user is unmuting the card */
+ tt->muted = 0;
+ tt_write_vol(tt, vol); /* enable card */
}
-
- return 0;
- }
-
- if(vol == 0) { /* volume = 0 means mute the card */
- cardWriteVol(0); /* "turn off card" by setting vol to 0
*/
- dev->curvol = vol; /* track the volume state! */
- return 0;
- }
-
- dev->muted = 0;
-
- cardWriteVol(vol);
-
- dev->curvol = vol;
-
- return 0;
-
+ return 0;
+ }
+
+ if (vol == 0) { /* volume = 0 means mute the card */
+ tt_write_vol(tt, 0); /* "turn off card" by setting vol to 0
*/
+ tt->curvol = vol; /* track the volume state! */
+ return 0;
+ }
+
+ tt->muted = 0;
+ tt_write_vol(tt, vol);
+ tt->curvol = vol;
+ return 0;
}
/* this is the worst part in this driver */
/* many more or less strange things are going on here, but hey, it works :) */
-static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
+static int tt_setfreq(struct terratec *tt, unsigned long freq1)
{
int freq;
int i;
int p;
int temp;
long rest;
-
unsigned char buffer[25]; /* we have to bit shift 25
registers */
- freq = freq1/160; /* convert the freq. to a nice
to handle value */
- for(i=24;i>-1;i--)
- buffer[i]=0;
-
- rest = freq*10+10700; /* i once had understood what is going
on here */
+
+ mutex_lock(&tt->lock);
+
+ tt->curfreq = freq1;
+
+ freq = freq1 / 160; /* convert the freq. to a nice
to handle value */
+ memset(buffer, 0, sizeof(buffer));
+
+ rest = freq * 10 + 10700; /* I once had understood what is going
on here */
/* maybe some wise guy (friedhelm?) can
comment this stuff */
- i=13;
- p=10;
- temp=102400;
- while (rest!=0)
- {
- if (rest%temp == rest)
+ i = 13;
+ p = 10;
+ temp = 102400;
+ while (rest != 0) {
+ if (rest % temp == rest)
buffer[i] = 0;
- else
- {
+ else {
buffer[i] = 1;
- rest = rest-temp;
+ rest = rest - temp;
}
i--;
p--;
- temp = temp/2;
- }
-
- spin_lock(&lock);
-
- for (i=24;i>-1;i--) /* bit shift the values to the
radiocard */
- {
- if (buffer[i]==1)
- {
- outb(WRT_EN|DATA, BASEPORT);
- outb(WRT_EN|DATA|CLK_ON , BASEPORT);
- outb(WRT_EN|DATA, BASEPORT);
+ temp = temp / 2;
+ }
+
+ for (i = 24; i > -1; i--) { /* bit shift the values to the
radiocard */
+ if (buffer[i] == 1) {
+ outb(WRT_EN | DATA, tt->io);
+ outb(WRT_EN | DATA | CLK_ON, tt->io);
+ outb(WRT_EN | DATA, tt->io);
+ } else {
+ outb(WRT_EN | 0x00, tt->io);
+ outb(WRT_EN | 0x00 | CLK_ON, tt->io);
}
- else
- {
- outb(WRT_EN|0x00, BASEPORT);
- outb(WRT_EN|0x00|CLK_ON , BASEPORT);
- }
- }
- outb(0x00, BASEPORT);
-
- spin_unlock(&lock);
-
- return 0;
-}
-
-static int tt_getsigstr(struct tt_device *dev) /* TODO */
-{
- if (inb(io) & 2) /* bit set = no signal present */
+ }
+ outb(0x00, tt->io);
+
+ mutex_unlock(&tt->lock);
+
+ return 0;
+}
+
+static int tt_getsigstr(struct terratec *tt)
+{
+ if (inb(tt->io) & 2) /* bit set = no signal present */
return 0;
return 1; /* signal present */
}
@@ -213,53 +207,50 @@ static int vidioc_querycap(struct file *
{
strlcpy(v->driver, "radio-terratec", sizeof(v->driver));
strlcpy(v->card, "ActiveRadio", 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;
}
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- struct tt_device *tt = video_drvdata(file);
+ struct terratec *tt = video_drvdata(file);
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*16000);
- v->rangehigh = (108*16000);
+ v->rangelow = 87 * 16000;
+ v->rangehigh = 108 * 16000;
v->rxsubchans = V4L2_TUNER_SUB_MONO;
v->capability = V4L2_TUNER_CAP_LOW;
v->audmode = V4L2_TUNER_MODE_MONO;
- v->signal = 0xFFFF*tt_getsigstr(tt);
+ v->signal = 0xFFFF * tt_getsigstr(tt);
return 0;
}
static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
- if (v->index > 0)
- return -EINVAL;
- return 0;
+ return v->index ? -EINVAL : 0;
}
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct tt_device *tt = video_drvdata(file);
-
- tt->curfreq = f->frequency;
- tt_setfreq(tt, tt->curfreq);
+ struct terratec *tt = video_drvdata(file);
+
+ tt_setfreq(tt, f->frequency);
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct tt_device *tt = video_drvdata(file);
+ struct terratec *tt = video_drvdata(file);
f->type = V4L2_TUNER_RADIO;
f->frequency = tt->curfreq;
@@ -273,8 +264,7 @@ static int vidioc_queryctrl(struct file
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));
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
return 0;
}
}
@@ -284,7 +274,7 @@ static int vidioc_g_ctrl(struct file *fi
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct tt_device *tt = video_drvdata(file);
+ struct terratec *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -303,7 +293,7 @@ static int vidioc_s_ctrl(struct file *fi
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct tt_device *tt = video_drvdata(file);
+ struct terratec *tt = video_drvdata(file);
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
@@ -319,55 +309,46 @@ static int vidioc_s_ctrl(struct file *fi
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 tt_device terratec_unit;
-
-static int terratec_exclusive_open(struct file *file)
-{
- return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
-}
-
-static int terratec_exclusive_release(struct file *file)
-{
- clear_bit(0, &terratec_unit.in_use);
+ return a->index ? -EINVAL : 0;
+}
+
+static int terratec_open(struct file *file)
+{
+ return 0;
+}
+
+static int terratec_release(struct file *file)
+{
return 0;
}
static const struct v4l2_file_operations terratec_fops = {
.owner = THIS_MODULE,
- .open = terratec_exclusive_open,
- .release = terratec_exclusive_release,
+ .open = terratec_open,
+ .release = terratec_release,
.ioctl = video_ioctl2,
};
@@ -386,60 +367,63 @@ static const struct v4l2_ioctl_ops terra
.vidioc_s_input = vidioc_s_input,
};
-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)
{
- if(io==-1)
- {
- printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ struct terratec *tt = &terratec_card;
+ struct v4l2_device *v4l2_dev = &tt->v4l2_dev;
+ int res;
+
+ strlcpy(v4l2_dev->name, "terratec", sizeof(v4l2_dev->name));
+ tt->io = io;
+ if (tt->io == -1) {
+ v4l2_err(v4l2_dev, "you must set an I/O address with
io=0x???\n");
return -EINVAL;
}
- if (!request_region(io, 2, "terratec"))
- {
- printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
+ if (!request_region(tt->io, 2, "terratec")) {
+ v4l2_err(v4l2_dev, "port 0x%x already in use\n", io);
return -EBUSY;
}
- video_set_drvdata(&terratec_radio, &terratec_unit);
-
- spin_lock_init(&lock);
-
- if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) <
0) {
- release_region(io,2);
+ res = v4l2_device_register(NULL, v4l2_dev);
+ if (res < 0) {
+ release_region(tt->io, 2);
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ return res;
+ }
+
+ strlcpy(tt->vdev.name, v4l2_dev->name, sizeof(tt->vdev.name));
+ tt->vdev.v4l2_dev = v4l2_dev;
+ tt->vdev.fops = &terratec_fops;
+ tt->vdev.ioctl_ops = &terratec_ioctl_ops;
+ tt->vdev.release = video_device_release_empty;
+ video_set_drvdata(&tt->vdev, tt);
+
+ mutex_init(&tt->lock);
+
+ if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+ v4l2_device_unregister(&tt->v4l2_dev);
+ release_region(tt->io, 2);
return -EINVAL;
}
- printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n");
+ v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
/* mute card - prevents noisy bootups */
-
- /* this ensures that the volume is all the way down */
- cardWriteVol(0);
- terratec_unit.curvol = 0;
-
- return 0;
-}
-
-MODULE_AUTHOR("R.OFFERMANNS & others");
-MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio
card.");
-MODULE_LICENSE("GPL");
-module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or
0x591)");
-module_param(radio_nr, int, 0);
-
-static void __exit terratec_cleanup_module(void)
-{
- video_unregister_device(&terratec_radio);
- release_region(io,2);
- printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver
unloaded.\n");
+ tt_write_vol(tt, 0);
+ return 0;
+}
+
+static void __exit terratec_exit(void)
+{
+ struct terratec *tt = &terratec_card;
+ struct v4l2_device *v4l2_dev = &tt->v4l2_dev;
+
+ video_unregister_device(&tt->vdev);
+ v4l2_device_unregister(&tt->v4l2_dev);
+ release_region(tt->io, 2);
+ v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver
unloaded.\n");
}
module_init(terratec_init);
-module_exit(terratec_cleanup_module);
-
+module_exit(terratec_exit);
+
---
Patch is available at:
http://linuxtv.org/hg/v4l-dvb/rev/75182c7f36d42b75d6f88ef573ab9874ee925ac5
_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits