Commit a2ef73af authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

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: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent f8c559f8
...@@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS ...@@ -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
......
...@@ -13,6 +13,7 @@ ...@@ -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 @@ ...@@ -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, ...@@ -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;
}
case VIDIOCGFREQ:
{
unsigned long *freq = arg;
*freq = fmi->curfreq;
if (!(fmi->flags & VIDEO_TUNER_LOW))
*freq /= 1000;
return 0; return 0;
} }
case VIDIOCSFREQ: case VIDIOC_S_FREQUENCY:
{ {
unsigned long *freq = arg; struct v4l2_frequency *f = arg;
if (!(fmi->flags & VIDEO_TUNER_LOW))
*freq *= 1000; if (!(fmi->flags & V4L2_TUNER_CAP_LOW))
if (*freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) f->frequency *= 1000;
if (f->frequency < RSF16_MINFREQ ||
f->frequency > 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;
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
if (qc->id && qc->id == radio_qctrl[i].id) {
memcpy(qc, &(radio_qctrl[i]),
sizeof(*qc));
return (0);
}
}
return -EINVAL; return -EINVAL;
fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1;
fmi->curvol ?
fmi_unmute(fmi->port) : fmi_mute(fmi->port);
return 0;
} }
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= ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment