X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fradio%2Fradio-zoltrix.c;h=671fe1b1e5bcec6a028c71804699db75dfb976d4;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d590e80c922e336a69d610f26f18f3cf28898652;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index d590e80c9..671fe1b1e 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -1,7 +1,7 @@ /* zoltrix radio plus driver for Linux radio support * (c) 1998 C. van Schaik * - * BUGS + * BUGS * Due to the inconsistency in reading from the signal flags * it is difficult to get an accurate tuned signal. * @@ -14,7 +14,7 @@ * * 1999-05-06 - (C. van Schaik) * - Make signal strength and stereo scans - * kinder to cpu while in delay + * kinder to cpu while in delay * 1999-01-05 - (C. van Schaik) * - Changed tuning to 1/160Mhz accuracy * - Added stereo support @@ -24,6 +24,9 @@ * - Added unmute function * - Reworked ioctl functions * 2002-07-15 - Fix Stereo typo + * + * 2006-07-24 - Converted to V4L2 API + * by Mauro Carvalho Chehab */ #include /* Modules */ @@ -32,8 +35,30 @@ #include /* udelay, msleep */ #include /* outb, outb_p */ #include /* copy to/from user */ -#include /* kernel radio structs */ -#include /* CONFIG_RADIO_ZOLTRIX_PORT */ +#include /* kernel radio structs */ +#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 = 4096, + .default_value = 0xff, + .type = V4L2_CTRL_TYPE_INTEGER, + } +}; #ifndef CONFIG_RADIO_ZOLTRIX_PORT #define CONFIG_RADIO_ZOLTRIX_PORT -1 @@ -48,7 +73,7 @@ struct zol_device { unsigned long curfreq; int muted; unsigned int stereo; - struct semaphore lock; + struct mutex lock; }; static int zol_setvol(struct zol_device *dev, int vol) @@ -57,30 +82,30 @@ static int zol_setvol(struct zol_device *dev, int vol) if (dev->muted) return 0; - down(&dev->lock); + mutex_lock(&dev->lock); if (vol == 0) { outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } outb(dev->curvol-1, io); msleep(10); inb(io + 2); - up(&dev->lock); + mutex_unlock(&dev->lock); return 0; } static void zol_mute(struct zol_device *dev) { dev->muted = 1; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ - up(&dev->lock); + mutex_unlock(&dev->lock); } static void zol_unmute(struct zol_device *dev) @@ -104,8 +129,8 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) bitmask = 0xc480402c10080000ull; i = 45; - down(&dev->lock); - + mutex_lock(&dev->lock); + outb(0, io); outb(0, io); inb(io + 3); /* Zoltrix needs to be read to confirm */ @@ -139,8 +164,8 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) udelay(1000); inb(io+2); - udelay(1000); - + udelay(1000); + if (dev->muted) { outb(0, io); @@ -148,12 +173,12 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq) inb(io + 3); udelay(1000); } - - up(&dev->lock); - + + mutex_unlock(&dev->lock); + if(!dev->muted) { - zol_setvol(dev, dev->curvol); + zol_setvol(dev, dev->curvol); } return 0; } @@ -164,7 +189,7 @@ static int zol_getsigstr(struct zol_device *dev) { int a, b; - down(&dev->lock); + mutex_lock(&dev->lock); outb(0x00, io); /* This stuff I found to do nothing */ outb(dev->curvol, io); msleep(20); @@ -173,23 +198,23 @@ static int zol_getsigstr(struct zol_device *dev) msleep(10); b = inb(io); - up(&dev->lock); - + mutex_unlock(&dev->lock); + if (a != b) return (0); - if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */ + 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); + return (0); } static int zol_is_stereo (struct zol_device *dev) { int x1, x2; - down(&dev->lock); - + mutex_lock(&dev->lock); + outb(0x00, io); outb(dev->curvol, io); msleep(20); @@ -198,8 +223,8 @@ static int zol_is_stereo (struct zol_device *dev) msleep(10); x2 = inb(io); - up(&dev->lock); - + mutex_unlock(&dev->lock); + if ((x1 == x2) && (x1 == 0xcf)) return 1; return 0; @@ -212,78 +237,116 @@ static int zol_do_ioctl(struct inode *inode, struct file *file, struct zol_device *zol = dev->priv; switch (cmd) { - case VIDIOCGCAP: + case VIDIOC_QUERYCAP: { - struct video_capability *v = arg; - + struct v4l2_capability *v = arg; memset(v,0,sizeof(*v)); - v->type = VID_TYPE_TUNER; - v->channels = 1 + zol->stereo; - v->audios = 1; - strcpy(v->name, "Zoltrix Radio"); + strlcpy(v->driver, "radio-zoltrix", sizeof (v->driver)); + strlcpy(v->card, "Zoltrix Radio", sizeof (v->card)); + sprintf(v->bus_info,"ISA"); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER; + return 0; } - case VIDIOCGTUNER: + case VIDIOC_G_TUNER: { - struct video_tuner *v = arg; - if (v->tuner) + struct v4l2_tuner *v = arg; + + if (v->index > 0) return -EINVAL; + + memset(v,0,sizeof(*v)); strcpy(v->name, "FM"); - v->rangelow = (int) (88.0 * 16000); - v->rangehigh = (int) (108.0 * 16000); - v->flags = zol_is_stereo(zol) - ? VIDEO_TUNER_STEREO_ON : 0; - v->flags |= VIDEO_TUNER_LOW; - v->mode = VIDEO_MODE_AUTO; - v->signal = 0xFFFF * zol_getsigstr(zol); + v->type = V4L2_TUNER_RADIO; + + 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); + return 0; } - case VIDIOCSTUNER: + case VIDIOC_S_TUNER: { - struct video_tuner *v = arg; - if (v->tuner != 0) + struct v4l2_tuner *v = arg; + + if (v->index > 0) return -EINVAL; - /* Only 1 tuner so no setting needed ! */ + return 0; } - case VIDIOCGFREQ: - { - unsigned long *freq = arg; - *freq = zol->curfreq; - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *freq = arg; - zol->curfreq = *freq; - zol_setfreq(zol, zol->curfreq); - return 0; - } - case VIDIOCGAUDIO: + case VIDIOC_S_FREQUENCY: { - struct video_audio *v = arg; - memset(v, 0, sizeof(*v)); - v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - v->mode |= zol_is_stereo(zol) - ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; - v->volume = zol->curvol * 4096; - v->step = 4096; - strcpy(v->name, "Zoltrix Radio"); + struct v4l2_frequency *f = arg; + + zol->curfreq = f->frequency; + zol_setfreq(zol, zol->curfreq); return 0; } - case VIDIOCSAUDIO: + case VIDIOC_G_FREQUENCY: { - struct video_audio *v = arg; - if (v->audio) - return -EINVAL; + struct v4l2_frequency *f = arg; - if (v->flags & VIDEO_AUDIO_MUTE) - zol_mute(zol); - else { - zol_unmute(zol); - zol_setvol(zol, v->volume / 4096); - } + f->type = V4L2_TUNER_RADIO; + f->frequency = zol->curfreq; + return 0; + } + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + 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; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *ctrl= arg; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value=zol->muted; + return (0); + case V4L2_CID_AUDIO_VOLUME: + ctrl->value=zol->curvol * 4096; + return (0); + } + return -EINVAL; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl= arg; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + zol_mute(zol); + } else { + zol_unmute(zol); + zol_setvol(zol,zol->curvol); + } + return (0); + case V4L2_CID_AUDIO_VOLUME: + zol_setvol(zol,ctrl->value/4096); + return (0); + } + zol->stereo = 1; + zol_setfreq(zol, zol->curfreq); +#if 0 +/* FIXME: Implement stereo/mono switch on V4L2 */ if (v->mode & VIDEO_SOUND_STEREO) { zol->stereo = 1; zol_setfreq(zol, zol->curfreq); @@ -292,10 +355,13 @@ static int zol_do_ioctl(struct inode *inode, struct file *file, zol->stereo = 0; zol_setfreq(zol, zol->curfreq); } - return 0; +#endif + return -EINVAL; } - default: - return -ENOIOCTLCMD; + + default: + return v4l_compat_translate_ioctl(inode,file,cmd,arg, + zol_do_ioctl); } } @@ -322,7 +388,7 @@ static struct video_device zoltrix_radio = .owner = THIS_MODULE, .name = "Zoltrix Radio Plus", .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_ZOLTRIX, + .hardware = 0, .fops = &zoltrix_fops, }; @@ -350,8 +416,8 @@ static int __init zoltrix_init(void) } printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); - init_MUTEX(&zoltrix_unit.lock); - + mutex_init(&zoltrix_unit.lock); + /* mute card - prevents noisy bootups */ /* this ensures that the volume is all the way down */