V4L/DVB (4353): V4L2 conversion: radio-sf16fmi

Driver conversion to V4L2 API.
Require some testing, since this obsolete hardware is not
common those days.

Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Mauro Carvalho Chehab 2006-08-08 09:10:02 -03:00
parent f8c559f8c0
commit a2ef73af4c
2 changed files with 101 additions and 58 deletions

View File

@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS
config RADIO_SF16FMI config RADIO_SF16FMI
tristate "SF16FMI Radio" tristate "SF16FMI Radio"
depends on ISA && VIDEO_V4L1 depends on ISA && VIDEO_V4L2
---help--- ---help---
Choose Y here if you have one of these FM radio cards. If you Choose Y here if you have one of these FM radio cards. If you
compile the driver into the kernel and your card is not PnP one, you compile the driver into the kernel and your card is not PnP one, you

View File

@ -13,6 +13,7 @@
* No volume control - only mute/unmute - you have to use line volume * No volume control - only mute/unmute - you have to use line volume
* control on SB-part of SF16FMI * control on SB-part of SF16FMI
* *
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
*/ */
#include <linux/kernel.h> /* __setup */ #include <linux/kernel.h> /* __setup */
@ -20,13 +21,26 @@
#include <linux/init.h> /* Initdata */ #include <linux/init.h> /* Initdata */
#include <linux/ioport.h> /* request_region */ #include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */ #include <linux/delay.h> /* udelay */
#include <linux/videodev.h> /* kernel radio structs */ #include <linux/videodev2.h> /* kernel radio structs */
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <linux/isapnp.h> #include <linux/isapnp.h>
#include <asm/io.h> /* outb, outb_p */ #include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */ #include <asm/uaccess.h> /* copy to/from user */
#include <linux/mutex.h> #include <linux/mutex.h>
#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,
}
};
struct fmi_device struct fmi_device
{ {
int port; int port;
@ -123,93 +137,122 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file,
switch(cmd) switch(cmd)
{ {
case VIDIOCGCAP: case VIDIOC_QUERYCAP:
{ {
struct video_capability *v = arg; struct v4l2_capability *v = arg;
memset(v,0,sizeof(*v)); memset(v,0,sizeof(*v));
strcpy(v->name, "SF16-FMx radio"); strlcpy(v->driver, "radio-sf16fmi", sizeof (v->driver));
v->type=VID_TYPE_TUNER; strlcpy(v->card, "SF16-FMx radio", sizeof (v->card));
v->channels=1; sprintf(v->bus_info,"ISA");
v->audios=1; v->version = RADIO_VERSION;
v->capabilities = V4L2_CAP_TUNER;
return 0; return 0;
} }
case VIDIOCGTUNER: case VIDIOC_G_TUNER:
{ {
struct video_tuner *v = arg; struct v4l2_tuner *v = arg;
int mult; int mult;
if(v->tuner) /* Only 1 tuner */ if (v->index > 0)
return -EINVAL; return -EINVAL;
memset(v,0,sizeof(*v));
strcpy(v->name, "FM"); strcpy(v->name, "FM");
mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000; v->type = V4L2_TUNER_RADIO;
mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
v->rangelow = RSF16_MINFREQ/mult; v->rangelow = RSF16_MINFREQ/mult;
v->rangehigh = RSF16_MAXFREQ/mult; v->rangehigh = RSF16_MAXFREQ/mult;
v->flags=fmi->flags; v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
v->mode=VIDEO_MODE_AUTO; v->capability=fmi->flags;
v->audmode = V4L2_TUNER_MODE_STEREO;
v->signal = fmi_getsigstr(fmi); v->signal = fmi_getsigstr(fmi);
return 0; return 0;
} }
case VIDIOCSTUNER: case VIDIOC_S_TUNER:
{ {
struct video_tuner *v = arg; struct v4l2_tuner *v = arg;
if(v->tuner!=0)
if (v->index > 0)
return -EINVAL; return -EINVAL;
fmi->flags = v->flags & VIDEO_TUNER_LOW;
/* Only 1 tuner so no setting needed ! */
return 0; return 0;
} }
case VIDIOCGFREQ: case VIDIOC_S_FREQUENCY:
{ {
unsigned long *freq = arg; struct v4l2_frequency *f = arg;
*freq = fmi->curfreq;
if (!(fmi->flags & VIDEO_TUNER_LOW)) if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
*freq /= 1000; f->frequency *= 1000;
return 0; if (f->frequency < RSF16_MINFREQ ||
} f->frequency > RSF16_MAXFREQ )
case VIDIOCSFREQ:
{
unsigned long *freq = arg;
if (!(fmi->flags & VIDEO_TUNER_LOW))
*freq *= 1000;
if (*freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ )
return -EINVAL; return -EINVAL;
/*rounding in steps of 800 to match th freq /*rounding in steps of 800 to match th freq
that will be used */ that will be used */
fmi->curfreq = (*freq/800)*800; fmi->curfreq = (f->frequency/800)*800;
fmi_setfreq(fmi); fmi_setfreq(fmi);
return 0; return 0;
} }
case VIDIOCGAUDIO: case VIDIOC_G_FREQUENCY:
{ {
struct video_audio *v = arg; struct v4l2_frequency *f = arg;
memset(v,0,sizeof(*v));
v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); f->type = V4L2_TUNER_RADIO;
strcpy(v->name, "Radio"); f->frequency = fmi->curfreq;
v->mode=VIDEO_SOUND_STEREO; if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
f->frequency /= 1000;
return 0; return 0;
} }
case VIDIOCSAUDIO: case VIDIOC_QUERYCTRL:
{ {
struct video_audio *v = arg; struct v4l2_queryctrl *qc = arg;
if(v->audio) int i;
return -EINVAL;
fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1; for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
fmi->curvol ? if (qc->id && qc->id == radio_qctrl[i].id) {
fmi_unmute(fmi->port) : fmi_mute(fmi->port); memcpy(qc, &(radio_qctrl[i]),
return 0; sizeof(*qc));
return (0);
}
}
return -EINVAL;
} }
case VIDIOCGUNIT: case VIDIOC_G_CTRL:
{ {
struct video_unit *v = arg; struct v4l2_control *ctrl= arg;
v->video=VIDEO_NO_UNIT;
v->vbi=VIDEO_NO_UNIT; switch (ctrl->id) {
v->radio=dev->minor; case V4L2_CID_AUDIO_MUTE:
v->audio=0; /* How do we find out this??? */ ctrl->value=fmi->curvol;
v->teletext=VIDEO_NO_UNIT; return (0);
return 0; }
return -EINVAL;
}
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl= arg;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
{
if (ctrl->value)
fmi_mute(fmi->port);
else
fmi_unmute(fmi->port);
fmi->curvol=ctrl->value;
return (0);
}
}
return -EINVAL;
} }
default: default:
return -ENOIOCTLCMD; return v4l_compat_translate_ioctl(inode,file,cmd,arg,
fmi_do_ioctl);
} }
} }
@ -235,7 +278,7 @@ static struct video_device fmi_radio=
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "SF16FMx radio", .name = "SF16FMx radio",
.type = VID_TYPE_TUNER, .type = VID_TYPE_TUNER,
.hardware = VID_HARDWARE_SF16MI, .hardware = 0,
.fops = &fmi_fops, .fops = &fmi_fops,
}; };
@ -294,7 +337,7 @@ static int __init fmi_init(void)
fmi_unit.port = io; fmi_unit.port = io;
fmi_unit.curvol = 0; fmi_unit.curvol = 0;
fmi_unit.curfreq = 0; fmi_unit.curfreq = 0;
fmi_unit.flags = VIDEO_TUNER_LOW; fmi_unit.flags = V4L2_TUNER_CAP_LOW;
fmi_radio.priv = &fmi_unit; fmi_radio.priv = &fmi_unit;
mutex_init(&lock); mutex_init(&lock);