From 66457790914e610bc7f372d47794cee4304ba959 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 3 Mar 2009 13:53:13 -0800 Subject: compat: rename struct delayed_work to work_struct on pre-2.6.20 From: Trent Piepho In v2.6.19-rc6-118-g52bad64 struct work_struct was changed to be only for non-delayed work and struct delayed_work was created for delayed work. Instead of putting ifdefs in the drivers, we use compat.h to rename delayed_work to work_struct on pre-2.6.20 kernels. This will only be a problem if some driver decides to create identifiers named both work_struct and delayed_work in the same scope. There is one driver that has something named work_struct and none with anything named delayed_work, so I don't think will be a problem for as long as this compat code sticks around. Priority: normal Signed-off-by: Trent Piepho --- linux/drivers/media/radio/radio-si470x.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index b0a1e5832..a5ba4bf21 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -459,11 +459,7 @@ struct si470x_device { unsigned short registers[RADIO_REGISTER_NUM]; /* RDS receive buffer */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) - struct work_struct work; -#else struct delayed_work work; -#endif wait_queue_head_t read_queue; struct mutex lock; /* buffer locking */ unsigned char *buffer; /* size is always multiple of three */ -- cgit v1.2.3 From 7c7af993cc14112fbcb88c86c94ec1a546a2263b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:45:27 +0100 Subject: radio-aimslab: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 350 ++++++++++++++---------------- 1 file changed, 168 insertions(+), 182 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 384aa928f..57b896968 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -32,15 +32,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("M.Kirkwood"); +MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK_PORT #define CONFIG_RADIO_RTRACK_PORT -1 @@ -48,86 +50,95 @@ static int io = CONFIG_RADIO_RTRACK_PORT; static int radio_nr = -1; -static struct mutex lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; int port; int curvol; unsigned long curfreq; int muted; + int io; + struct mutex lock; }; +static struct rtrack rtrack_card; /* local things */ static void sleep_delay(long n) { /* Sleep nicely for 'n' uS */ - int d=n/msecs_to_jiffies(1000); - if(!d) + int d = n / msecs_to_jiffies(1000); + if (!d) udelay(n); else msleep(jiffies_to_msecs(d)); } -static void rt_decvol(void) +static void rt_decvol(struct rtrack *rt) { - outb(0x58, io); /* volume down + sigstr + on */ + outb(0x58, rt->io); /* volume down + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_incvol(void) +static void rt_incvol(struct rtrack *rt) { - outb(0x98, io); /* volume up + sigstr + on */ + outb(0x98, rt->io); /* volume up + sigstr + on */ sleep_delay(100000); - outb(0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ } -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack *rt) { - dev->muted = 1; - mutex_lock(&lock); - outb(0xd0, io); /* volume steady, off */ - mutex_unlock(&lock); + rt->muted = 1; + mutex_lock(&rt->lock); + outb(0xd0, rt->io); /* volume steady, off */ + mutex_unlock(&rt->lock); } -static int rt_setvol(struct rt_device *dev, int vol) +static int rt_setvol(struct rtrack *rt, int vol) { int i; - mutex_lock(&lock); + mutex_lock(&rt->lock); - if(vol == dev->curvol) { /* requested volume = current */ - if (dev->muted) { /* user is unmuting the card */ - dev->muted = 0; - outb (0xd8, io); /* enable card */ + if (vol == rt->curvol) { /* requested volume = current */ + if (rt->muted) { /* user is unmuting the card */ + rt->muted = 0; + outb(0xd8, rt->io); /* enable card */ } - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } - if(vol == 0) { /* volume = 0 means mute the card */ - outb(0x48, io); /* volume down but still "on" */ + if (vol == 0) { /* volume = 0 means mute the card */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xd0, io); /* volume steady, off */ - dev->curvol = 0; /* track the volume state! */ - mutex_unlock(&lock); + outb(0xd0, rt->io); /* volume steady, off */ + rt->curvol = 0; /* track the volume state! */ + mutex_unlock(&rt->lock); return 0; } - dev->muted = 0; - if(vol > dev->curvol) - for(i = dev->curvol; i < vol; i++) - rt_incvol(); + rt->muted = 0; + if (vol > rt->curvol) + for (i = rt->curvol; i < vol; i++) + rt_incvol(rt); else - for(i = dev->curvol; i > vol; i--) - rt_decvol(); + for (i = rt->curvol; i > vol; i--) + rt_decvol(rt); - dev->curvol = vol; - mutex_unlock(&lock); + rt->curvol = vol; + mutex_unlock(&rt->lock); return 0; } @@ -136,155 +147,137 @@ static int rt_setvol(struct rt_device *dev, int vol) * and bit 4 (+16) is to keep the signal strength meter enabled */ -static void send_0_byte(int port, struct rt_device *dev) +static void send_0_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+ 1, port); /* wr-enable + data low */ - outb_p(128+64+16+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+ 1, rt->io); /* wr-enable + data low */ + outb_p(128+64+16+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */ - outb_p(128+64+16+8+2+1, port); /* clock */ + outb_p(128+64+16+8+ 1, rt->io); /* on + wr-enable + data low */ + outb_p(128+64+16+8+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static void send_1_byte(int port, struct rt_device *dev) +static void send_1_byte(struct rtrack *rt) { - if ((dev->curvol == 0) || (dev->muted)) { - outb_p(128+64+16+4 +1, port); /* wr-enable+data high */ - outb_p(128+64+16+4+2+1, port); /* clock */ + if (rt->curvol == 0 || rt->muted) { + outb_p(128+64+16+4 +1, rt->io); /* wr-enable+data high */ + outb_p(128+64+16+4+2+1, rt->io); /* clock */ } else { - outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */ - outb_p(128+64+16+8+4+2+1, port); /* clock */ + outb_p(128+64+16+8+4 +1, rt->io); /* on+wr-enable+data high */ + outb_p(128+64+16+8+4+2+1, rt->io); /* clock */ } sleep_delay(1000); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack *rt, unsigned long freq) { int i; - /* adapted from radio-aztech.c */ + mutex_lock(&rt->lock); /* Stop other ops interfering */ + + rt->curfreq = freq; /* now uses VIDEO_TUNER_LOW for fine tuning */ freq += 171200; /* Add 10.7 MHz IF */ freq /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); /* Stop other ops interfering */ - - send_0_byte (io, dev); /* 0: LSB of frequency */ + send_0_byte(rt); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (freq & (1 << i)) - send_1_byte (io, dev); + send_1_byte(rt); else - send_0_byte (io, dev); + send_0_byte(rt); - send_0_byte (io, dev); /* 14: test bit - always 0 */ - send_0_byte (io, dev); /* 15: test bit - always 0 */ + send_0_byte(rt); /* 14: test bit - always 0 */ + send_0_byte(rt); /* 15: test bit - always 0 */ - send_0_byte (io, dev); /* 16: band data 0 - always 0 */ - send_0_byte (io, dev); /* 17: band data 1 - always 0 */ - send_0_byte (io, dev); /* 18: band data 2 - always 0 */ - send_0_byte (io, dev); /* 19: time base - always 0 */ + send_0_byte(rt); /* 16: band data 0 - always 0 */ + send_0_byte(rt); /* 17: band data 1 - always 0 */ + send_0_byte(rt); /* 18: band data 2 - always 0 */ + send_0_byte(rt); /* 19: time base - always 0 */ - send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */ + send_0_byte(rt); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(rt); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(rt); /* 23: AM/FM (FM = 1, always) */ - if ((dev->curvol == 0) || (dev->muted)) - outb (0xd0, io); /* volume steady + sigstr */ + if (rt->curvol == 0 || rt->muted) + outb(0xd0, rt->io); /* volume steady + sigstr */ else - outb (0xd8, io); /* volume steady + sigstr + on */ + outb(0xd8, rt->io); /* volume steady + sigstr + on */ - mutex_unlock(&lock); + mutex_unlock(&rt->lock); return 0; } -static int rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack *rt) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ -} + int sig = 1; -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 = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; + mutex_lock(&rt->lock); + if (inb(rt->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&rt->lock); + return sig; +} static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { strlcpy(v->driver, "radio-aimslab", sizeof(v->driver)); strlcpy(v->card, "RadioTrack", 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 rt_device *rt = video_drvdata(file); + struct rtrack *rt = 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*rt_getsigstr(rt); + v->signal = 0xffff * rt_getsigstr(rt); 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 rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -294,14 +287,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, 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, 0xff, 1, 0xff); } return -EINVAL; } @@ -309,14 +299,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = rt->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = rt->curvol * 6554; + ctrl->value = rt->curvol; return 0; } return -EINVAL; @@ -325,33 +315,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 rt_device *rt = video_drvdata(file); + struct rtrack *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) rt_mute(rt); else - rt_setvol(rt,rt->curvol); + rt_setvol(rt, rt->curvol); return 0; case V4L2_CID_AUDIO_VOLUME: - rt_setvol(rt,ctrl->value); + rt_setvol(rt, ctrl->value); return 0; } return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -360,36 +339,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack_exclusive_open(struct file *file) +static int rtrack_open(struct file *file) { - return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack_exclusive_release(struct file *file) +static int rtrack_release(struct file *file) { - clear_bit(0, &rtrack_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack_fops = { .owner = THIS_MODULE, - .open = rtrack_exclusive_open, - .release = rtrack_exclusive_release, + .open = rtrack_open, + .release = rtrack_release, .ioctl = video_ioctl2, }; @@ -408,64 +389,69 @@ static const struct v4l2_ioctl_ops rtrack_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -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) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct rtrack *rt = &rtrack_card; + struct v4l2_device *v4l2_dev = &rt->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack", sizeof(v4l2_dev->name)); + rt->io = io; + + if (rt->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "rtrack")) - { - printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); + if (!request_region(rt->io, 2, "rtrack")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", rt->io); return -EBUSY; } - video_set_drvdata(&rtrack_radio, &rtrack_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(rt->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); + return res; + } + + strlcpy(rt->vdev.name, v4l2_dev->name, sizeof(rt->vdev.name)); + rt->vdev.v4l2_dev = v4l2_dev; + rt->vdev.fops = &rtrack_fops; + rt->vdev.ioctl_ops = &rtrack_ioctl_ops; + rt->vdev.release = video_device_release_empty; + video_set_drvdata(&rt->vdev, rt); - if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); return -EINVAL; } - printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ - mutex_init(&lock); + mutex_init(&rt->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0x48, io); /* volume down but still "on" */ + outb(0x48, rt->io); /* volume down but still "on" */ sleep_delay(2000000); /* make sure it's totally down */ - outb(0xc0, io); /* steady volume, mute card */ - rtrack_unit.curvol = 0; + outb(0xc0, rt->io); /* steady volume, mute card */ return 0; } -MODULE_AUTHOR("M.Kirkwood"); -MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)"); -module_param(radio_nr, int, 0); - -static void __exit cleanup_rtrack_module(void) +static void __exit rtrack_exit(void) { - video_unregister_device(&rtrack_radio); - release_region(io,2); + struct rtrack *rt = &rtrack_card; + + video_unregister_device(&rt->vdev); + v4l2_device_unregister(&rt->v4l2_dev); + release_region(rt->io, 2); } module_init(rtrack_init); -module_exit(cleanup_rtrack_module); +module_exit(rtrack_exit); -- cgit v1.2.3 From e307d0fca84d4a54dd56ab786481a76e40f19d77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:18 +0100 Subject: radio-aztech: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aztech.c | 381 +++++++++++++++---------------- 1 file changed, 182 insertions(+), 199 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index d4d5babcd..dcf53edc2 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -29,34 +29,17 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -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 = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Aztech radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -67,55 +50,64 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_AZTECH_PORT; static int radio_nr = -1; static int radio_wait_time = 1000; -static struct mutex lock; -struct az_device +module_param(io, int, 0); +module_param(radio_nr, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct aztech { - unsigned long in_use; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int stereo; + struct mutex lock; }; +static struct aztech aztech_card; + static int volconvert(int level) { - level>>=14; /* Map 16bits down to 2 bit */ - level&=3; + level >>= 14; /* Map 16bits down to 2 bit */ + level &= 3; /* convert to card-friendly values */ - switch (level) - { - case 0: - return 0; - case 1: - return 1; - case 2: - return 4; - case 3: - return 5; + switch (level) { + case 0: + return 0; + case 1: + return 1; + case 2: + return 4; + case 3: + return 5; } return 0; /* Quieten gcc */ } -static void send_0_byte (struct az_device *dev) +static void send_0_byte(struct aztech *az) { udelay(radio_wait_time); - outb_p(2+volconvert(dev->curvol), io); - outb_p(64+2+volconvert(dev->curvol), io); + outb_p(2 + volconvert(az->curvol), az->io); + outb_p(64 + 2 + volconvert(az->curvol), az->io); } -static void send_1_byte (struct az_device *dev) +static void send_1_byte(struct aztech *az) { udelay (radio_wait_time); - outb_p(128+2+volconvert(dev->curvol), io); - outb_p(128+64+2+volconvert(dev->curvol), io); + outb_p(128 + 2 + volconvert(az->curvol), az->io); + outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); } -static int az_setvol(struct az_device *dev, int vol) +static int az_setvol(struct aztech *az, int vol) { - mutex_lock(&lock); - outb (volconvert(vol), io); - mutex_unlock(&lock); + mutex_lock(&az->lock); + outb(volconvert(vol), az->io); + mutex_unlock(&az->lock); return 0; } @@ -127,116 +119,110 @@ static int az_setvol(struct az_device *dev, int vol) * */ -static int az_getsigstr(struct az_device *dev) +static int az_getsigstr(struct aztech *az) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&az->lock); + return sig; } -static int az_getstereo(struct az_device *dev) +static int az_getstereo(struct aztech *az) { - if (inb(io) & 1) /* bit set = mono */ - return 0; - return 1; /* stereo */ + int stereo = 1; + + mutex_lock(&az->lock); + if (inb(az->io) & 1) /* bit set = mono */ + stereo = 0; + mutex_unlock(&az->lock); + return stereo; } -static int az_setfreq(struct az_device *dev, unsigned long frequency) +static int az_setfreq(struct aztech *az, unsigned long frequency) { int i; + mutex_lock(&az->lock); + + az->curfreq = frequency; frequency += 171200; /* Add 10.7 MHz IF */ frequency /= 800; /* Convert to 50 kHz units */ - mutex_lock(&lock); - - send_0_byte (dev); /* 0: LSB of frequency */ + send_0_byte(az); /* 0: LSB of frequency */ for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ if (frequency & (1 << i)) - send_1_byte (dev); + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_0_byte (dev); /* 14: test bit - always 0 */ - send_0_byte (dev); /* 15: test bit - always 0 */ - send_0_byte (dev); /* 16: band data 0 - always 0 */ - if (dev->stereo) /* 17: stereo (1 to enable) */ - send_1_byte (dev); + send_0_byte(az); /* 14: test bit - always 0 */ + send_0_byte(az); /* 15: test bit - always 0 */ + send_0_byte(az); /* 16: band data 0 - always 0 */ + if (az->stereo) /* 17: stereo (1 to enable) */ + send_1_byte(az); else - send_0_byte (dev); + send_0_byte(az); - send_1_byte (dev); /* 18: band data 1 - unknown */ - send_0_byte (dev); /* 19: time base - always 0 */ - send_0_byte (dev); /* 20: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 21: spacing (1 = 25 kHz) */ - send_0_byte (dev); /* 22: spacing (0 = 25 kHz) */ - send_1_byte (dev); /* 23: AM/FM (FM = 1, always) */ + send_1_byte(az); /* 18: band data 1 - unknown */ + send_0_byte(az); /* 19: time base - always 0 */ + send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ + send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ + send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ /* latch frequency */ - udelay (radio_wait_time); - outb_p(128+64+volconvert(dev->curvol), io); + udelay(radio_wait_time); + outb_p(128 + 64 + volconvert(az->curvol), az->io); - mutex_unlock(&lock); + mutex_unlock(&az->lock); return 0; } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); - strlcpy(v->card, "Aztech Radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); + strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); + strlcpy(v->card, "Aztech Radio", sizeof(v->card)); + 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, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct az_device *az = video_drvdata(file); + struct aztech *az = 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->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(az_getstereo(az)) + v->rangelow = 87 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (az_getstereo(az)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xFFFF*az_getsigstr(az); + v->signal = 0xFFFF * az_getsigstr(az); return 0; } - -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 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->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 0; } static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) @@ -247,113 +233,107 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } - -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); - az->curfreq = f->frequency; - az_setfreq(az, az->curfreq); + az_setfreq(az, f->frequency); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = az->curfreq; - return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +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, 0xff, 1, 0xff); } return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, +static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (az->curvol==0) - ctrl->value=1; - else - ctrl->value=0; - return (0); - case V4L2_CID_AUDIO_VOLUME: - ctrl->value=az->curvol * 6554; - return (0); + case V4L2_CID_AUDIO_MUTE: + if (az->curvol == 0) + ctrl->value = 1; + else + ctrl->value = 0; + return 0; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = az->curvol * 6554; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, +static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct az_device *az = video_drvdata(file); + struct aztech *az = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - az_setvol(az,0); - } else { - az_setvol(az,az->curvol); - } - return (0); - case V4L2_CID_AUDIO_VOLUME: - az_setvol(az,ctrl->value); - return (0); + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) + az_setvol(az, 0); + else + az_setvol(az, az->curvol); + return 0; + case V4L2_CID_AUDIO_VOLUME: + az_setvol(az, ctrl->value); + return 0; } return -EINVAL; } -static struct az_device aztech_unit; - -static int aztech_exclusive_open(struct file *file) +static int aztech_open(struct file *file) { - return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; + return 0; } -static int aztech_exclusive_release(struct file *file) +static int aztech_release(struct file *file) { - clear_bit(0, &aztech_unit.in_use); return 0; } static const struct v4l2_file_operations aztech_fops = { .owner = THIS_MODULE, - .open = aztech_exclusive_open, - .release = aztech_exclusive_release, + .open = aztech_open, + .release = aztech_release, .ioctl = video_ioctl2, }; @@ -372,57 +352,60 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device aztech_radio = { - .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); -MODULE_PARM_DESC(debug,"activates debug info"); - static int __init aztech_init(void) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct aztech *az = &aztech_card; + struct v4l2_device *v4l2_dev = &az->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); + az->io = io; + + if (az->io == -1) { + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); return -EINVAL; } - if (!request_region(io, 2, "aztech")) - { - printk(KERN_ERR "aztech: port 0x%x already in use\n", io); + if (!request_region(az->io, 2, "aztech")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); return -EBUSY; } - mutex_init(&lock); - video_set_drvdata(&aztech_radio, &aztech_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(az->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + mutex_init(&az->lock); + strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); + az->vdev.v4l2_dev = v4l2_dev; + az->vdev.fops = &aztech_fops; + az->vdev.ioctl_ops = &aztech_ioctl_ops; + az->vdev.release = video_device_release_empty; + video_set_drvdata(&az->vdev, az); + + if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(az->io, 2); return -EINVAL; } - printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); + v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); /* mute card - prevents noisy bootups */ - outb (0, io); + outb(0, az->io); return 0; } -MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Aztech radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -module_param(radio_nr, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); - -static void __exit aztech_cleanup(void) +static void __exit aztech_exit(void) { - video_unregister_device(&aztech_radio); - release_region(io,2); + struct aztech *az = &aztech_card; + + video_unregister_device(&az->vdev); + v4l2_device_unregister(&az->v4l2_dev); + release_region(az->io, 2); } module_init(aztech_init); -module_exit(aztech_cleanup); +module_exit(aztech_exit); -- cgit v1.2.3 From cbc98821002e4065b69ce74c892bb9ad2085428f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:48:47 +0100 Subject: radio-cadet: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-cadet.c | 622 ++++++++++++++++---------------- 1 file changed, 307 insertions(+), 315 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 7425aef88..03e76bc74 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -35,363 +35,346 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* V4L2 API defs */ -#include -#include #include #include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" + +MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); +MODULE_LICENSE("GPL"); + +static int io = -1; /* default to isapnp activation */ +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); +module_param(radio_nr, int, 0); + +#define CADET_VERSION KERNEL_VERSION(0, 3, 3) #define RDS_BUFFER 256 #define RDS_RX_FLAG 1 #define MBS_RX_FLAG 2 -#define CADET_VERSION KERNEL_VERSION(0,3,3) - -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 = 0xff, - .step = 1, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } +struct cadet { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int users; + int curtuner; + int tunestat; + int sigstrength; + wait_queue_head_t read_queue; + struct timer_list readtimer; + __u8 rdsin, rdsout, rdsstat; + unsigned char rdsbuf[RDS_BUFFER]; + struct mutex lock; + int reading; }; -static int io=-1; /* default to isapnp activation */ -static int radio_nr = -1; -static int users; -static int curtuner; -static int tunestat; -static int sigstrength; -static wait_queue_head_t read_queue; -static struct timer_list readtimer; -static __u8 rdsin, rdsout, rdsstat; -static unsigned char rdsbuf[RDS_BUFFER]; -static spinlock_t cadet_io_lock; - -static int cadet_probe(void); +static struct cadet cadet_card; /* * Signal Strength Threshold Values * The V4L API spec does not define any particular unit for the signal * strength value. These values are in microvolts of RF at the tuner's input. */ -static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; +static __u16 sigtable[2][4] = { + { 5, 10, 30, 150 }, + { 28, 40, 63, 1000 } +}; #if 0 /* Note: cadet_getrds() is not used at the moment. It will be useful for future extensions, e.g. an ioctl to query RDS reception quality. - Hans J. Koch */ -static int -cadet_getrds(void) +static int cadet_getrds(struct cadet *dev) { - int rds_mbs_stat=0; + int rds_mbs_stat = 0; - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */ - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + outb(inb(dev->io + 1) & 0x7f, dev->io + 1); /* Reset RDS detection */ + mutex_unlock(&dev->lock); msleep(100); - spin_lock(&cadet_io_lock); - outb(3,io); /* Select Decoder Control/Status */ - if((inb(io+1)&0x80)!=0) { + mutex_lock(&dev->lock); + outb(3, dev->io); /* Select Decoder Control/Status */ + if ((inb(dev->io + 1) & 0x80) != 0) rds_mbs_stat |= RDS_RX_FLAG; - } - if((inb(io+1)&0x10)!=0) { + if ((inb(dev->io + 1) & 0x10) != 0) rds_mbs_stat |= MBS_RX_FLAG; - } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return rds_mbs_stat; } #endif -static int -cadet_getstereo(void) +static int cadet_getstereo(struct cadet *dev) { int ret = V4L2_TUNER_SUB_MONO; - if(curtuner != 0) /* Only FM has stereo capability! */ + + if (dev->curtuner != 0) /* Only FM has stereo capability! */ return V4L2_TUNER_SUB_MONO; - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if( (inb(io+1) & 0x40) == 0) + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x40) == 0) ret = V4L2_TUNER_SUB_STEREO; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static unsigned -cadet_gettune(void) +static unsigned cadet_gettune(struct cadet *dev) { - int curvol,i; - unsigned fifo=0; + int curvol, i; + unsigned fifo = 0; /* * Prepare for read */ - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); /* Save current volume/mute setting */ - outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */ - tunestat=0xffff; + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); /* Save current volume/mute setting */ + outb(0x00, dev->io + 1); /* Ensure WRITE-ENABLE is LOW */ + dev->tunestat = 0xffff; /* * Read the shift register */ - for(i=0;i<25;i++) { - fifo=(fifo<<1)|((inb(io+1)>>7)&0x01); - if(i<24) { - outb(0x01,io+1); - tunestat&=inb(io+1); - outb(0x00,io+1); + for (i = 0; i < 25; i++) { + fifo = (fifo << 1) | ((inb(dev->io + 1) >> 7) & 0x01); + if (i < 24) { + outb(0x01, dev->io + 1); + dev->tunestat &= inb(dev->io + 1); + outb(0x00, dev->io + 1); } } /* * Restore volume/mute setting */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); return fifo; } -static unsigned -cadet_getfreq(void) +static unsigned cadet_getfreq(struct cadet *dev) { int i; - unsigned freq=0,test,fifo=0; + unsigned freq = 0, test, fifo = 0; /* * Read current tuning */ - fifo=cadet_gettune(); + fifo = cadet_gettune(dev); /* * Convert to actual frequency */ - if(curtuner==0) { /* FM */ - test=12500; - for(i=0;i<14;i++) { - if((fifo&0x01)!=0) { - freq+=test; - } - test=test<<1; - fifo=fifo>>1; + if (dev->curtuner == 0) { /* FM */ + test = 12500; + for (i = 0; i < 14; i++) { + if ((fifo & 0x01) != 0) + freq += test; + test = test << 1; + fifo = fifo >> 1; } - freq-=10700000; /* IF frequency is 10.7 MHz */ - freq=(freq*16)/1000000; /* Make it 1/16 MHz */ - } - if(curtuner==1) { /* AM */ - freq=((fifo&0x7fff)-2010)*16; + freq -= 10700000; /* IF frequency is 10.7 MHz */ + freq = (freq * 16) / 1000000; /* Make it 1/16 MHz */ } + if (dev->curtuner == 1) /* AM */ + freq = ((fifo & 0x7fff) - 2010) * 16; return freq; } -static void -cadet_settune(unsigned fifo) +static void cadet_settune(struct cadet *dev, unsigned fifo) { int i; unsigned test; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ + outb(7, dev->io); /* Select tuner control */ /* * Write the shift register */ - test=0; - test=(fifo>>23)&0x02; /* Align data for SDO */ - test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ - outb(7,io); /* Select tuner control */ - outb(test,io+1); /* Initialize for write */ - for(i=0;i<25;i++) { - test|=0x01; /* Toggle SCK High */ - outb(test,io+1); - test&=0xfe; /* Toggle SCK Low */ - outb(test,io+1); - fifo=fifo<<1; /* Prepare the next bit */ - test=0x1c|((fifo>>23)&0x02); - outb(test,io+1); + test = 0; + test = (fifo >> 23) & 0x02; /* Align data for SDO */ + test |= 0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */ + outb(7, dev->io); /* Select tuner control */ + outb(test, dev->io + 1); /* Initialize for write */ + for (i = 0; i < 25; i++) { + test |= 0x01; /* Toggle SCK High */ + outb(test, dev->io + 1); + test &= 0xfe; /* Toggle SCK Low */ + outb(test, dev->io + 1); + fifo = fifo << 1; /* Prepare the next bit */ + test = 0x1c | ((fifo >> 23) & 0x02); + outb(test, dev->io + 1); } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } -static void -cadet_setfreq(unsigned freq) +static void cadet_setfreq(struct cadet *dev, unsigned freq) { unsigned fifo; - int i,j,test; + int i, j, test; int curvol; /* * Formulate a fifo command */ - fifo=0; - if(curtuner==0) { /* FM */ - test=102400; - freq=(freq*1000)/16; /* Make it kHz */ - freq+=10700; /* IF is 10700 kHz */ - for(i=0;i<14;i++) { - fifo=fifo<<1; - if(freq>=test) { - fifo|=0x01; - freq-=test; + fifo = 0; + if (dev->curtuner == 0) { /* FM */ + test = 102400; + freq = (freq * 1000) / 16; /* Make it kHz */ + freq += 10700; /* IF is 10700 kHz */ + for (i = 0; i < 14; i++) { + fifo = fifo << 1; + if (freq >= test) { + fifo |= 0x01; + freq -= test; } - test=test>>1; + test = test >> 1; } } - if(curtuner==1) { /* AM */ - fifo=(freq/16)+2010; /* Make it kHz */ - fifo|=0x100000; /* Select AM Band */ + if (dev->curtuner == 1) { /* AM */ + fifo = (freq / 16) + 2010; /* Make it kHz */ + fifo |= 0x100000; /* Select AM Band */ } /* * Save current volume/mute setting */ - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - curvol=inb(io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + curvol = inb(dev->io + 1); + mutex_unlock(&dev->lock); /* * Tune the card */ - for(j=3;j>-1;j--) { - cadet_settune(fifo|(j<<16)); + for (j = 3; j > -1; j--) { + cadet_settune(dev, fifo | (j << 16)); - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - outb(curvol,io+1); - spin_unlock(&cadet_io_lock); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + outb(curvol, dev->io + 1); + mutex_unlock(&dev->lock); msleep(100); - cadet_gettune(); - if((tunestat & 0x40) == 0) { /* Tuned */ - sigstrength=sigtable[curtuner][j]; + cadet_gettune(dev); + if ((dev->tunestat & 0x40) == 0) { /* Tuned */ + dev->sigstrength = sigtable[dev->curtuner][j]; return; } } - sigstrength=0; + dev->sigstrength = 0; } -static int -cadet_getvol(void) +static int cadet_getvol(struct cadet *dev) { int ret = 0; - spin_lock(&cadet_io_lock); + mutex_lock(&dev->lock); - outb(7,io); /* Select tuner control */ - if((inb(io + 1) & 0x20) != 0) + outb(7, dev->io); /* Select tuner control */ + if ((inb(dev->io + 1) & 0x20) != 0) ret = 0xffff; - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); return ret; } -static void -cadet_setvol(int vol) +static void cadet_setvol(struct cadet *dev, int vol) { - spin_lock(&cadet_io_lock); - outb(7,io); /* Select tuner control */ - if(vol>0) - outb(0x20,io+1); + mutex_lock(&dev->lock); + outb(7, dev->io); /* Select tuner control */ + if (vol > 0) + outb(0x20, dev->io + 1); else - outb(0x00,io+1); - spin_unlock(&cadet_io_lock); + outb(0x00, dev->io + 1); + mutex_unlock(&dev->lock); } -static void -cadet_handler(unsigned long data) +static void cadet_handler(unsigned long data) { - /* - * Service the RDS fifo - */ + struct cadet *dev = (void *)data; - if(spin_trylock(&cadet_io_lock)) - { - outb(0x3,io); /* Select RDS Decoder Control */ - if((inb(io+1)&0x20)!=0) { + /* Service the RDS fifo */ + if (mutex_trylock(&dev->lock)) { + outb(0x3, dev->io); /* Select RDS Decoder Control */ + if ((inb(dev->io + 1) & 0x20) != 0) printk(KERN_CRIT "cadet: RDS fifo overflow\n"); - } - outb(0x80,io); /* Select RDS fifo */ - while((inb(io)&0x80)!=0) { - rdsbuf[rdsin]=inb(io+1); - if(rdsin==rdsout) + outb(0x80, dev->io); /* Select RDS fifo */ + while ((inb(dev->io) & 0x80) != 0) { + dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); + if (dev->rdsin == dev->rdsout) printk(KERN_WARNING "cadet: RDS buffer overflow\n"); else - rdsin++; + dev->rdsin++; } - spin_unlock(&cadet_io_lock); + mutex_unlock(&dev->lock); } /* * Service pending read */ - if( rdsin!=rdsout) - wake_up_interruptible(&read_queue); + if (dev->rdsin != dev->rdsout) + wake_up_interruptible(&dev->read_queue); /* * Clean up and exit */ - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)0; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - -static ssize_t -cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) +static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { - int i=0; + struct cadet *dev = video_drvdata(file); unsigned char readbuf[RDS_BUFFER]; - - if(rdsstat==0) { - spin_lock(&cadet_io_lock); - rdsstat=1; - outb(0x80,io); /* Select RDS fifo */ - spin_unlock(&cadet_io_lock); - init_timer(&readtimer); - readtimer.function=cadet_handler; - readtimer.data=(unsigned long)0; - readtimer.expires=jiffies+msecs_to_jiffies(50); - add_timer(&readtimer); + int i = 0; + + if (dev->rdsstat == 0) { + mutex_lock(&dev->lock); + dev->rdsstat = 1; + outb(0x80, dev->io); /* Select RDS fifo */ + mutex_unlock(&dev->lock); + init_timer(&dev->readtimer); + dev->readtimer.function = cadet_handler; + dev->readtimer.data = (unsigned long)dev; + dev->readtimer.expires = jiffies + msecs_to_jiffies(50); + add_timer(&dev->readtimer); } - if(rdsin==rdsout) { + if (dev->rdsin == dev->rdsout) { if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - interruptible_sleep_on(&read_queue); + interruptible_sleep_on(&dev->read_queue); } - while( irdsin != dev->rdsout) + readbuf[i++] = dev->rdsbuf[dev->rdsout++]; - if (copy_to_user(data,readbuf,i)) + if (copy_to_user(data, readbuf, i)) return -EFAULT; return i; } @@ -400,38 +383,40 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - v->capabilities = - V4L2_CAP_TUNER | - V4L2_CAP_READWRITE; + strlcpy(v->driver, "ADS Cadet", sizeof(v->driver)); + strlcpy(v->card, "ADS Cadet", sizeof(v->card)); + strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); v->version = CADET_VERSION; - strcpy(v->driver, "ADS Cadet"); - strcpy(v->card, "ADS Cadet"); + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE; return 0; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct cadet *dev = video_drvdata(file); + v->type = V4L2_TUNER_RADIO; switch (v->index) { case 0: - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_STEREO; v->rangelow = 1400; /* 87.5 MHz */ v->rangehigh = 1728; /* 108.0 MHz */ - v->rxsubchans=cadet_getstereo(); - switch (v->rxsubchans){ + v->rxsubchans = cadet_getstereo(dev); + switch (v->rxsubchans) { case V4L2_TUNER_SUB_MONO: v->audmode = V4L2_TUNER_MODE_MONO; break; case V4L2_TUNER_SUB_STEREO: v->audmode = V4L2_TUNER_MODE_STEREO; break; - default: ; + default: + break; } break; case 1: - strcpy(v->name, "AM"); + strlcpy(v->name, "AM", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_LOW; v->rangelow = 8320; /* 520 kHz */ v->rangehigh = 26400; /* 1650 kHz */ @@ -441,25 +426,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, default: return -EINVAL; } - v->signal = sigstrength; /* We might need to modify scaling of this */ + v->signal = dev->sigstrength; /* We might need to modify scaling of this */ return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if((v->index != 0)&&(v->index != 1)) + struct cadet *dev = video_drvdata(file); + + if (v->index != 0 && v->index != 1) return -EINVAL; - curtuner = v->index; + dev->curtuner = v->index; return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - f->tuner = curtuner; + struct cadet *dev = video_drvdata(file); + + f->tuner = dev->curtuner; f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(); + f->frequency = cadet_getfreq(dev); return 0; } @@ -467,27 +456,26 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct cadet *dev = video_drvdata(file); + if (f->type != V4L2_TUNER_RADIO) return -EINVAL; - if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) + if (dev->curtuner == 0 && (f->frequency < 1400 || f->frequency > 1728)) return -EINVAL; - if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) + if (dev->curtuner == 1 && (f->frequency < 8320 || f->frequency > 26400)) return -EINVAL; - cadet_setfreq(f->frequency); + cadet_setfreq(dev, f->frequency); 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, 0xff, 1, 0xff); } return -EINVAL; } @@ -495,12 +483,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - switch (ctrl->id){ + struct cadet *dev = video_drvdata(file); + + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - ctrl->value = (cadet_getvol() == 0); + ctrl->value = (cadet_getvol(dev) == 0); break; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = cadet_getvol(); + ctrl->value = cadet_getvol(dev); break; default: return -EINVAL; @@ -511,15 +501,17 @@ 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 cadet *dev = video_drvdata(file); + switch (ctrl->id){ case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ if (ctrl->value) - cadet_setvol(0); + cadet_setvol(dev, 0); else - cadet_setvol(0xffff); + cadet_setvol(dev, 0xffff); break; case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(ctrl->value); + cadet_setvol(dev, ctrl->value); break; default: return -EINVAL; @@ -527,16 +519,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return 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->capability = V4L2_AUDCAP_STEREO; - return 0; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -545,43 +527,52 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int -cadet_open(struct file *file) +static int cadet_open(struct file *file) { - users++; - if (1 == users) init_waitqueue_head(&read_queue); + struct cadet *dev = video_drvdata(file); + + dev->users++; + if (1 == dev->users) + init_waitqueue_head(&dev->read_queue); return 0; } -static int -cadet_release(struct file *file) +static int cadet_release(struct file *file) { - users--; - if (0 == users){ - del_timer_sync(&readtimer); - rdsstat=0; + struct cadet *dev = video_drvdata(file); + + dev->users--; + if (0 == dev->users) { + del_timer_sync(&dev->readtimer); + dev->rdsstat = 0; } return 0; } -static unsigned int -cadet_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) { - poll_wait(file,&read_queue,wait); - if(rdsin != rdsout) + struct cadet *dev = video_drvdata(file); + + poll_wait(file, &dev->read_queue, wait); + if (dev->rdsin != dev->rdsout) return POLLIN | POLLRDNORM; return 0; } @@ -611,13 +602,6 @@ static const struct v4l2_ioctl_ops cadet_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -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 static struct pnp_device_id cadet_pnp_devices[] = { @@ -628,7 +612,7 @@ static struct pnp_device_id cadet_pnp_devices[] = { MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices); -static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id) +static int cadet_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { if (!dev) return -ENODEV; @@ -636,13 +620,12 @@ static int cadet_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev if (io > 0) return -EBUSY; - if (!pnp_port_valid(dev, 0)) { + if (!pnp_port_valid(dev, 0)) return -ENODEV; - } io = pnp_port_start(dev, 0); - printk ("radio-cadet: PnP reports device at %#x\n", io); + printk(KERN_INFO "radio-cadet: PnP reports device at %#x\n", io); return io; } @@ -658,23 +641,23 @@ static struct pnp_driver cadet_pnp_driver = { static struct pnp_driver cadet_pnp_driver; #endif -static int cadet_probe(void) +static void cadet_probe(struct cadet *dev) { - static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; + static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e }; int i; - for(i=0;i<8;i++) { - io=iovals[i]; - if (request_region(io, 2, "cadet-probe")) { - cadet_setfreq(1410); - if(cadet_getfreq()==1410) { - release_region(io, 2); - return io; + for (i = 0; i < 8; i++) { + dev->io = iovals[i]; + if (request_region(dev->io, 2, "cadet-probe")) { + cadet_setfreq(dev, 1410); + if (cadet_getfreq(dev) == 1410) { + release_region(dev->io, 2); + return; } - release_region(io, 2); + release_region(dev->io, 2); } } - return -1; + dev->io = -1; } /* @@ -684,59 +667,68 @@ static int cadet_probe(void) static int __init cadet_init(void) { - spin_lock_init(&cadet_io_lock); + struct cadet *dev = &cadet_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; - /* - * If a probe was requested then probe ISAPnP first (safest) - */ + strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); + mutex_init(&dev->lock); + + /* If a probe was requested then probe ISAPnP first (safest) */ if (io < 0) pnp_register_driver(&cadet_pnp_driver); - /* - * If that fails then probe unsafely if probe is requested - */ - if(io < 0) - io = cadet_probe (); + dev->io = io; - /* - * Else we bail out - */ + /* If that fails then probe unsafely if probe is requested */ + if (dev->io < 0) + cadet_probe(dev); - if(io < 0) { + /* Else we bail out */ + if (dev->io < 0) { #ifdef MODULE - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); #endif goto fail; } - if (!request_region(io,2,"cadet")) + if (!request_region(dev->io, 2, "cadet")) goto fail; - if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 2); + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); goto fail; } - printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io); + + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &cadet_fops; + dev->vdev.ioctl_ops = &cadet_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(v4l2_dev); + release_region(dev->io, 2); + goto fail; + } + v4l2_info(v4l2_dev, "ADS Cadet Radio Card at 0x%x\n", dev->io); return 0; fail: pnp_unregister_driver(&cadet_pnp_driver); - return -1; + return -ENODEV; } - - -MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)"); -module_param(radio_nr, int, 0); - -static void __exit cadet_cleanup_module(void) +static void __exit cadet_exit(void) { - video_unregister_device(&cadet_radio); - release_region(io,2); + struct cadet *dev = &cadet_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 2); pnp_unregister_driver(&cadet_pnp_driver); } module_init(cadet_init); -module_exit(cadet_cleanup_module); +module_exit(cadet_exit); -- cgit v1.2.3 From 4a0a23dc3b75fa7ca0bb514cb7ad2a51eb2236eb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:07 +0100 Subject: radio-gemtek-pci: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek-pci.c | 340 +++++++++++++-------------- 1 file changed, 165 insertions(+), 175 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-gemtek-pci.c b/linux/drivers/media/radio/radio-gemtek-pci.c index 7edd3e594..b68e2ba4c 100644 --- a/linux/drivers/media/radio/radio-gemtek-pci.c +++ b/linux/drivers/media/radio/radio-gemtek-pci.c @@ -44,36 +44,28 @@ #include #include #include -#include "compat.h" #include -#include -#include #include - #include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -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 = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +#include +#include +#include +#include +#include "compat.h" -#include -#include +MODULE_AUTHOR("Vladimir Shebordaev "); +MODULE_DESCRIPTION("The video4linux driver for the Gemtek PCI Radio Card"); +MODULE_LICENSE("GPL"); + +static int nr_radio = -1; +static int mx = 1; + +module_param(mx, bool, 0); +MODULE_PARM_DESC(mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not"); +module_param(nr_radio, int, 0); +MODULE_PARM_DESC(nr_radio, "video4linux device number to use"); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) #ifndef PCI_VENDOR_ID_GEMTEK #define PCI_VENDOR_ID_GEMTEK 0x5046 @@ -91,8 +83,11 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define GEMTEK_PCI_RANGE_HIGH (108*16000) #endif -struct gemtek_pci_card { - struct video_device *videodev; +struct gemtek_pci { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + struct pci_dev *pdev; u32 iobase; u32 length; @@ -101,116 +96,133 @@ struct gemtek_pci_card { u8 mute; }; -static int nr_radio = -1; -static unsigned long in_use; +static inline struct gemtek_pci *to_gemtek_pci(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct gemtek_pci, v4l2_dev); +} -static inline u8 gemtek_pci_out( u16 value, u32 port ) +static inline u8 gemtek_pci_out(u16 value, u32 port) { - outw( value, port ); + outw(value, port); return (u8)value; } -#define _b0( v ) *((u8 *)&v) -static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep ) +#define _b0(v) (*((u8 *)&v)) + +static void __gemtek_pci_cmd(u16 value, u32 port, u8 *last_byte, int keep) { - register u8 byte = *last_byte; + u8 byte = *last_byte; - if ( !value ) { - if ( !keep ) + if (!value) { + if (!keep) value = (u16)port; byte &= 0xfd; } else byte |= 2; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte |= 1; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); byte &= 0xfe; - _b0( value ) = byte; - outw( value, port ); + _b0(value) = byte; + outw(value, port); *last_byte = byte; } -static inline void gemtek_pci_nil( u32 port, u8 *last_byte ) +static inline void gemtek_pci_nil(u32 port, u8 *last_byte) { - __gemtek_pci_cmd( 0x00, port, last_byte, false ); + __gemtek_pci_cmd(0x00, port, last_byte, false); } -static inline void gemtek_pci_cmd( u16 cmd, u32 port, u8 *last_byte ) +static inline void gemtek_pci_cmd(u16 cmd, u32 port, u8 *last_byte) { - __gemtek_pci_cmd( cmd, port, last_byte, true ); + __gemtek_pci_cmd(cmd, port, last_byte, true); } -static void gemtek_pci_setfrequency( struct gemtek_pci_card *card, unsigned long frequency ) +static void gemtek_pci_setfrequency(struct gemtek_pci *card, unsigned long frequency) { - register int i; - register u32 value = frequency / 200 + 856; - register u16 mask = 0x8000; + int i; + u32 value = frequency / 200 + 856; + u16 mask = 0x8000; u8 last_byte; u32 port = card->iobase; - last_byte = gemtek_pci_out( 0x06, port ); + mutex_lock(&card->lock); + card->current_frequency = frequency; + last_byte = gemtek_pci_out(0x06, port); i = 0; do { - gemtek_pci_nil( port, &last_byte ); + gemtek_pci_nil(port, &last_byte); i++; - } while ( i < 9 ); + } while (i < 9); i = 0; do { - gemtek_pci_cmd( value & mask, port, &last_byte ); + gemtek_pci_cmd(value & mask, port, &last_byte); mask >>= 1; i++; - } while ( i < 16 ); + } while (i < 16); - outw( 0x10, port ); + outw(0x10, port); + mutex_unlock(&card->lock); } -static inline void gemtek_pci_mute( struct gemtek_pci_card *card ) +static void gemtek_pci_mute(struct gemtek_pci *card) { - outb( 0x1f, card->iobase ); + mutex_lock(&card->lock); + outb(0x1f, card->iobase); card->mute = true; + mutex_unlock(&card->lock); } -static inline void gemtek_pci_unmute( struct gemtek_pci_card *card ) +static void gemtek_pci_unmute(struct gemtek_pci *card) { - if ( card->mute ) { - gemtek_pci_setfrequency( card, card->current_frequency ); + mutex_lock(&card->lock); + if (card->mute) { + gemtek_pci_setfrequency(card, card->current_frequency); card->mute = false; } + mutex_unlock(&card->lock); } -static inline unsigned int gemtek_pci_getsignal( struct gemtek_pci_card *card ) +static int gemtek_pci_getsignal(struct gemtek_pci *card) { - return ( inb( card->iobase ) & 0x08 ) ? 0 : 1; + int sig; + + mutex_lock(&card->lock); + sig = (inb(card->iobase) & 0x08) ? 0 : 1; + mutex_unlock(&card->lock); + return sig; } static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct gemtek_pci *card = video_drvdata(file); + strlcpy(v->driver, "radio-gemtek-pci", sizeof(v->driver)); strlcpy(v->card, "GemTek PCI Radio", sizeof(v->card)); - sprintf(v->bus_info, "ISA"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(card->pdev)); 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 gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = 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 = GEMTEK_PCI_RANGE_LOW; v->rangehigh = GEMTEK_PCI_RANGE_HIGH; @@ -224,21 +236,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, 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 gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); - if ( (f->frequency < GEMTEK_PCI_RANGE_LOW) || - (f->frequency > GEMTEK_PCI_RANGE_HIGH) ) + if (f->frequency < GEMTEK_PCI_RANGE_LOW || + f->frequency > GEMTEK_PCI_RANGE_HIGH) return -EINVAL; gemtek_pci_setfrequency(card, f->frequency); - card->current_frequency = f->frequency; card->mute = false; return 0; } @@ -246,7 +255,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 gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = card->current_frequency; @@ -256,13 +265,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, 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, 65535, 65535); } return -EINVAL; } @@ -270,7 +277,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 gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -289,7 +296,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 gemtek_pci_card *card = video_drvdata(file); + struct gemtek_pci *card = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -308,17 +315,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -327,17 +323,22 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } enum { @@ -355,25 +356,22 @@ static struct pci_device_id gemtek_pci_id[] = { 0 } }; -MODULE_DEVICE_TABLE( pci, gemtek_pci_id ); - -static int mx = 1; +MODULE_DEVICE_TABLE(pci, gemtek_pci_id); -static int gemtek_pci_exclusive_open(struct file *file) +static int gemtek_pci_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_pci_exclusive_release(struct file *file) +static int gemtek_pci_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_pci_fops = { .owner = THIS_MODULE, - .open = gemtek_pci_exclusive_open, - .release = gemtek_pci_exclusive_release, + .open = gemtek_pci_open, + .release = gemtek_pci_release, .ioctl = video_ioctl2, }; @@ -392,114 +390,106 @@ static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device vdev_template = { - .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 ) +static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { - struct gemtek_pci_card *card; - struct video_device *devradio; + struct gemtek_pci *card; + struct v4l2_device *v4l2_dev; + int res; - if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); + card = kzalloc(sizeof(struct gemtek_pci), GFP_KERNEL); + if (card == NULL) { + dev_err(&pdev->dev, "out of memory\n"); return -ENOMEM; } - if ( pci_enable_device( pci_dev ) ) - goto err_pci; + v4l2_dev = &card->v4l2_dev; + mutex_init(&card->lock); + card->pdev = pdev; - card->iobase = pci_resource_start( pci_dev, 0 ); - card->length = pci_resource_len( pci_dev, 0 ); + strlcpy(v4l2_dev->name, "gemtek_pci", sizeof(v4l2_dev->name)); - if ( request_region( card->iobase, card->length, card_names[pci_id->driver_data] ) == NULL ) { - printk( KERN_ERR "gemtek_pci: i/o port already in use\n" ); - goto err_pci; + res = v4l2_device_register(&pdev->dev, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + kfree(card); + return res; } - pci_set_drvdata( pci_dev, card ); + if (pci_enable_device(pdev)) + goto err_pci; - if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) { - printk( KERN_ERR "gemtek_pci: out of memory\n" ); - goto err_video; + card->iobase = pci_resource_start(pdev, 0); + card->length = pci_resource_len(pdev, 0); + + if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { + v4l2_err(v4l2_dev, "i/o port already in use\n"); + goto err_pci; } - *devradio = vdev_template; - if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) { - kfree( devradio ); + strlcpy(card->vdev.name, v4l2_dev->name, sizeof(card->vdev.name)); + card->vdev.v4l2_dev = v4l2_dev; + card->vdev.fops = &gemtek_pci_fops; + card->vdev.ioctl_ops = &gemtek_pci_ioctl_ops; + card->vdev.release = video_device_release_empty; + video_set_drvdata(&card->vdev, card); + + if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0) goto err_video; - } - card->videodev = devradio; - video_set_drvdata(devradio, card); - gemtek_pci_mute( card ); + gemtek_pci_mute(card); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - pci_dev->revision, card->iobase, card->iobase + card->length - 1 ); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22) + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + pdev->revision, card->iobase, card->iobase + card->length - 1); #else - printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", - v4l_compat_pci_rev(pci_dev), card->iobase, - card->iobase + card->length - 1 ); + v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", + v4l_compat_pci_rev(pdev), card->iobase, + card->iobase + card->length - 1); #endif return 0; err_video: - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); err_pci: - kfree( card ); + v4l2_device_unregister(v4l2_dev); + kfree(card); return -ENODEV; } -static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev ) +static void __devexit gemtek_pci_remove(struct pci_dev *pdev) { - struct gemtek_pci_card *card = pci_get_drvdata( pci_dev ); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct gemtek_pci *card = to_gemtek_pci(v4l2_dev); - video_unregister_device( card->videodev ); - kfree( card->videodev ); + video_unregister_device(&card->vdev); + v4l2_device_unregister(v4l2_dev); - release_region( card->iobase, card->length ); + release_region(card->iobase, card->length); - if ( mx ) - gemtek_pci_mute( card ); + if (mx) + gemtek_pci_mute(card); - kfree( card ); - - pci_set_drvdata( pci_dev, NULL ); + kfree(card); } -static struct pci_driver gemtek_pci_driver = -{ +static struct pci_driver gemtek_pci_driver = { .name = "gemtek_pci", .id_table = gemtek_pci_id, .probe = gemtek_pci_probe, .remove = __devexit_p(gemtek_pci_remove), }; -static int __init gemtek_pci_init_module( void ) +static int __init gemtek_pci_init(void) { - return pci_register_driver( &gemtek_pci_driver ); + return pci_register_driver(&gemtek_pci_driver); } -static void __exit gemtek_pci_cleanup_module( void ) +static void __exit gemtek_pci_exit(void) { pci_unregister_driver(&gemtek_pci_driver); } -MODULE_AUTHOR( "Vladimir Shebordaev " ); -MODULE_DESCRIPTION( "The video4linux driver for the Gemtek PCI Radio Card" ); -MODULE_LICENSE("GPL"); - -module_param(mx, bool, 0); -MODULE_PARM_DESC( mx, "single digit: 1 - turn off the turner upon module exit (default), 0 - do not" ); -module_param(nr_radio, int, 0); -MODULE_PARM_DESC( nr_radio, "video4linux device number to use"); - -module_init( gemtek_pci_init_module ); -module_exit( gemtek_pci_cleanup_module ); - +module_init(gemtek_pci_init); +module_exit(gemtek_pci_exit); -- cgit v1.2.3 From 48a5a5d79f817cd2646721c2deaf2a357a5f4f7c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:50:42 +0100 Subject: radio-gemtek: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-gemtek.c | 399 +++++++++++++++---------------- 1 file changed, 188 insertions(+), 211 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-gemtek.c b/linux/drivers/media/radio/radio-gemtek.c index a1ae890c8..0cb1cb0a1 100644 --- a/linux/drivers/media/radio/radio-gemtek.c +++ b/linux/drivers/media/radio/radio-gemtek.c @@ -20,17 +20,16 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ +#include /* for KERNEL_VERSION MACRO */ +#include +#include /* outb, outb_p */ +#include /* copy to/from user */ #include -#include -#include +#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,3) -#define RADIO_BANNER "GemTek Radio card driver: v0.0.3" +#define RADIO_VERSION KERNEL_VERSION(0, 0, 3) /* * Module info. @@ -58,7 +57,6 @@ 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 " @@ -113,12 +111,19 @@ module_param(radio_nr, int, 0444); #define SHORT_DELAY 5 /* usec */ #define LONG_DELAY 75 /* usec */ -struct gemtek_device { +struct gemtek { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; unsigned long lastfreq; int muted; + int verified; + int io; u32 bu2614data; }; +static struct gemtek gemtek_card; + #define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ #define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ #define BU2614_VOID_BITS 4 /* unused */ @@ -154,10 +159,6 @@ struct gemtek_device { #define BU2614_FMUN_MASK MKMASK(FMUN) #define BU2614_TEST_MASK MKMASK(TEST) -static struct gemtek_device gemtek_unit; - -static spinlock_t lock; - /* * Set data which will be sent to BU2614FS. */ @@ -167,33 +168,33 @@ static spinlock_t lock; /* * Transmit settings to BU2614FS over GemTek IC. */ -static void gemtek_bu2614_transmit(struct gemtek_device *dev) +static void gemtek_bu2614_transmit(struct gemtek *gt) { int i, bit, q, mute; - spin_lock(&lock); + mutex_lock(>->lock); - mute = dev->muted ? GEMTEK_MT : 0x00; + mute = gt->muted ? GEMTEK_MT : 0x00; - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) { - bit = (q & 1) ? GEMTEK_DA : 0; - outb_p(mute | GEMTEK_CE | bit, io); - udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io); - udelay(SHORT_DELAY); + for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) { + bit = (q & 1) ? GEMTEK_DA : 0; + outb_p(mute | GEMTEK_CE | bit, gt->io); + udelay(SHORT_DELAY); + outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io); + udelay(SHORT_DELAY); } - outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(SHORT_DELAY); - outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); + outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io); udelay(LONG_DELAY); - spin_unlock(&lock); + mutex_unlock(>->lock); } /* @@ -207,107 +208,109 @@ static unsigned long gemtek_convfreq(unsigned long freq) /* * Set FM-frequency. */ -static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) +static void gemtek_setfreq(struct gemtek *gt, unsigned long freq) { - - if (keepmuted && hardmute && dev->muted) + if (keepmuted && hardmute && gt->muted) return; - if (freq < GEMTEK_LOWFREQ) - freq = GEMTEK_LOWFREQ; - else if (freq > GEMTEK_HIGHFREQ) - freq = GEMTEK_HIGHFREQ; + freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ); - dev->lastfreq = freq; - dev->muted = 0; + gt->lastfreq = freq; + gt->muted = 0; - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); - gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq)); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); + gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq)); - gemtek_bu2614_transmit(dev); + gemtek_bu2614_transmit(gt); } /* * Set mute flag. */ -static void gemtek_mute(struct gemtek_device *dev) +static void gemtek_mute(struct gemtek *gt) { int i; - dev->muted = 1; + + gt->muted = 1; if (hardmute) { /* Turn off PLL, disable data output */ - gemtek_bu2614_set(dev, BU2614_PORT, 0); - gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */ - gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ - gemtek_bu2614_set(dev, BU2614_SWAL, 0); - gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */ - gemtek_bu2614_set(dev, BU2614_TEST, 0); - gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF); - gemtek_bu2614_set(dev, BU2614_FREQ, 0); - gemtek_bu2614_transmit(dev); - } else { - spin_lock(&lock); + gemtek_bu2614_set(gt, BU2614_PORT, 0); + gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */ + gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */ + gemtek_bu2614_set(gt, BU2614_SWAL, 0); + gemtek_bu2614_set(gt, BU2614_FMUN, 0); /* GT bit off */ + gemtek_bu2614_set(gt, BU2614_TEST, 0); + gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF); + gemtek_bu2614_set(gt, BU2614_FREQ, 0); + gemtek_bu2614_transmit(gt); + return; + } - /* Read bus contents (CE, CK and DA). */ - i = inb_p(io); - /* Write it back with mute flag set. */ - outb_p((i >> 5) | GEMTEK_MT, io); - udelay(SHORT_DELAY); + mutex_lock(>->lock); - spin_unlock(&lock); - } + /* Read bus contents (CE, CK and DA). */ + i = inb_p(gt->io); + /* Write it back with mute flag set. */ + outb_p((i >> 5) | GEMTEK_MT, gt->io); + udelay(SHORT_DELAY); + + mutex_unlock(>->lock); } /* * Unset mute flag. */ -static void gemtek_unmute(struct gemtek_device *dev) +static void gemtek_unmute(struct gemtek *gt) { int i; - dev->muted = 0; + gt->muted = 0; if (hardmute) { /* Turn PLL back on. */ - gemtek_setfreq(dev, dev->lastfreq); - } else { - spin_lock(&lock); + gemtek_setfreq(gt, gt->lastfreq); + return; + } + mutex_lock(>->lock); - i = inb_p(io); - outb_p(i >> 5, io); - udelay(SHORT_DELAY); + i = inb_p(gt->io); + outb_p(i >> 5, gt->io); + udelay(SHORT_DELAY); - spin_unlock(&lock); - } + mutex_unlock(>->lock); } /* * Get signal strength (= stereo status). */ -static inline int gemtek_getsigstr(void) +static inline int gemtek_getsigstr(struct gemtek *gt) { - return inb_p(io) & GEMTEK_NS ? 0 : 1; + int sig; + + mutex_lock(>->lock); + sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1; + mutex_unlock(>->lock); + return sig; } /* * Check if requested card acts like GemTek Radio card. */ -static int gemtek_verify(int port) +static int gemtek_verify(struct gemtek *gt, int port) { - static int verified = -1; int i, q; - if (verified == port) + if (gt->verified == port) return 1; - spin_lock(&lock); + mutex_lock(>->lock); q = inb_p(port); /* Read bus contents before probing. */ /* Try to turn on CE, CK and DA respectively and check if card responds @@ -317,15 +320,15 @@ static int gemtek_verify(int port) udelay(SHORT_DELAY); if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { - spin_unlock(&lock); + mutex_unlock(>->lock); return 0; } } outb_p(q >> 5, port); /* Write bus contents back. */ udelay(SHORT_DELAY); - spin_unlock(&lock); - verified = port; + mutex_unlock(>->lock); + gt->verified = port; return 1; } @@ -333,83 +336,61 @@ static int gemtek_verify(int port) /* * Automatic probing for card. */ -static int gemtek_probe(void) +static int gemtek_probe(struct gemtek *gt) { + struct v4l2_device *v4l2_dev = >->v4l2_dev; int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; int i; if (!probe) { - printk(KERN_INFO "Automatic device probing disabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing disabled.\n"); return -1; } - printk(KERN_INFO "Automatic device probing enabled.\n"); + v4l2_info(v4l2_dev, "Automatic device probing enabled.\n"); for (i = 0; i < ARRAY_SIZE(ioports); ++i) { - printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]); + v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]); if (!request_region(ioports[i], 1, "gemtek-probe")) { - printk(KERN_WARNING "I/O port 0x%x busy!\n", + v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n", ioports[i]); continue; } - if (gemtek_verify(ioports[i])) { - printk(KERN_INFO "Card found from I/O port " + if (gemtek_verify(gt, ioports[i])) { + v4l2_info(v4l2_dev, "Card found from I/O port " "0x%x!\n", ioports[i]); release_region(ioports[i], 1); - - io = ioports[i]; - return io; + gt->io = ioports[i]; + return gt->io; } release_region(ioports[i], 1); } - printk(KERN_ERR "Automatic probing failed!\n"); - + v4l2_err(v4l2_dev, "Automatic probing failed!\n"); return -1; } /* * Video 4 Linux stuff. */ - -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 = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - -static int gemtek_exclusive_open(struct file *file) +static int gemtek_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int gemtek_exclusive_release(struct file *file) +static int gemtek_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations gemtek_fops = { .owner = THIS_MODULE, - .open = gemtek_exclusive_open, - .release = gemtek_exclusive_release, + .open = gemtek_open, + .release = gemtek_release, .ioctl = video_ioctl2, }; @@ -418,23 +399,25 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); strlcpy(v->card, "GemTek", 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 gemtek *gt = 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 = GEMTEK_LOWFREQ; v->rangehigh = GEMTEK_HIGHFREQ; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; - v->signal = 0xffff * gemtek_getsigstr(); + v->signal = 0xffff * gemtek_getsigstr(gt); if (v->signal) { v->audmode = V4L2_TUNER_MODE_STEREO; v->rxsubchans = V4L2_TUNER_SUB_STEREO; @@ -442,65 +425,56 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) v->audmode = V4L2_TUNER_MODE_MONO; v->rxsubchans = V4L2_TUNER_SUB_MONO; } - 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 != 0) ? -EINVAL : 0; } -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 gemtek_device *rt = video_drvdata(file); - - gemtek_setfreq(rt, f->frequency); + struct gemtek *gt = video_drvdata(file); + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = gt->lastfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); - f->type = V4L2_TUNER_RADIO; - f->frequency = rt->lastfreq; + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + gemtek_setfreq(gt, f->frequency); 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, 0); + default: + return -EINVAL; } - return -EINVAL; } static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = rt->muted; - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (rt->muted) - ctrl->value = 0; - else - ctrl->value = 65535; + ctrl->value = gt->muted; return 0; } return -EINVAL; @@ -509,35 +483,19 @@ 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 gemtek_device *rt = video_drvdata(file); + struct gemtek *gt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - gemtek_mute(rt); - else - gemtek_unmute(rt); - return 0; - case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value) - gemtek_unmute(rt); + gemtek_mute(gt); else - gemtek_mute(rt); + gemtek_unmute(gt); return 0; } return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -546,16 +504,20 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return (i != 0) ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return (a->index != 0) ? -EINVAL : 0; } static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { @@ -573,62 +535,73 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl }; -static struct video_device gemtek_radio = { - .name = "GemTek Radio card", - .fops = &gemtek_fops, - .ioctl_ops = &gemtek_ioctl_ops, - .release = video_device_release_empty, -}; - /* * Initialization / cleanup related stuff. */ -/* - * Initilize card. - */ static int __init gemtek_init(void) { - printk(KERN_INFO RADIO_BANNER "\n"); + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + int res; - spin_lock_init(&lock); + strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name)); - gemtek_probe(); - if (io) { - if (!request_region(io, 1, "gemtek")) { - printk(KERN_ERR "I/O port 0x%x already in use.\n", io); + v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n"); + + mutex_init(>->lock); + + gt->verified = -1; + gt->io = io; + gemtek_probe(gt); + if (gt->io) { + if (!request_region(gt->io, 1, "gemtek")) { + v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io); return -EBUSY; } - if (!gemtek_verify(io)) - printk(KERN_WARNING "Card at I/O port 0x%x does not " + if (!gemtek_verify(gt, gt->io)) + v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not " "respond properly, check your " - "configuration.\n", io); + "configuration.\n", gt->io); else - printk(KERN_INFO "Using I/O port 0x%x.\n", io); + v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io); } else if (probe) { - printk(KERN_ERR "Automatic probing failed and no " + v4l2_err(v4l2_dev, "Automatic probing failed and no " "fixed I/O port defined.\n"); return -ENODEV; } else { - printk(KERN_ERR "Automatic probing disabled but no fixed " + v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed " "I/O port defined."); return -EINVAL; } - video_set_drvdata(&gemtek_radio, &gemtek_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + release_region(gt->io, 1); + return res; + } - if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 1); + strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name)); + gt->vdev.v4l2_dev = v4l2_dev; + gt->vdev.fops = &gemtek_fops; + gt->vdev.ioctl_ops = &gemtek_ioctl_ops; + gt->vdev.release = video_device_release_empty; + video_set_drvdata(>->vdev, gt); + + if (video_register_device(>->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(gt->io, 1); return -EBUSY; } /* Set defaults */ - gemtek_unit.lastfreq = GEMTEK_LOWFREQ; - gemtek_unit.bu2614data = 0; + gt->lastfreq = GEMTEK_LOWFREQ; + gt->bu2614data = 0; if (initmute) - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); return 0; } @@ -638,15 +611,19 @@ static int __init gemtek_init(void) */ static void __exit gemtek_exit(void) { + struct gemtek *gt = &gemtek_card; + struct v4l2_device *v4l2_dev = >->v4l2_dev; + if (shutdown) { hardmute = 1; /* Turn off PLL */ - gemtek_mute(&gemtek_unit); + gemtek_mute(gt); } else { - printk(KERN_INFO "Module unloaded but card not muted!\n"); + v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n"); } - video_unregister_device(&gemtek_radio); - release_region(io, 1); + video_unregister_device(>->vdev); + v4l2_device_unregister(>->v4l2_dev); + release_region(gt->io, 1); } module_init(gemtek_init); -- cgit v1.2.3 From a6922f733d048625fdb478ea22a1964acad3ef58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:08 +0100 Subject: radio-maestro: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maestro.c | 338 +++++++++++++++--------------- 1 file changed, 164 insertions(+), 174 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-maestro.c b/linux/drivers/media/radio/radio-maestro.c index 7442be614..b35092f30 100644 --- a/linux/drivers/media/radio/radio-maestro.c +++ b/linux/drivers/media/radio/radio-maestro.c @@ -22,28 +22,24 @@ #include #include #include -#include -#include +#include /* for KERNEL_VERSION MACRO */ #include #include -#include +#include +#include +#include #include #include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,6) -#define DRIVER_VERSION "0.06" +MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); +MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); +MODULE_LICENSE("GPL"); -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, - } -}; +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 6) +#define DRIVER_VERSION "0.06" #define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */ @@ -73,62 +69,27 @@ static struct v4l2_queryctrl radio_qctrl[] = { #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int radio_nr = -1; -module_param(radio_nr, int, 0); +struct maestro { + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; + struct mutex lock; -static unsigned long in_use; - -static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent); + u16 io; /* base of Maestro card radio io (GPIO_DATA)*/ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ +}; -static int maestro_exclusive_open(struct file *file) +static inline struct maestro *to_maestro(struct v4l2_device *v4l2_dev) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return container_of(v4l2_dev, struct maestro, v4l2_dev); } -static int maestro_exclusive_release(struct file *file) +static u32 radio_bits_get(struct maestro *dev) { - clear_bit(0, &in_use); - return 0; -} - -static void maestro_remove(struct pci_dev *pdev); - -static struct pci_device_id maestro_r_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), - .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, - .class_mask = 0xffff00 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); - -static struct pci_driver maestro_r_driver = { - .name = "maestro_radio", - .id_table = maestro_r_pci_tbl, - .probe = maestro_probe, - .remove = __devexit_p(maestro_remove), -}; - -static const struct v4l2_file_operations maestro_fops = { - .owner = THIS_MODULE, - .open = maestro_exclusive_open, - .release = maestro_exclusive_release, - .ioctl = video_ioctl2, -}; - -struct radio_device { - u16 io, /* base of Maestro card radio io (GPIO_DATA)*/ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ -}; - -static u32 radio_bits_get(struct radio_device *dev) -{ - register u16 io=dev->io, l, rdata; - register u32 data=0; + u16 io = dev->io, l, rdata; + u32 data = 0; u16 omask; omask = inw(io + IO_MASK); @@ -136,25 +97,23 @@ static u32 radio_bits_get(struct radio_device *dev) outw(0, io); udelay(16); - for (l=24;l--;) { + for (l = 24; l--;) { outw(STR_CLK, io); /* HI state */ udelay(2); - if(!l) + if (!l) dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff; outw(0, io); /* LO state */ udelay(2); data <<= 1; /* shift data */ rdata = inw(io); - if(!l) - dev->stereo = rdata & STR_MOST ? - 0 : 1; - else - if(rdata & STR_DATA) - data++; + if (!l) + dev->stereo = (rdata & STR_MOST) ? 0 : 1; + else if (rdata & STR_DATA) + data++; udelay(2); } - if(dev->muted) + if (dev->muted) outw(STR_WREN, io); udelay(4); @@ -163,18 +122,18 @@ static u32 radio_bits_get(struct radio_device *dev) return data & 0x3ffe; } -static void radio_bits_set(struct radio_device *dev, u32 data) +static void radio_bits_set(struct maestro *dev, u32 data) { - register u16 io=dev->io, l, bits; + u16 io = dev->io, l, bits; u16 omask, odir; omask = inw(io + IO_MASK); - odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); + odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN); outw(odir | STR_DATA, io + IO_DIR); outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK); udelay(16); - for (l=25;l;l--) { - bits = ((data >> 18) & STR_DATA) | STR_WREN ; + for (l = 25; l; l--) { + bits = ((data >> 18) & STR_DATA) | STR_WREN; data <<= 1; /* shift data */ outw(bits, io); /* start strobe */ udelay(2); @@ -184,7 +143,7 @@ static void radio_bits_set(struct radio_device *dev, u32 data) udelay(4); } - if(!dev->muted) + if (!dev->muted) outw(0, io); udelay(4); @@ -196,78 +155,79 @@ static void radio_bits_set(struct radio_device *dev, u32 data) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { + struct maestro *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maestro", sizeof(v->driver)); strlcpy(v->card, "Maestro Radio", sizeof(v->card)); - sprintf(v->bus_info, "PCI"); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); 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 radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - (void)radio_bits_get(card); + mutex_lock(&dev->lock); + radio_bits_get(dev); - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if(card->stereo) + if (dev->stereo) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = card->tuned; + v->signal = dev->tuned; + mutex_unlock(&dev->lock); 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 radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; - radio_bits_set(card, FREQ2BITS(f->frequency)); + mutex_lock(&dev->lock); + radio_bits_set(dev, FREQ2BITS(f->frequency)); + mutex_unlock(&dev->lock); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = BITS2FREQ(radio_bits_get(card)); + mutex_lock(&dev->lock); + f->frequency = BITS2FREQ(radio_bits_get(dev)); + mutex_unlock(&dev->lock); 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); } return -EINVAL; } @@ -275,11 +235,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maestro *dev = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = card->muted; + ctrl->value = dev->muted; return 0; } return -EINVAL; @@ -288,56 +248,85 @@ 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 radio_device *card = video_drvdata(file); - register u16 io = card->io; - register u16 omask = inw(io + IO_MASK); + struct maestro *dev = video_drvdata(file); + u16 io = dev->io; + u16 omask; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + omask = inw(io + IO_MASK); outw(~STR_WREN, io + IO_MASK); - outw((card->muted = ctrl->value ) ? - STR_WREN : 0, io); + dev->muted = ctrl->value; + outw(dev->muted ? STR_WREN : 0, io); udelay(4); outw(omask, io + IO_MASK); msleep(125); + mutex_unlock(&dev->lock); 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) +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) { - *i = 0; - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +static int maestro_open(struct file *file) { - if (i != 0) - return -EINVAL; return 0; } -static int vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *a) +static int maestro_release(struct file *file) { - if (a->index != 0) - return -EINVAL; return 0; } -static u16 __devinit radio_power_on(struct radio_device *dev) +static const struct v4l2_file_operations maestro_fops = { + .owner = THIS_MODULE, + .open = maestro_open, + .release = maestro_release, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops maestro_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .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, +}; + +static u16 __devinit radio_power_on(struct maestro *dev) { register u16 io = dev->io; register u32 ofreq; @@ -361,33 +350,11 @@ static u16 __devinit radio_power_on(struct radio_device *dev) return (ofreq == radio_bits_get(dev)); } -static const struct v4l2_ioctl_ops maestro_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .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, -}; - -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, const struct pci_device_id *ent) { - struct radio_device *radio_unit; - struct video_device *maestro_radio_inst; + struct maestro *dev; + struct v4l2_device *v4l2_dev; int retval; retval = pci_enable_device(pdev); @@ -398,46 +365,53 @@ static int __devinit maestro_probe(struct pci_dev *pdev, retval = -ENOMEM; - radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL); - if (radio_unit == NULL) { + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { dev_err(&pdev->dev, "not enough memory\n"); goto err; } - radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; - maestro_radio_inst = video_device_alloc(); - if (maestro_radio_inst == NULL) { - dev_err(&pdev->dev, "not enough memory\n"); + strlcpy(v4l2_dev->name, "maestro", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); goto errfr; } - memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio)); - video_set_drvdata(maestro_radio_inst, radio_unit); - pci_set_drvdata(pdev, maestro_radio_inst); + dev->io = pci_resource_start(pdev, 0) + GPIO_DATA; - retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maestro_fops; + dev->vdev.ioctl_ops = &maestro_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr); if (retval) { - printk(KERN_ERR "can't register video device!\n"); + v4l2_err(v4l2_dev, "can't register video device!\n"); goto errfr1; } - if (!radio_power_on(radio_unit)) { + if (!radio_power_on(dev)) { retval = -EIO; goto errunr; } - dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " " - __DATE__ "\n"); - dev_info(&pdev->dev, "radio chip initialized\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); return 0; errunr: - video_unregister_device(maestro_radio_inst); + video_unregister_device(&dev->vdev); errfr1: - video_device_release(maestro_radio_inst); + v4l2_device_unregister(v4l2_dev); errfr: - kfree(radio_unit); + kfree(dev); err: return retval; @@ -445,11 +419,31 @@ err: static void __devexit maestro_remove(struct pci_dev *pdev) { - struct video_device *vdev = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maestro *dev = to_maestro(v4l2_dev); - video_unregister_device(vdev); + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); } +static struct pci_device_id maestro_r_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl); + +static struct pci_driver maestro_r_driver = { + .name = "maestro_radio", + .id_table = maestro_r_pci_tbl, + .probe = maestro_probe, + .remove = __devexit_p(maestro_remove), +}; + static int __init maestro_radio_init(void) { int retval = pci_register_driver(&maestro_r_driver); @@ -467,7 +461,3 @@ static void __exit maestro_radio_exit(void) module_init(maestro_radio_init); module_exit(maestro_radio_exit); - -MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); -MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 8dcdc9fab2af7f5123f3660b04f2ca497d6ec098 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:51:33 +0100 Subject: radio-maxiradio: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-maxiradio.c | 375 ++++++++++++++-------------- 1 file changed, 186 insertions(+), 189 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-maxiradio.c b/linux/drivers/media/radio/radio-maxiradio.c index cb9d07bc7..fa2c5f1ef 100644 --- a/linux/drivers/media/radio/radio-maxiradio.c +++ b/linux/drivers/media/radio/radio-maxiradio.c @@ -37,39 +37,34 @@ #include #include #include -#include -#include #include - #include #include -#include +#include /* for KERNEL_VERSION MACRO */ +#include +#include +#include #include #include "compat.h" +MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); +MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); +MODULE_LICENSE("GPL"); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +static int debug; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + #define DRIVER_VERSION "0.77" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,7,7) - -static struct video_device maxiradio_radio; - -#define dprintk(num, fmt, arg...) \ - do { \ - if (maxiradio_radio.debug >= num) \ - printk(KERN_DEBUG "%s: " fmt, \ - maxiradio_radio.name, ## arg); } while (0) - -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, - } -}; +#define RADIO_VERSION KERNEL_VERSION(0, 7, 7) + +#define dprintk(dev, num, fmt, arg...) \ + v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) #ifndef PCI_VENDOR_ID_GUILLEMOT #define PCI_VENDOR_ID_GUILLEMOT 0x5046 @@ -81,90 +76,70 @@ static struct v4l2_queryctrl radio_qctrl[] = { /* TEA5757 pin mappings */ -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 const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; -static unsigned long in_use; - -#define FREQ_LO 50*16000 -#define FREQ_HI 150*16000 +#define FREQ_LO (50 * 16000) +#define FREQ_HI (150 * 16000) #define FREQ_IF 171200 /* 10.7*16000 */ #define FREQ_STEP 200 /* 12.5*16 */ /* (x==fmhz*16*1000) -> bits */ -#define FREQ2BITS(x) ((( (unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1)) \ - /(FREQ_STEP<<2))<<2) +#define FREQ2BITS(x) \ + ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) -static int maxiradio_exclusive_open(struct file *file) +struct maxiradio { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; -} - -static int maxiradio_exclusive_release(struct file *file) -{ - clear_bit(0, &in_use); - return 0; -} - -static const struct v4l2_file_operations maxiradio_fops = { - .owner = THIS_MODULE, - .open = maxiradio_exclusive_open, - .release = maxiradio_exclusive_release, - .ioctl = video_ioctl2, -}; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct pci_dev *pdev; -static struct radio_device -{ - __u16 io, /* base of radio io */ - muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ - tuned; /* signal strength (0 or 0xffff) */ + u16 io; /* base of radio io */ + u16 muted; /* VIDEO_AUDIO_MUTE */ + u16 stereo; /* VIDEO_TUNER_STEREO_ON */ + u16 tuned; /* signal strength (0 or 0xffff) */ unsigned long freq; struct mutex lock; -} radio_unit = { - .muted =1, - .freq = FREQ_LO, }; -static void outbit(unsigned long bit, __u16 io) +static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) { - if (bit != 0) - { - outb( power|wren|data ,io); udelay(4); - outb( power|wren|data|clk ,io); udelay(4); - outb( power|wren|data ,io); udelay(4); - } - else - { - outb( power|wren ,io); udelay(4); - outb( power|wren|clk ,io); udelay(4); - outb( power|wren ,io); udelay(4); - } + return container_of(v4l2_dev, struct maxiradio, v4l2_dev); } -static void turn_power(__u16 io, int p) +static void outbit(unsigned long bit, u16 io) +{ + int val = power | wren | (bit ? data : 0); + + outb(val, io); + udelay(4); + outb(val | clk, io); + udelay(4); + outb(val, io); + udelay(4); +} + +static void turn_power(struct maxiradio *dev, int p) { if (p != 0) { - dprintk(1, "Radio powered on\n"); - outb(power, io); + dprintk(dev, 1, "Radio powered on\n"); + outb(power, dev->io); } else { - dprintk(1, "Radio powered off\n"); - outb(0,io); + dprintk(dev, 1, "Radio powered off\n"); + outb(0, dev->io); } } -static void set_freq(__u16 io, __u32 freq) +static void set_freq(struct maxiradio *dev, u32 freq) { unsigned long int si; int bl; + int io = dev->io; int val = FREQ2BITS(freq); /* TEA5757 shift register bits (see pdf) */ @@ -189,14 +164,14 @@ static void set_freq(__u16 io, __u32 freq) si >>= 1; } - dprintk(1, "Radio freq set to %d.%02d MHz\n", + dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", freq / 16000, freq % 16000 * 100 / 16000); - turn_power(io, 1); + turn_power(dev, 1); } -static int get_stereo(__u16 io) +static int get_stereo(u16 io) { outb(power,io); udelay(4); @@ -204,7 +179,7 @@ static int get_stereo(__u16 io) return !(inb(io) & mo_st); } -static int get_tune(__u16 io) +static int get_tune(u16 io) { outb(power+clk,io); udelay(4); @@ -213,95 +188,84 @@ static int get_tune(__u16 io) } -static int vidioc_querycap (struct file *file, void *priv, +static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); - strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + struct maxiradio *dev = video_drvdata(file); + strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); + strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); + snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; } -static int vidioc_g_tuner (struct file *file, void *priv, +static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); if (v->index > 0) return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "FM"); + mutex_lock(&dev->lock); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; - - v->rangelow=FREQ_LO; - v->rangehigh=FREQ_HI; - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(get_stereo(card->io)) + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if (get_stereo(dev->io)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal=0xffff*get_tune(card->io); + v->signal = 0xffff * get_tune(dev->io); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_s_tuner (struct file *file, void *priv, +static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; - - return 0; -} - -static int vidioc_g_audio (struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "FM"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; + return v->index ? -EINVAL : 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 i ? -EINVAL : 0; +} +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static int vidioc_s_audio (struct file *file, void *priv, +static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - - return 0; + return a->index ? -EINVAL : 0; } -static int vidioc_s_frequency (struct file *file, void *priv, +static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = 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", + dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", f->frequency / 16000, f->frequency % 16000 * 100 / 16000, FREQ_LO / 16000, FREQ_HI / 16000); @@ -309,75 +273,91 @@ static int vidioc_s_frequency (struct file *file, void *priv, return -EINVAL; } - card->freq = f->frequency; - set_freq(card->io, card->freq); + mutex_lock(&dev->lock); + dev->freq = f->frequency; + set_freq(dev, dev->freq); msleep(125); + mutex_unlock(&dev->lock); return 0; } -static int vidioc_g_frequency (struct file *file, void *priv, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); f->type = V4L2_TUNER_RADIO; - f->frequency = card->freq; + f->frequency = dev->freq; - dprintk(4, "radio freq is %d.%02d MHz", + dprintk(dev, 4, "radio freq is %d.%02d MHz", f->frequency / 16000, f->frequency % 16000 * 100 / 16000); return 0; } -static int vidioc_queryctrl (struct file *file, void *priv, +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); } - return -EINVAL; } -static int vidioc_g_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value=card->muted; - return (0); + case V4L2_CID_AUDIO_MUTE: + ctrl->value = dev->muted; + return 0; } return -EINVAL; } -static int vidioc_s_ctrl (struct file *file, void *priv, - struct v4l2_control *ctrl) +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - struct radio_device *card = video_drvdata(file); + struct maxiradio *dev = video_drvdata(file); switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - card->muted = ctrl->value; - if(card->muted) - turn_power(card->io, 0); - else - set_freq(card->io, card->freq); - return 0; + case V4L2_CID_AUDIO_MUTE: + mutex_lock(&dev->lock); + dev->muted = ctrl->value; + if (dev->muted) + turn_power(dev, 0); + else + set_freq(dev, dev->freq); + mutex_unlock(&dev->lock); + return 0; } return -EINVAL; } +static int maxiradio_open(struct file *file) +{ + return 0; +} + +static int maxiradio_release(struct file *file) +{ + return 0; +} + +static const struct v4l2_file_operations maxiradio_fops = { + .owner = THIS_MODULE, + .open = maxiradio_open, + .release = maxiradio_release, + .ioctl = video_ioctl2, +}; + static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, @@ -393,60 +373,84 @@ static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -static struct video_device maxiradio_radio = { - .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) { - if(!request_region(pci_resource_start(pdev, 0), + struct maxiradio *dev; + struct v4l2_device *v4l2_dev; + int retval = -ENOMEM; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&pdev->dev, "not enough memory\n"); + return -ENOMEM; + } + + v4l2_dev = &dev->v4l2_dev; + mutex_init(&dev->lock); + dev->pdev = pdev; + dev->muted = 1; + dev->freq = FREQ_LO; + + strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); + + retval = v4l2_device_register(&pdev->dev, v4l2_dev); + if (retval < 0) { + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + goto errfr; + } + + if (!request_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { - printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); + v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); goto err_out; } if (pci_enable_device(pdev)) goto err_out_free_region; - radio_unit.io = pci_resource_start(pdev, 0); - mutex_init(&radio_unit.lock); - video_set_drvdata(&maxiradio_radio, &radio_unit); + dev->io = pci_resource_start(pdev, 0); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &maxiradio_fops; + dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); - if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - printk("radio-maxiradio: can't register device!"); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_err(v4l2_dev, "can't register device!"); goto err_out_free_region; } - printk(KERN_INFO "radio-maxiradio: version " - DRIVER_VERSION - " time " - __TIME__ " " - __DATE__ - "\n"); + v4l2_info(v4l2_dev, "version " DRIVER_VERSION + " time " __TIME__ " " __DATE__ "\n"); - printk(KERN_INFO "radio-maxiradio: found Guillemot MAXI Radio device (io = 0x%x)\n", - radio_unit.io); + v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", + dev->io); return 0; err_out_free_region: release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); err_out: + v4l2_device_unregister(v4l2_dev); +errfr: + kfree(dev); return -ENODEV; } static void __devexit maxiradio_remove_one(struct pci_dev *pdev) { - video_unregister_device(&maxiradio_radio); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct maxiradio *dev = to_maxiradio(v4l2_dev); + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); } static struct pci_device_id maxiradio_pci_tbl[] = { { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, PCI_ANY_ID, PCI_ANY_ID, }, - { 0,} + { 0 } }; MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); @@ -470,10 +474,3 @@ static void __exit maxiradio_radio_exit(void) module_init(maxiradio_radio_init); module_exit(maxiradio_radio_exit); - -MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); -MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); -MODULE_LICENSE("GPL"); - -module_param_named(debug,maxiradio_radio.debug, int, 0644); -MODULE_PARM_DESC(debug,"activates debug info"); -- cgit v1.2.3 From 62c50db1615e612d466a6bfcd9badcd300b54609 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:06 +0100 Subject: radio-rtrack2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-rtrack2.c | 280 ++++++++++++++---------------- 1 file changed, 130 insertions(+), 150 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-rtrack2.c b/linux/drivers/media/radio/radio-rtrack2.c index fa9e243c8..93b3da04a 100644 --- a/linux/drivers/media/radio/radio-rtrack2.c +++ b/linux/drivers/media/radio/radio-rtrack2.c @@ -13,35 +13,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -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 = 65535, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("Ben Pfaff"); +MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_RTRACK2_PORT #define CONFIG_RADIO_RTRACK2_PORT -1 @@ -49,79 +32,89 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_RTRACK2_PORT; static int radio_nr = -1; -static spinlock_t lock; -struct rt_device +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct rtrack2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; unsigned long curfreq; int muted; + struct mutex lock; }; +static struct rtrack2 rtrack2_card; + /* local things */ -static void rt_mute(struct rt_device *dev) +static void rt_mute(struct rtrack2 *dev) { - if(dev->muted) + if (dev->muted) return; - spin_lock(&lock); - outb(1, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(1, dev->io); + mutex_unlock(&dev->lock); + mutex_unlock(&dev->lock); dev->muted = 1; } -static void rt_unmute(struct rt_device *dev) +static void rt_unmute(struct rtrack2 *dev) { if(dev->muted == 0) return; - spin_lock(&lock); - outb(0, io); - spin_unlock(&lock); + mutex_lock(&dev->lock); + outb(0, dev->io); + mutex_unlock(&dev->lock); dev->muted = 0; } -static void zero(void) +static void zero(struct rtrack2 *dev) { - outb_p(1, io); - outb_p(3, io); - outb_p(1, io); + outb_p(1, dev->io); + outb_p(3, dev->io); + outb_p(1, dev->io); } -static void one(void) +static void one(struct rtrack2 *dev) { - outb_p(5, io); - outb_p(7, io); - outb_p(5, io); + outb_p(5, dev->io); + outb_p(7, dev->io); + outb_p(5, dev->io); } -static int rt_setfreq(struct rt_device *dev, unsigned long freq) +static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) { int i; + mutex_lock(&dev->lock); + dev->curfreq = freq; freq = freq / 200 + 856; - spin_lock(&lock); - - outb_p(0xc8, io); - outb_p(0xc9, io); - outb_p(0xc9, io); + outb_p(0xc8, dev->io); + outb_p(0xc9, dev->io); + outb_p(0xc9, dev->io); for (i = 0; i < 10; i++) - zero (); + zero(dev); for (i = 14; i >= 0; i--) if (freq & (1 << i)) - one (); + one(dev); else - zero (); + zero(dev); - outb_p(0xc8, io); + outb_p(0xc8, dev->io); if (!dev->muted) - outb_p(0, io); + outb_p(0, dev->io); - spin_unlock(&lock); + mutex_unlock(&dev->lock); return 0; } @@ -130,61 +123,61 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); strlcpy(v->card, "RadioTrack II", 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_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 rt_getsigstr(struct rt_device *dev) +static int rt_getsigstr(struct rtrack2 *dev) { - if (inb(io) & 2) /* bit set = no signal present */ - return 0; - return 1; /* signal present */ + int sig = 1; + + mutex_lock(&dev->lock); + if (inb(dev->io) & 2) /* bit set = no signal present */ + sig = 0; + mutex_unlock(&dev->lock); + return sig; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = 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 = (88*16000); - v->rangehigh = (108*16000); + v->rangelow = 88 * 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*rt_getsigstr(rt); + v->signal = 0xFFFF * rt_getsigstr(rt); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); - rt->curfreq = f->frequency; - rt_setfreq(rt, rt->curfreq); + rt_setfreq(rt, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = rt->curfreq; @@ -194,14 +187,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, 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, 65535, 65535); } return -EINVAL; } @@ -209,7 +199,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 rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -228,7 +218,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 rt_device *rt = video_drvdata(file); + struct rtrack2 *rt = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -247,17 +237,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +245,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct rt_device rtrack2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int rtrack2_exclusive_open(struct file *file) +static int rtrack2_open(struct file *file) { - return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int rtrack2_exclusive_release(struct file *file) +static int rtrack2_release(struct file *file) { - clear_bit(0, &rtrack2_unit.in_use); return 0; } static const struct v4l2_file_operations rtrack2_fops = { .owner = THIS_MODULE, - .open = rtrack2_exclusive_open, - .release = rtrack2_exclusive_release, + .open = rtrack2_open, + .release = rtrack2_release, .ioctl = video_ioctl2, }; @@ -314,62 +295,61 @@ static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -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) { - if(io==-1) - { - printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); + struct rtrack2 *dev = &rtrack2_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); + dev->io = io; + if (dev->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); return -EINVAL; } - if (!request_region(io, 4, "rtrack2")) - { - printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); + if (!request_region(dev->io, 4, "rtrack2")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); return -EBUSY; } - video_set_drvdata(&rtrack2_radio, &rtrack2_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(dev->io, 4); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } - spin_lock_init(&lock); - if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 4); + strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + dev->vdev.v4l2_dev = v4l2_dev; + dev->vdev.fops = &rtrack2_fops; + dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; + dev->vdev.release = video_device_release_empty; + video_set_drvdata(&dev->vdev, dev); + + mutex_init(&dev->lock); + if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(dev->io, 4); return -EINVAL; } - printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); + v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); /* mute card - prevents noisy bootups */ - outb(1, io); - rtrack2_unit.muted = 1; + outb(1, dev->io); + dev->muted = 1; return 0; } -MODULE_AUTHOR("Ben Pfaff"); -MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit rtrack2_cleanup_module(void) +static void __exit rtrack2_exit(void) { - video_unregister_device(&rtrack2_radio); - release_region(io,4); + struct rtrack2 *dev = &rtrack2_card; + + video_unregister_device(&dev->vdev); + v4l2_device_unregister(&dev->v4l2_dev); + release_region(dev->io, 4); } module_init(rtrack2_init); -module_exit(rtrack2_cleanup_module); - -/* - Local variables: - compile-command: "mmake" - End: -*/ +module_exit(rtrack2_exit); -- cgit v1.2.3 From cf853d565db80b0025c0f9d25582b7825d258f21 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:52:34 +0100 Subject: radio-sf16fmi: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmi.c | 286 ++++++++++++++---------------- 1 file changed, 136 insertions(+), 150 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-sf16fmi.c b/linux/drivers/media/radio/radio-sf16fmi.c index 3cce0afb4..392aa27e0 100644 --- a/linux/drivers/media/radio/radio-sf16fmi.c +++ b/linux/drivers/media/radio/radio-sf16fmi.c @@ -22,114 +22,111 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include "compat.h" -#include /* kernel radio structs */ -#include -#include #include -#include /* outb, outb_p */ -#include /* copy to/from user */ #include +#include /* kernel radio structs */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -#define RADIO_VERSION KERNEL_VERSION(0,0,2) +MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); +MODULE_DESCRIPTION("A driver for the SF16MI radio."); +MODULE_LICENSE("GPL"); -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, - } -}; +static int io = -1; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); +module_param(radio_nr, int, 0); -struct fmi_device +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct fmi { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; /* 1 or 0 */ unsigned long curfreq; /* freq in kHz */ __u32 flags; + struct mutex lock; }; -static int io = -1; -static int radio_nr = -1; -static struct pnp_dev *dev = NULL; -static struct mutex lock; +static struct fmi fmi_card; +static struct pnp_dev *dev; /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ /* It is only useful to give freq in intervall of 800 (=0.05Mhz), * other bits will be truncated, e.g 92.7400016 -> 92.7, but * 92.7400017 -> 92.75 */ -#define RSF16_ENCODE(x) ((x)/800+214) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 800 + 214) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static void outbits(int bits, unsigned int data, int port) +static void outbits(int bits, unsigned int data, int io) { - while(bits--) { - if(data & 1) { - outb(5, port); + while (bits--) { + if (data & 1) { + outb(5, io); udelay(6); - outb(7, port); + outb(7, io); udelay(6); } else { - outb(1, port); + outb(1, io); udelay(6); - outb(3, port); + outb(3, io); udelay(6); } - data>>=1; + data >>= 1; } } -static inline void fmi_mute(int port) +static inline void fmi_mute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x00, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x00, fmi->io); + mutex_unlock(&fmi->lock); } -static inline void fmi_unmute(int port) +static inline void fmi_unmute(struct fmi *fmi) { - mutex_lock(&lock); - outb(0x08, port); - mutex_unlock(&lock); + mutex_lock(&fmi->lock); + outb(0x08, fmi->io); + mutex_unlock(&fmi->lock); } -static inline int fmi_setfreq(struct fmi_device *dev) +static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq) { - int myport = dev->port; - unsigned long freq = dev->curfreq; - - mutex_lock(&lock); + mutex_lock(&fmi->lock); + fmi->curfreq = freq; - outbits(16, RSF16_ENCODE(freq), myport); - outbits(8, 0xC0, myport); + outbits(16, RSF16_ENCODE(freq), fmi->io); + outbits(8, 0xC0, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - mutex_unlock(&lock); - if (dev->curvol) fmi_unmute(myport); + mutex_unlock(&fmi->lock); + if (fmi->curvol) + fmi_unmute(fmi); return 0; } -static inline int fmi_getsigstr(struct fmi_device *dev) +static inline int fmi_getsigstr(struct fmi *fmi) { int val; int res; - int myport = dev->port; - - mutex_lock(&lock); - val = dev->curvol ? 0x08 : 0x00; /* unmute/mute */ - outb(val, myport); - outb(val | 0x10, myport); + mutex_lock(&fmi->lock); + val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */ + outb(val, fmi->io); + outb(val | 0x10, fmi->io); msleep(143); /* was schedule_timeout(HZ/7) */ - res = (int)inb(myport+1); - outb(val, myport); + res = (int)inb(fmi->io + 1); + outb(val, fmi->io); - mutex_unlock(&lock); + mutex_unlock(&fmi->lock); return (res & 2) ? 0 : 0xFFFF; } @@ -138,9 +135,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); strlcpy(v->card, "SF16-FMx 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; } @@ -148,18 +145,18 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = 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; mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; - v->capability = fmi->flags&V4L2_TUNER_CAP_LOW; + v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); return 0; @@ -168,32 +165,29 @@ static int vidioc_g_tuner(struct file *file, void *priv, 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 fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); if (!(fmi->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 800 to match th freq - that will be used */ - fmi->curfreq = (f->frequency/800)*800; - fmi_setfreq(fmi); + /* rounding in steps of 800 to match the freq + that will be used */ + fmi_setfreq(fmi, (f->frequency / 800) * 800); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmi->curfreq; @@ -205,14 +199,9 @@ static int vidioc_g_frequency(struct file *file, void *priv, 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); } return -EINVAL; } @@ -220,7 +209,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 fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -233,31 +222,20 @@ 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 fmi_device *fmi = video_drvdata(file); + struct fmi *fmi = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) - fmi_mute(fmi->port); + fmi_mute(fmi); else - fmi_unmute(fmi->port); + fmi_unmute(fmi); fmi->curvol = ctrl->value; return 0; } return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -266,36 +244,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmi_device fmi_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmi_exclusive_open(struct file *file) +static int fmi_open(struct file *file) { - return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmi_exclusive_release(struct file *file) +static int fmi_release(struct file *file) { - clear_bit(0, &fmi_unit.in_use); return 0; } static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, - .open = fmi_exclusive_open, - .release = fmi_exclusive_release, + .open = fmi_open, + .release = fmi_release, .ioctl = video_ioctl2, }; @@ -314,13 +294,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -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? */ static struct isapnp_device_id id_table[] __devinitdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, @@ -345,7 +318,7 @@ static int __init isapnp_fmi_probe(void) if (pnp_device_attach(dev) < 0) return -EAGAIN; if (pnp_activate_dev(dev) < 0) { - printk ("radio-sf16fmi: PnP configure failed (out of resources?)\n"); + printk(KERN_ERR "radio-sf16fmi: PnP configure failed (out of resources?)\n"); pnp_device_detach(dev); return -ENOMEM; } @@ -355,59 +328,72 @@ static int __init isapnp_fmi_probe(void) } i = pnp_port_start(dev, 0); - printk ("radio-sf16fmi: PnP reports card at %#x\n", i); + printk(KERN_INFO "radio-sf16fmi: PnP reports card at %#x\n", i); return i; } static int __init fmi_init(void) { + struct fmi *fmi = &fmi_card; + struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; + int res; + if (io < 0) io = isapnp_fmi_probe(); - if (io < 0) { - printk(KERN_ERR "radio-sf16fmi: No PnP card found.\n"); - return io; + strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); + fmi->io = io; + if (fmi->io < 0) { + v4l2_err(v4l2_dev, "No PnP card found.\n"); + return fmi->io; } if (!request_region(io, 2, "radio-sf16fmi")) { - printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io); + v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io); pnp_device_detach(dev); return -EBUSY; } - fmi_unit.port = io; - fmi_unit.curvol = 0; - fmi_unit.curfreq = 0; - fmi_unit.flags = V4L2_TUNER_CAP_LOW; - video_set_drvdata(&fmi_radio, &fmi_unit); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmi->io, 2); + pnp_device_detach(dev); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + fmi->flags = V4L2_TUNER_CAP_LOW; + strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); + fmi->vdev.v4l2_dev = v4l2_dev; + fmi->vdev.fops = &fmi_fops; + fmi->vdev.ioctl_ops = &fmi_ioctl_ops; + fmi->vdev.release = video_device_release_empty; + video_set_drvdata(&fmi->vdev, fmi); - mutex_init(&lock); + mutex_init(&fmi->lock); - if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmi->io, 2); + pnp_device_detach(dev); return -EINVAL; } - printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io); + v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io); /* mute card - prevents noisy bootups */ - fmi_mute(io); + fmi_mute(fmi); return 0; } -MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); -MODULE_DESCRIPTION("A driver for the SF16MI radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); -module_param(radio_nr, int, 0); - -static void __exit fmi_cleanup_module(void) +static void __exit fmi_exit(void) { - video_unregister_device(&fmi_radio); - release_region(io, 2); + struct fmi *fmi = &fmi_card; + + video_unregister_device(&fmi->vdev); + v4l2_device_unregister(&fmi->v4l2_dev); + release_region(fmi->io, 2); if (dev) pnp_device_detach(dev); } module_init(fmi_init); -module_exit(fmi_cleanup_module); +module_exit(fmi_exit); -- cgit v1.2.3 From b4fe8e07fa8e6266902aa003db9f8653a9190e2f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:26 +0100 Subject: radio-sf16fmr2: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-sf16fmr2.c | 374 ++++++++++++++--------------- 1 file changed, 176 insertions(+), 198 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-sf16fmr2.c b/linux/drivers/media/radio/radio-sf16fmr2.c index 69a28d1ff..34de92f82 100644 --- a/linux/drivers/media/radio/radio-sf16fmr2.c +++ b/linux/drivers/media/radio/radio-sf16fmr2.c @@ -18,41 +18,30 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include -#include #include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include +#include +#include "compat.h" -static struct mutex lock; +MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); +MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); +MODULE_LICENSE("GPL"); + +static int io = 0x384; +static int radio_nr = -1; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); +module_param(radio_nr, int, 0); -#include /* for KERNEL_VERSION MACRO */ #define RADIO_VERSION KERNEL_VERSION(0,0,2) #define AUD_VOL_INDEX 1 -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, - }, - [AUD_VOL_INDEX] = { - .id = V4L2_CID_AUDIO_VOLUME, - .name = "Volume", - .minimum = 0, - .maximum = 15, - .step = 1, - .default_value = 0, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; - #undef DEBUG //#define DEBUG 1 @@ -63,156 +52,160 @@ static struct v4l2_queryctrl radio_qctrl[] = { #endif /* this should be static vars for module size */ -struct fmr2_device +struct fmr2 { - unsigned long in_use; - int port; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct mutex lock; + int io; int curvol; /* 0-15 */ int mute; int stereo; /* card is producing stereo audio */ unsigned long curfreq; /* freq in kHz */ int card_type; - __u32 flags; + u32 flags; }; -static int io = 0x384; -static int radio_nr = -1; +static struct fmr2 fmr2_card; /* hw precision is 12.5 kHz * It is only useful to give freq in intervall of 200 (=0.0125Mhz), * other bits will be truncated */ -#define RSF16_ENCODE(x) ((x)/200+856) -#define RSF16_MINFREQ 87*16000 -#define RSF16_MAXFREQ 108*16000 +#define RSF16_ENCODE(x) ((x) / 200 + 856) +#define RSF16_MINFREQ (87 * 16000) +#define RSF16_MAXFREQ (108 * 16000) -static inline void wait(int n,int port) +static inline void wait(int n, int io) { - for (;n;--n) inb(port); + for (; n; --n) + inb(io); } -static void outbits(int bits, unsigned int data, int nWait, int port) +static void outbits(int bits, unsigned int data, int nWait, int io) { int bit; - for(;--bits>=0;) { - bit = (data>>bits) & 1; - outb(bit,port); - wait(nWait,port); - outb(bit|2,port); - wait(nWait,port); - outb(bit,port); - wait(nWait,port); + + for (; --bits >= 0;) { + bit = (data >> bits) & 1; + outb(bit, io); + wait(nWait, io); + outb(bit | 2, io); + wait(nWait, io); + outb(bit, io); + wait(nWait, io); } } -static inline void fmr2_mute(int port) +static inline void fmr2_mute(int io) { - outb(0x00, port); - wait(4,port); + outb(0x00, io); + wait(4, io); } -static inline void fmr2_unmute(int port) +static inline void fmr2_unmute(int io) { - outb(0x04, port); - wait(4,port); + outb(0x04, io); + wait(4, io); } -static inline int fmr2_stereo_mode(int port) +static inline int fmr2_stereo_mode(int io) { - int n = inb(port); - outb(6,port); - inb(port); - n = ((n>>3)&1)^1; + int n = inb(io); + + outb(6, io); + inb(io); + n = ((n >> 3) & 1) ^ 1; debug_print((KERN_DEBUG "stereo: %d\n", n)); return n; } -static int fmr2_product_info(struct fmr2_device *dev) +static int fmr2_product_info(struct fmr2 *dev) { - int n = inb(dev->port); + int n = inb(dev->io); + n &= 0xC1; - if (n == 0) - { + if (n == 0) { /* this should support volume set */ dev->card_type = 12; return 0; } /* not volume (mine is 11) */ - dev->card_type = (n==128)?11:0; + dev->card_type = (n == 128) ? 11 : 0; return n; } -static inline int fmr2_getsigstr(struct fmr2_device *dev) +static inline int fmr2_getsigstr(struct fmr2 *dev) { - /* !!! work only if scanning freq */ - int port = dev->port, res = 0xffff; - outb(5,port); - wait(4,port); - if (!(inb(port)&1)) res = 0; + /* !!! works only if scanning freq */ + int res = 0xffff; + + outb(5, dev->io); + wait(4, dev->io); + if (!(inb(dev->io) & 1)) + res = 0; debug_print((KERN_DEBUG "signal: %d\n", res)); return res; } /* set frequency and unmute card */ -static int fmr2_setfreq(struct fmr2_device *dev) +static int fmr2_setfreq(struct fmr2 *dev) { - int port = dev->port; unsigned long freq = dev->curfreq; - fmr2_mute(port); + fmr2_mute(dev->io); /* 0x42 for mono output * 0x102 forward scanning * 0x182 scansione avanti */ - outbits(9,0x2,3,port); - outbits(16,RSF16_ENCODE(freq),2,port); + outbits(9, 0x2, 3, dev->io); + outbits(16, RSF16_ENCODE(freq), 2, dev->io); - fmr2_unmute(port); + fmr2_unmute(dev->io); /* wait 0.11 sec */ msleep(110); /* NOTE if mute this stop radio you must set freq on unmute */ - dev->stereo = fmr2_stereo_mode(port); + dev->stereo = fmr2_stereo_mode(dev->io); return 0; } /* !!! not tested, in my card this does't work !!! */ -static int fmr2_setvolume(struct fmr2_device *dev) +static int fmr2_setvolume(struct fmr2 *dev) { int vol[16] = { 0x021, 0x084, 0x090, 0x104, 0x110, 0x204, 0x210, 0x402, 0x404, 0x408, 0x410, 0x801, 0x802, 0x804, 0x808, 0x810 }; - int i, a, port = dev->port; + int i, a; int n = vol[dev->curvol & 0x0f]; if (dev->card_type != 11) return 1; for (i = 12; --i >= 0; ) { - a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ - outb(a | 4, port); - wait(4, port); - outb(a | 0x24, port); - wait(4, port); - outb(a | 4, port); - wait(4, port); + a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */ + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } for (i = 6; --i >= 0; ) { a = ((0x18 >> i) & 1) << 6; - outb(a | 4, port); - wait(4,port); - outb(a | 0x24, port); - wait(4,port); - outb(a|4, port); - wait(4,port); + outb(a | 4, dev->io); + wait(4, dev->io); + outb(a | 0x24, dev->io); + wait(4, dev->io); + outb(a | 4, dev->io); + wait(4, dev->io); } - wait(4, port); - outb(0x14, port); - + wait(4, dev->io); + outb(0x14, dev->io); return 0; } @@ -221,9 +214,9 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver)); strlcpy(v->card, "SF16-FMR2 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; } @@ -231,54 +224,52 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { int mult; - struct fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = 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; mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; - v->rangelow = RSF16_MINFREQ/mult; - v->rangehigh = RSF16_MAXFREQ/mult; + v->rangelow = RSF16_MINFREQ / mult; + v->rangehigh = RSF16_MAXFREQ / mult; v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; - mutex_lock(&lock); + mutex_lock(&fmr2->lock); v->signal = fmr2_getsigstr(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); 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 fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) f->frequency *= 1000; if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ ) + f->frequency > RSF16_MAXFREQ) return -EINVAL; - /*rounding in steps of 200 to match th freq - that will be used */ - fmr2->curfreq = (f->frequency/200)*200; + /* rounding in steps of 200 to match the freq + that will be used */ + fmr2->curfreq = (f->frequency / 200) * 200; /* set card freq (if not muted) */ if (fmr2->curvol && !fmr2->mute) { - mutex_lock(&lock); + mutex_lock(&fmr2->lock); fmr2_setfreq(fmr2); - mutex_unlock(&lock); + mutex_unlock(&fmr2->lock); } return 0; } @@ -286,7 +277,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 fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = fmr2->curfreq; @@ -298,13 +289,16 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; + struct fmr2 *fmr2 = video_drvdata(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)); - 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: + /* Only card_type == 11 implements volume */ + if (fmr2->card_type == 11) + return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0); + return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); } return -EINVAL; } @@ -312,7 +306,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 fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -328,18 +322,14 @@ 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 fmr2_device *fmr2 = video_drvdata(file); + struct fmr2 *fmr2 = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: fmr2->mute = ctrl->value; break; case V4L2_CID_AUDIO_VOLUME: - if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) - fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum; - else - fmr2->curvol = ctrl->value; - + fmr2->curvol = ctrl->value; break; default: return -EINVAL; @@ -352,25 +342,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, printk(KERN_DEBUG "mute\n"); #endif - mutex_lock(&lock); + mutex_lock(&fmr2->lock); if (fmr2->curvol && !fmr2->mute) { fmr2_setvolume(fmr2); /* Set frequency and unmute card */ fmr2_setfreq(fmr2); } else - fmr2_mute(fmr2->port); - mutex_unlock(&lock); - return 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->capability = V4L2_AUDCAP_STEREO; + fmr2_mute(fmr2->io); + mutex_unlock(&fmr2->lock); return 0; } @@ -382,36 +361,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct fmr2_device fmr2_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int fmr2_exclusive_open(struct file *file) +static int fmr2_open(struct file *file) { - return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; + return 0; } -static int fmr2_exclusive_release(struct file *file) +static int fmr2_release(struct file *file) { - clear_bit(0, &fmr2_unit.in_use); return 0; } static const struct v4l2_file_operations fmr2_fops = { .owner = THIS_MODULE, - .open = fmr2_exclusive_open, - .release = fmr2_exclusive_release, + .open = fmr2_open, + .release = fmr2_release, .ioctl = video_ioctl2, }; @@ -430,67 +411,64 @@ static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -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) { - fmr2_unit.port = io; - fmr2_unit.curvol = 0; - fmr2_unit.mute = 0; - fmr2_unit.curfreq = 0; - fmr2_unit.stereo = 1; - fmr2_unit.flags = V4L2_TUNER_CAP_LOW; - fmr2_unit.card_type = 0; - video_set_drvdata(&fmr2_radio, &fmr2_unit); - - mutex_init(&lock); - - if (!request_region(io, 2, "sf16fmr2")) { - printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n"); + struct fmr2 *fmr2 = &fmr2_card; + struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); + fmr2->io = io; + fmr2->stereo = 1; + fmr2->flags = V4L2_TUNER_CAP_LOW; + mutex_init(&fmr2->lock); + + if (!request_region(fmr2->io, 2, "sf16fmr2")) { + v4l2_err(v4l2_dev, "request_region failed!\n"); return -EBUSY; } - if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); - return -EINVAL; + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(fmr2->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; } - printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); - /* mute card - prevents noisy bootups */ - mutex_lock(&lock); - fmr2_mute(io); - fmr2_product_info(&fmr2_unit); - mutex_unlock(&lock); - debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); + strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name)); + fmr2->vdev.v4l2_dev = v4l2_dev; + fmr2->vdev.fops = &fmr2_fops; + fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops; + fmr2->vdev.release = video_device_release_empty; + video_set_drvdata(&fmr2->vdev, fmr2); - /* Only card_type == 11 implements volume */ - if (fmr2_unit.card_type != 11) - radio_qctrl[AUD_VOL_INDEX].maximum = 1; + if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(fmr2->io, 2); + return -EINVAL; + } + v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); + /* mute card - prevents noisy bootups */ + mutex_lock(&fmr2->lock); + fmr2_mute(fmr2->io); + fmr2_product_info(fmr2); + mutex_unlock(&fmr2->lock); + debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type)); return 0; } -MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); -MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); -module_param(radio_nr, int, 0); - -static void __exit fmr2_cleanup_module(void) +static void __exit fmr2_exit(void) { - video_unregister_device(&fmr2_radio); - release_region(io,2); + struct fmr2 *fmr2 = &fmr2_card; + + video_unregister_device(&fmr2->vdev); + v4l2_device_unregister(&fmr2->v4l2_dev); + release_region(fmr2->io, 2); } module_init(fmr2_init); -module_exit(fmr2_cleanup_module); +module_exit(fmr2_exit); #ifndef MODULE -- cgit v1.2.3 From 241f0d88b7d45102e0c58b0532cbc4b4b3090a87 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:53:58 +0100 Subject: radio-terratec: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-terratec.c | 312 ++++++++++++++--------------- 1 file changed, 148 insertions(+), 164 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index 1c2b4db2d..b63443076 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -28,16 +28,31 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include -#include +#include "compat.h" -#include /* 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 +struct terratec { - unsigned long in_use; - int port; + 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); + + 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); } - spin_unlock(&lock); + mutex_unlock(&tt->lock); } -static void tt_mute(struct tt_device *dev) +static void tt_mute(struct terratec *tt) { - dev->muted = 1; - cardWriteVol(0); + tt->muted = 1; + tt_write_vol(tt, 0); } -static int tt_setvol(struct tt_device *dev, int vol) +static int tt_setvol(struct terratec *tt, 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 */ + 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! */ + 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; } - dev->muted = 0; - - cardWriteVol(vol); - - dev->curvol = vol; - + 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; + 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); - } - else - { - outb(WRT_EN|0x00, BASEPORT); - outb(WRT_EN|0x00|CLK_ON , BASEPORT); + 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); } } - outb(0x00, BASEPORT); + outb(0x00, tt->io); - spin_unlock(&lock); + mutex_unlock(&tt->lock); return 0; } -static int tt_getsigstr(struct tt_device *dev) /* TODO */ +static int tt_getsigstr(struct terratec *tt) { - if (inb(io) & 2) /* bit set = no signal present */ + 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 *file, void *priv, { 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); + struct terratec *tt = video_drvdata(file); - tt->curfreq = f->frequency; - tt_setfreq(tt, tt->curfreq); + 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 *file, void *priv, 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_queryctrl(struct file *file, void *priv, 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_g_ctrl(struct file *file, void *priv, 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,17 +309,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -338,36 +317,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct tt_device terratec_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int terratec_exclusive_open(struct file *file) +static int terratec_open(struct file *file) { - return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0; + return 0; } -static int terratec_exclusive_release(struct file *file) +static int terratec_release(struct file *file) { - clear_bit(0, &terratec_unit.in_use); 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 terratec_ioctl_ops = { .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); + 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); - spin_lock_init(&lock); + mutex_init(&tt->lock); - if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io,2); + 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; - + tt_write_vol(tt, 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) +static void __exit terratec_exit(void) { - video_unregister_device(&terratec_radio); - release_region(io,2); - printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n"); + 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); -- cgit v1.2.3 From ea7413e897555d76567d20e4124ba38502f71e52 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:23 +0100 Subject: radio-trust: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-trust.c | 349 ++++++++++++++++---------------- 1 file changed, 180 insertions(+), 169 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 5ce7a9d1d..196db11de 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -19,50 +19,17 @@ #include #include #include -#include -#include -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include -#include +#include +#include +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -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 = 2048, - .default_value = 65535, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_BASS, - .name = "Bass", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - },{ - .id = V4L2_CID_AUDIO_TREBLE, - .name = "Treble", - .minimum = 0, - .maximum = 65535, - .step = 4370, - .default_value = 32768, - .type = V4L2_CTRL_TYPE_INTEGER, - }, -}; +MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); +MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); +MODULE_LICENSE("GPL"); /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ @@ -72,26 +39,41 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_TRUST_PORT; static int radio_nr = -1; -static int ioval = 0xf; -static __u16 curvol; -static __u16 curbass; -static __u16 curtreble; -static unsigned long curfreq; -static int curstereo; -static int curmute; -static unsigned long in_use; + +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct trust { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; + int ioval; + __u16 curvol; + __u16 curbass; + __u16 curtreble; + int muted; + unsigned long curfreq; + int curstereo; + int curmute; + struct mutex lock; +}; + +static struct trust trust_card; /* i2c addresses */ #define TDA7318_ADDR 0x88 #define TSA6060T_ADDR 0xc4 -#define TR_DELAY do { inb(io); inb(io); inb(io); } while(0) -#define TR_SET_SCL outb(ioval |= 2, io) -#define TR_CLR_SCL outb(ioval &= 0xfd, io) -#define TR_SET_SDA outb(ioval |= 1, io) -#define TR_CLR_SDA outb(ioval &= 0xfe, io) +#define TR_DELAY do { inb(tr->io); inb(tr->io); inb(tr->io); } while (0) +#define TR_SET_SCL outb(tr->ioval |= 2, tr->io) +#define TR_CLR_SCL outb(tr->ioval &= 0xfd, tr->io) +#define TR_SET_SDA outb(tr->ioval |= 1, tr->io) +#define TR_CLR_SDA outb(tr->ioval &= 0xfe, tr->io) -static void write_i2c(int n, ...) +static void write_i2c(struct trust *tr, int n, ...) { unsigned char val, mask; va_list args; @@ -137,62 +119,77 @@ static void write_i2c(int n, ...) va_end(args); } -static void tr_setvol(__u16 vol) +static void tr_setvol(struct trust *tr, __u16 vol) { - curvol = vol / 2048; - write_i2c(2, TDA7318_ADDR, curvol ^ 0x1f); + mutex_lock(&tr->lock); + tr->curvol = vol / 2048; + write_i2c(tr, 2, TDA7318_ADDR, tr->curvol ^ 0x1f); + mutex_unlock(&tr->lock); } static int basstreble2chip[15] = { 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8 }; -static void tr_setbass(__u16 bass) +static void tr_setbass(struct trust *tr, __u16 bass) { - curbass = bass / 4370; - write_i2c(2, TDA7318_ADDR, 0x60 | basstreble2chip[curbass]); + mutex_lock(&tr->lock); + tr->curbass = bass / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x60 | basstreble2chip[tr->curbass]); + mutex_unlock(&tr->lock); } -static void tr_settreble(__u16 treble) +static void tr_settreble(struct trust *tr, __u16 treble) { - curtreble = treble / 4370; - write_i2c(2, TDA7318_ADDR, 0x70 | basstreble2chip[curtreble]); + mutex_lock(&tr->lock); + tr->curtreble = treble / 4370; + write_i2c(tr, 2, TDA7318_ADDR, 0x70 | basstreble2chip[tr->curtreble]); + mutex_unlock(&tr->lock); } -static void tr_setstereo(int stereo) +static void tr_setstereo(struct trust *tr, int stereo) { - curstereo = !!stereo; - ioval = (ioval & 0xfb) | (!curstereo << 2); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curstereo = !!stereo; + tr->ioval = (tr->ioval & 0xfb) | (!tr->curstereo << 2); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static void tr_setmute(int mute) +static void tr_setmute(struct trust *tr, int mute) { - curmute = !!mute; - ioval = (ioval & 0xf7) | (curmute << 3); - outb(ioval, io); + mutex_lock(&tr->lock); + tr->curmute = !!mute; + tr->ioval = (tr->ioval & 0xf7) | (tr->curmute << 3); + outb(tr->ioval, tr->io); + mutex_unlock(&tr->lock); } -static int tr_getsigstr(void) +static int tr_getsigstr(struct trust *tr) { int i, v; - for(i = 0, v = 0; i < 100; i++) v |= inb(io); - return (v & 1)? 0 : 0xffff; + mutex_lock(&tr->lock); + for (i = 0, v = 0; i < 100; i++) + v |= inb(tr->io); + mutex_unlock(&tr->lock); + return (v & 1) ? 0 : 0xffff; } -static int tr_getstereo(void) +static int tr_getstereo(struct trust *tr) { /* don't know how to determine it, just return the setting */ - return curstereo; + return tr->curstereo; } -static void tr_setfreq(unsigned long f) +static void tr_setfreq(struct trust *tr, unsigned long f) { + mutex_lock(&tr->lock); + tr->curfreq = f; f /= 160; /* Convert to 10 kHz units */ - f += 1070; /* Add 10.7 MHz IF */ - - write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + f += 1070; /* Add 10.7 MHz IF */ + write_i2c(tr, 5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0); + mutex_unlock(&tr->lock); } static int vidioc_querycap(struct file *file, void *priv, @@ -200,68 +197,75 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-trust", sizeof(v->driver)); strlcpy(v->card, "Trust FM 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; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { + struct trust *tr = 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.5*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 87.5 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; - if (tr_getstereo()) + if (tr_getstereo(tr)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = tr_getsigstr(); + v->signal = tr_getsigstr(tr); return 0; } static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - if (v->index > 0) - return -EINVAL; + struct trust *tr = video_drvdata(file); + if (v->index) + return -EINVAL; + tr_setstereo(tr, v->audmode == V4L2_TUNER_MODE_STEREO); return 0; } static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - curfreq = f->frequency; - tr_setfreq(curfreq); + struct trust *tr = video_drvdata(file); + + tr_setfreq(tr, f->frequency); return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { + struct trust *tr = video_drvdata(file); + f->type = V4L2_TUNER_RADIO; - f->frequency = curfreq; + f->frequency = tr->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, 2048, 65535); + case V4L2_CID_AUDIO_BASS: + case V4L2_CID_AUDIO_TREBLE: + return v4l2_ctrl_query_fill(qc, 0, 65535, 4370, 32768); } return -EINVAL; } @@ -269,18 +273,20 @@ static int vidioc_queryctrl(struct file *file, void *priv, static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { + struct trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = curmute; + ctrl->value = tr->curmute; return 0; case V4L2_CID_AUDIO_VOLUME: - ctrl->value = curvol * 2048; + ctrl->value = tr->curvol * 2048; return 0; case V4L2_CID_AUDIO_BASS: - ctrl->value = curbass * 4370; + ctrl->value = tr->curbass * 4370; return 0; case V4L2_CID_AUDIO_TREBLE: - ctrl->value = curtreble * 4370; + ctrl->value = tr->curtreble * 4370; return 0; } return -EINVAL; @@ -289,37 +295,25 @@ 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 trust *tr = video_drvdata(file); + switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - tr_setmute(ctrl->value); + tr_setmute(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_VOLUME: - tr_setvol(ctrl->value); + tr_setvol(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_BASS: - tr_setbass(ctrl->value); + tr_setbass(tr, ctrl->value); return 0; case V4L2_CID_AUDIO_TREBLE: - tr_settreble(ctrl->value); + tr_settreble(tr, ctrl->value); return 0; } -#if 0 /* Should implement mono/stereo on V4L2 */ - tr_setstereo(v->mode & VIDEO_SOUND_STEREO); -#endif return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -328,34 +322,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static int trust_exclusive_open(struct file *file) +static int trust_open(struct file *file) { - return test_and_set_bit(0, &in_use) ? -EBUSY : 0; + return 0; } -static int trust_exclusive_release(struct file *file) +static int trust_release(struct file *file) { - clear_bit(0, &in_use); return 0; } static const struct v4l2_file_operations trust_fops = { .owner = THIS_MODULE, - .open = trust_exclusive_open, - .release = trust_exclusive_release, + .open = trust_open, + .release = trust_release, .ioctl = video_ioctl2, }; @@ -374,59 +372,72 @@ static const struct v4l2_ioctl_ops trust_ioctl_ops = { .vidioc_s_input = vidioc_s_input, }; -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) { - if(io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct trust *tr = &trust_card; + struct v4l2_device *v4l2_dev = &tr->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "trust", sizeof(v4l2_dev->name)); + tr->io = io; + tr->ioval = 0xf; + mutex_init(&tr->lock); + + if (tr->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if(!request_region(io, 2, "Trust FM Radio")) { - printk(KERN_ERR "trust: port 0x%x already in use\n", io); + if (!request_region(tr->io, 2, "Trust FM Radio")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", tr->io); return -EBUSY; } - if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(tr->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(tr->vdev.name, v4l2_dev->name, sizeof(tr->vdev.name)); + tr->vdev.v4l2_dev = v4l2_dev; + tr->vdev.fops = &trust_fops; + tr->vdev.ioctl_ops = &trust_ioctl_ops; + tr->vdev.release = video_device_release_empty; + video_set_drvdata(&tr->vdev, tr); + + if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(tr->io, 2); return -EINVAL; } - printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); + v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n"); - write_i2c(2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ - write_i2c(2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x80); /* speaker att. LF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xa0); /* speaker att. RF = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xc0); /* speaker att. LR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0xe0); /* speaker att. RR = 0 dB */ + write_i2c(tr, 2, TDA7318_ADDR, 0x40); /* stereo 1 input, gain = 18.75 dB */ - tr_setvol(0x8000); - tr_setbass(0x8000); - tr_settreble(0x8000); - tr_setstereo(1); + tr_setvol(tr, 0xffff); + tr_setbass(tr, 0x8000); + tr_settreble(tr, 0x8000); + tr_setstereo(tr, 1); /* mute card - prevents noisy bootups */ - tr_setmute(1); + tr_setmute(tr, 1); return 0; } -MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); -MODULE_DESCRIPTION("A driver for the Trust FM Radio card."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)"); -module_param(radio_nr, int, 0); - static void __exit cleanup_trust_module(void) { - video_unregister_device(&trust_radio); - release_region(io, 2); + struct trust *tr = &trust_card; + + video_unregister_device(&tr->vdev); + v4l2_device_unregister(&tr->v4l2_dev); + release_region(tr->io, 2); } module_init(trust_init); -- cgit v1.2.3 From 60f11d69155659eb8ed46eb60c0fa3fa2c48fb77 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:54:52 +0100 Subject: radio-typhoon: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-typhoon.c | 352 ++++++++++++------------------ 1 file changed, 142 insertions(+), 210 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-typhoon.c b/linux/drivers/media/radio/radio-typhoon.c index bf812fbb5..11e3775ab 100644 --- a/linux/drivers/media/radio/radio-typhoon.c +++ b/linux/drivers/media/radio/radio-typhoon.c @@ -34,38 +34,17 @@ #include /* Modules */ #include /* Initdata */ #include /* request_region */ -#include /* radio card status report */ -#include -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" +#include /* for KERNEL_VERSION MACRO */ #include /* kernel radio structs */ -#include +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* 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 +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_device { - unsigned long in_use; - int iobase; +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 struct typhoon typhoon_card; -static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) +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(struct typhoon_device *dev, 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_device *dev) 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 typhoon_device *dev) 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 *file, void *priv, { 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 *file, void *priv, 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_g_tuner(struct file *file, void *priv, 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, +static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct typhoon_device *typhoon = video_drvdata(file); + struct typhoon *dev = video_drvdata(file); - typhoon->curfreq = f->frequency; - typhoon_setfreq(typhoon, typhoon->curfreq); + f->type = V4L2_TUNER_RADIO; + f->frequency = dev->curfreq; return 0; } -static int vidioc_g_frequency(struct file *file, void *priv, +static int vidioc_s_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_queryctrl(struct file *file, void *priv, 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,33 +255,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 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_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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -311,45 +279,62 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; + return i ? -EINVAL : 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; - return 0; + return a->index ? -EINVAL : 0; } -static struct typhoon_device typhoon_unit = +static int vidioc_log_status(struct file *file, void *priv) { - .iobase = CONFIG_RADIO_TYPHOON_PORT, - .curfreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, - .mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ, -}; + 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_exclusive_open(struct file *file) +static int typhoon_open(struct file *file) { - return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0; + return 0; } -static int typhoon_exclusive_release(struct file *file) +static int typhoon_release(struct file *file) { - clear_bit(0, &typhoon_unit.in_use); 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 typhoon_ioctl_ops = { .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) +static int __init typhoon_init(void) { - return single_open(file, typhoon_proc_show, NULL); -} + struct typhoon *dev = &typhoon_card; + struct v4l2_device *v4l2_dev = &dev->v4l2_dev; + int res; -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 */ + strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name)); + dev->io = io; + dev->curfreq = dev->mutefreq = mutefreq; -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"); + 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 + typhoon_mute(dev); return 0; } -static void __exit typhoon_cleanup_module(void) +static void __exit typhoon_exit(void) { + struct typhoon *dev = &typhoon_card; -#ifdef CONFIG_RADIO_TYPHOON_PROC_FS - remove_proc_entry("driver/radio-typhoon", NULL); -#endif - - video_unregister_device(&typhoon_radio); - release_region(io, 8); + 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); -- cgit v1.2.3 From 8cf31fefb7f2a3a6c95c9f66fc63e00ec6b0bec0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 6 Mar 2009 17:55:34 +0100 Subject: radio-zoltrix: convert to v4l2_device. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-zoltrix.c | 381 ++++++++++++++---------------- 1 file changed, 179 insertions(+), 202 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 4654ecd8b..93bc72adb 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -33,34 +33,18 @@ #include /* Initdata */ #include /* request_region */ #include /* udelay, msleep */ -#include /* outb, outb_p */ -#include /* copy to/from user */ -#include "compat.h" #include /* kernel radio structs */ -#include +#include +#include /* for KERNEL_VERSION MACRO */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include #include +#include "compat.h" -#include /* for KERNEL_VERSION MACRO */ -#define RADIO_VERSION KERNEL_VERSION(0,0,2) - -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 = 4096, - .default_value = 0xff, - .type = V4L2_CTRL_TYPE_INTEGER, - } -}; +MODULE_AUTHOR("C.van Schaik"); +MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); +MODULE_LICENSE("GPL"); #ifndef CONFIG_RADIO_ZOLTRIX_PORT #define CONFIG_RADIO_ZOLTRIX_PORT -1 @@ -69,9 +53,16 @@ static struct v4l2_queryctrl radio_qctrl[] = { static int io = CONFIG_RADIO_ZOLTRIX_PORT; static int radio_nr = -1; -struct zol_device { - unsigned long in_use; - int port; +module_param(io, int, 0); +MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0, 0, 2) + +struct zoltrix { + struct v4l2_device v4l2_dev; + struct video_device vdev; + int io; int curvol; unsigned long curfreq; int muted; @@ -79,161 +70,158 @@ struct zol_device { struct mutex lock; }; -static int zol_setvol(struct zol_device *dev, int vol) +static struct zoltrix zoltrix_card; + +static int zol_setvol(struct zoltrix *zol, int vol) { - dev->curvol = vol; - if (dev->muted) + zol->curvol = vol; + if (zol->muted) return 0; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); if (vol == 0) { - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); return 0; } - outb(dev->curvol-1, io); + outb(zol->curvol-1, zol->io); msleep(10); - inb(io + 2); - mutex_unlock(&dev->lock); + inb(zol->io + 2); + mutex_unlock(&zol->lock); return 0; } -static void zol_mute(struct zol_device *dev) +static void zol_mute(struct zoltrix *zol) { - dev->muted = 1; - mutex_lock(&dev->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ - mutex_unlock(&dev->lock); + zol->muted = 1; + mutex_lock(&zol->lock); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ + mutex_unlock(&zol->lock); } -static void zol_unmute(struct zol_device *dev) +static void zol_unmute(struct zoltrix *zol) { - dev->muted = 0; - zol_setvol(dev, dev->curvol); + zol->muted = 0; + zol_setvol(zol, zol->curvol); } -static int zol_setfreq(struct zol_device *dev, unsigned long freq) +static int zol_setfreq(struct zoltrix *zol, unsigned long freq) { /* tunes the radio to the desired frequency */ + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; unsigned long long bitmask, f, m; - unsigned int stereo = dev->stereo; + unsigned int stereo = zol->stereo; int i; if (freq == 0) { - printk(KERN_WARNING "zoltrix: received zero freq. Failed to set.\n"); + v4l2_warn(v4l2_dev, "cannot set a frequency of 0.\n"); return -EINVAL; } m = (freq / 160 - 8800) * 2; - f = (unsigned long long) m + 0x4d1c; + f = (unsigned long long)m + 0x4d1c; bitmask = 0xc480402c10080000ull; i = 45; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0, io); - outb(0, io); - inb(io + 3); /* Zoltrix needs to be read to confirm */ + zol->curfreq = freq; - outb(0x40, io); - outb(0xc0, io); + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); /* Zoltrix needs to be read to confirm */ - bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31)); + outb(0x40, zol->io); + outb(0xc0, zol->io); + + bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ (stereo << 31)); while (i--) { if ((bitmask & 0x8000000000000000ull) != 0) { - outb(0x80, io); + outb(0x80, zol->io); udelay(50); - outb(0x00, io); + outb(0x00, zol->io); udelay(50); - outb(0x80, io); + outb(0x80, zol->io); udelay(50); } else { - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); - outb(0x40, io); + outb(0x40, zol->io); udelay(50); - outb(0xc0, io); + outb(0xc0, zol->io); udelay(50); } bitmask *= 2; } /* termination sequence */ - outb(0x80, io); - outb(0xc0, io); - outb(0x40, io); + outb(0x80, zol->io); + outb(0xc0, zol->io); + outb(0x40, zol->io); udelay(1000); - inb(io+2); + inb(zol->io + 2); udelay(1000); - if (dev->muted) - { - outb(0, io); - outb(0, io); - inb(io + 3); + if (zol->muted) { + outb(0, zol->io); + outb(0, zol->io); + inb(zol->io + 3); udelay(1000); } - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if(!dev->muted) - { - zol_setvol(dev, dev->curvol); - } + if (!zol->muted) + zol_setvol(zol, zol->curvol); return 0; } /* Get signal strength */ - -static int zol_getsigstr(struct zol_device *dev) +static int zol_getsigstr(struct zoltrix *zol) { int a, b; - mutex_lock(&dev->lock); - outb(0x00, io); /* This stuff I found to do nothing */ - outb(dev->curvol, io); + mutex_lock(&zol->lock); + outb(0x00, zol->io); /* This stuff I found to do nothing */ + outb(zol->curvol, zol->io); msleep(20); - a = inb(io); + a = inb(zol->io); msleep(10); - b = inb(io); + b = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); if (a != b) - return (0); + return 0; - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ - || (a == 0xef)) /* with a binary scanner on the card io */ - return (1); - return (0); + /* I found this out by playing with a binary scanner on the card io */ + return a == 0xcf || a == 0xdf || a == 0xef; } -static int zol_is_stereo (struct zol_device *dev) +static int zol_is_stereo(struct zoltrix *zol) { int x1, x2; - mutex_lock(&dev->lock); + mutex_lock(&zol->lock); - outb(0x00, io); - outb(dev->curvol, io); + outb(0x00, zol->io); + outb(zol->curvol, zol->io); msleep(20); - x1 = inb(io); + x1 = inb(zol->io); msleep(10); - x2 = inb(io); + x2 = inb(zol->io); - mutex_unlock(&dev->lock); + mutex_unlock(&zol->lock); - if ((x1 == x2) && (x1 == 0xcf)) - return 1; - return 0; + return x1 == x2 && x1 == 0xcf; } static int vidioc_querycap(struct file *file, void *priv, @@ -241,59 +229,54 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-zoltrix", sizeof(v->driver)); strlcpy(v->card, "Zoltrix 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; } static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = 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 = (88*16000); - v->rangehigh = (108*16000); - v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->rangelow = 88 * 16000; + v->rangehigh = 108 * 16000; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = V4L2_TUNER_CAP_LOW; if (zol_is_stereo(zol)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF*zol_getsigstr(zol); + v->signal = 0xFFFF * zol_getsigstr(zol); 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 zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); - zol->curfreq = f->frequency; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, f->frequency) != 0) return -EINVAL; - } return 0; } static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { - struct zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); f->type = V4L2_TUNER_RADIO; f->frequency = zol->curfreq; @@ -303,14 +286,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, 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, 4096, 65535); } return -EINVAL; } @@ -318,7 +298,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 zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -334,7 +314,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 zol_device *zol = video_drvdata(file); + struct zoltrix *zol = video_drvdata(file); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -342,43 +322,30 @@ static int vidioc_s_ctrl(struct file *file, void *priv, zol_mute(zol); else { zol_unmute(zol); - zol_setvol(zol,zol->curvol); + zol_setvol(zol, zol->curvol); } return 0; case V4L2_CID_AUDIO_VOLUME: - zol_setvol(zol,ctrl->value/4096); + zol_setvol(zol, ctrl->value / 4096); return 0; } zol->stereo = 1; - if (zol_setfreq(zol, zol->curfreq) != 0) { - printk(KERN_WARNING "zoltrix: Set frequency failed.\n"); + if (zol_setfreq(zol, zol->curfreq) != 0) return -EINVAL; - } #if 0 /*keep*/ /* FIXME: Implement stereo/mono switch on V4L2 */ - if (v->mode & VIDEO_SOUND_STEREO) { - zol->stereo = 1; - zol_setfreq(zol, zol->curfreq); - } - if (v->mode & VIDEO_SOUND_MONO) { - zol->stereo = 0; - zol_setfreq(zol, zol->curfreq); - } + if (v->mode & VIDEO_SOUND_STEREO) { + zol->stereo = 1; + zol_setfreq(zol, zol->curfreq); + } + if (v->mode & VIDEO_SOUND_MONO) { + zol->stereo = 0; + zol_setfreq(zol, zol->curfreq); + } #endif return -EINVAL; } -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; -} - static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) { *i = 0; @@ -387,37 +354,39 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) { - if (i != 0) - return -EINVAL; - return 0; + return i ? -EINVAL : 0; } -static int vidioc_s_audio(struct file *file, void *priv, +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { - if (a->index != 0) - return -EINVAL; + a->index = 0; + strlcpy(a->name, "Radio", sizeof(a->name)); + a->capability = V4L2_AUDCAP_STEREO; return 0; } -static struct zol_device zoltrix_unit; +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return a->index ? -EINVAL : 0; +} -static int zoltrix_exclusive_open(struct file *file) +static int zoltrix_open(struct file *file) { - return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0; + return 0; } -static int zoltrix_exclusive_release(struct file *file) +static int zoltrix_release(struct file *file) { - clear_bit(0, &zoltrix_unit.in_use); return 0; } static const struct v4l2_file_operations zoltrix_fops = { .owner = THIS_MODULE, - .open = zoltrix_exclusive_open, - .release = zoltrix_exclusive_release, + .open = zoltrix_open, + .release = zoltrix_release, .ioctl = video_ioctl2, }; @@ -436,67 +405,75 @@ static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = { .vidioc_s_ctrl = vidioc_s_ctrl, }; -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) { - if (io == -1) { - printk(KERN_ERR "You must set an I/O address with io=0x???\n"); + struct zoltrix *zol = &zoltrix_card; + struct v4l2_device *v4l2_dev = &zol->v4l2_dev; + int res; + + strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); + zol->io = io; + if (zol->io == -1) { + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if ((io != 0x20c) && (io != 0x30c)) { - printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n"); + if (zol->io != 0x20c && zol->io != 0x30c) { + v4l2_err(v4l2_dev, "invalid port, try 0x20c or 0x30c\n"); return -ENXIO; } - 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); + if (!request_region(zol->io, 2, "zoltrix")) { + v4l2_err(v4l2_dev, "port 0x%x already in use\n", zol->io); return -EBUSY; } - if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) { - release_region(io, 2); + res = v4l2_device_register(NULL, v4l2_dev); + if (res < 0) { + release_region(zol->io, 2); + v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); + return res; + } + + strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name)); + zol->vdev.v4l2_dev = v4l2_dev; + zol->vdev.fops = &zoltrix_fops; + zol->vdev.ioctl_ops = &zoltrix_ioctl_ops; + zol->vdev.release = video_device_release_empty; + video_set_drvdata(&zol->vdev, zol); + + if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_device_unregister(v4l2_dev); + release_region(zol->io, 2); return -EINVAL; } - printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); + v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n"); - mutex_init(&zoltrix_unit.lock); + mutex_init(&zol->lock); /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */ - outb(0, io); - outb(0, io); + outb(0, zol->io); + outb(0, zol->io); msleep(20); - inb(io + 3); + inb(zol->io + 3); - zoltrix_unit.curvol = 0; - zoltrix_unit.stereo = 1; + zol->curvol = 0; + zol->stereo = 1; return 0; } -MODULE_AUTHOR("C.van Schaik"); -MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus."); -MODULE_LICENSE("GPL"); - -module_param(io, int, 0); -MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)"); -module_param(radio_nr, int, 0); - -static void __exit zoltrix_cleanup_module(void) +static void __exit zoltrix_exit(void) { - video_unregister_device(&zoltrix_radio); - release_region(io, 2); + struct zoltrix *zol = &zoltrix_card; + + video_unregister_device(&zol->vdev); + v4l2_device_unregister(&zol->v4l2_dev); + release_region(zol->io, 2); } module_init(zoltrix_init); -module_exit(zoltrix_cleanup_module); +module_exit(zoltrix_exit); -- cgit v1.2.3 From 74c1d5f410c25958fd587a05987e654bb9104d22 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Mar 2009 12:11:21 +0100 Subject: ISA radio drivers: improve kernel log message From: Hans Verkuil It's much nicer if the log message tells you which io ports are possible, rather than having to run modinfo or look it up in the source or manual. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/radio/radio-aimslab.c | 2 +- linux/drivers/media/radio/radio-aztech.c | 2 +- linux/drivers/media/radio/radio-cadet.c | 3 ++- linux/drivers/media/radio/radio-terratec.c | 2 +- linux/drivers/media/radio/radio-trust.c | 2 +- linux/drivers/media/radio/radio-zoltrix.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) (limited to 'linux/drivers/media/radio') diff --git a/linux/drivers/media/radio/radio-aimslab.c b/linux/drivers/media/radio/radio-aimslab.c index 57b896968..7c3a81ad9 100644 --- a/linux/drivers/media/radio/radio-aimslab.c +++ b/linux/drivers/media/radio/radio-aimslab.c @@ -399,7 +399,7 @@ static int __init rtrack_init(void) rt->io = io; if (rt->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x20f or 0x30f\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-aztech.c b/linux/drivers/media/radio/radio-aztech.c index dcf53edc2..8826b90a3 100644 --- a/linux/drivers/media/radio/radio-aztech.c +++ b/linux/drivers/media/radio/radio-aztech.c @@ -362,7 +362,7 @@ static int __init aztech_init(void) az->io = io; if (az->io == -1) { - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x350 or 0x358\n"); return -EINVAL; } diff --git a/linux/drivers/media/radio/radio-cadet.c b/linux/drivers/media/radio/radio-cadet.c index 03e76bc74..373a34fde 100644 --- a/linux/drivers/media/radio/radio-cadet.c +++ b/linux/drivers/media/radio/radio-cadet.c @@ -686,7 +686,8 @@ static int __init cadet_init(void) /* Else we bail out */ if (dev->io < 0) { #ifdef MODULE - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x330, 0x332, 0x334,\n"); + v4l2_err(v4l2_dev, "0x336, 0x338, 0x33a, 0x33c or 0x33e\n"); #endif goto fail; } diff --git a/linux/drivers/media/radio/radio-terratec.c b/linux/drivers/media/radio/radio-terratec.c index b63443076..9bb1773ca 100644 --- a/linux/drivers/media/radio/radio-terratec.c +++ b/linux/drivers/media/radio/radio-terratec.c @@ -376,7 +376,7 @@ static int __init terratec_init(void) 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"); + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x590 or 0x591\n"); return -EINVAL; } if (!request_region(tt->io, 2, "terratec")) { diff --git a/linux/drivers/media/radio/radio-trust.c b/linux/drivers/media/radio/radio-trust.c index 196db11de..9d2dcb0a7 100644 --- a/linux/drivers/media/radio/radio-trust.c +++ b/linux/drivers/media/radio/radio-trust.c @@ -384,7 +384,7 @@ static int __init trust_init(void) mutex_init(&tr->lock); if (tr->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x0x350 or 0x358\n"); return -EINVAL; } if (!request_region(tr->io, 2, "Trust FM Radio")) { diff --git a/linux/drivers/media/radio/radio-zoltrix.c b/linux/drivers/media/radio/radio-zoltrix.c index 93bc72adb..3662f68da 100644 --- a/linux/drivers/media/radio/radio-zoltrix.c +++ b/linux/drivers/media/radio/radio-zoltrix.c @@ -414,7 +414,7 @@ static int __init zoltrix_init(void) strlcpy(v4l2_dev->name, "zoltrix", sizeof(v4l2_dev->name)); zol->io = io; if (zol->io == -1) { - v4l2_err(v4l2_dev, "You must set an I/O address with io=0x???\n"); + v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or 0x30c\n"); return -EINVAL; } if (zol->io != 0x20c && zol->io != 0x30c) { -- cgit v1.2.3