X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fradio%2Fradio-maxiradio.c;h=c2eeae7a10d02eb37e65f1b430ca3deb959edb38;hb=refs%2Fheads%2Fvserver;hp=c975ddd86cd5257e9b8959a2f29e46381661bb1c;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index c975ddd86..c2eeae7a1 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -1,15 +1,15 @@ -/* - * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux +/* + * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux * (C) 2001 Dimitromanolakis Apostolos * * Based in the radio Maestro PCI driver. Actually it uses the same chip * for radio but different pci controller. * * I didn't have any specs I reversed engineered the protocol from - * the windows driver (radio.dll). + * the windows driver (radio.dll). * * The card uses the TEA5757 chip that includes a search function but it - * is useless as I haven't found any way to read back the frequency. If + * is useless as I haven't found any way to read back the frequency. If * anybody does please mail me. * * For the pdf file see: @@ -20,13 +20,14 @@ * 0.75b * - better pci interface thanks to Francois Romieu * - * 0.75 + * 0.75 Sun Feb 4 22:51:27 EET 2001 * - tiding up * - removed support for multiple devices as it didn't work anyway * - * BUGS: + * BUGS: * - card unmutes if you change frequency * + * Converted to V4L2 API by Mauro Carvalho Chehab */ @@ -37,12 +38,27 @@ #include #include #include -#include -#include -#include +#include -/* version 0.75 Sun Feb 4 22:51:27 EET 2001 */ -#define DRIVER_VERSION "0.75" +#include +#include +#include + +#define DRIVER_VERSION "0.76" + +#include /* for KERNEL_VERSION MACRO */ +#define RADIO_VERSION KERNEL_VERSION(0,7,6) + +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, + } +}; #ifndef PCI_VENDOR_ID_GUILLEMOT #define PCI_VENDOR_ID_GUILLEMOT 0x5046 @@ -79,7 +95,7 @@ static struct file_operations maxiradio_fops = { .owner = THIS_MODULE, .open = video_exclusive_open, .release = video_exclusive_release, - .ioctl = radio_ioctl, + .ioctl = radio_ioctl, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; @@ -88,7 +104,6 @@ static struct video_device maxiradio_radio = .owner = THIS_MODULE, .name = "Maxi Radio FM2000 radio", .type = VID_TYPE_TUNER, - .hardware = VID_HARDWARE_SF16MI, .fops = &maxiradio_fops, }; @@ -96,12 +111,12 @@ static struct radio_device { __u16 io, /* base of radio io */ muted, /* VIDEO_AUDIO_MUTE */ - stereo, /* VIDEO_TUNER_STEREO_ON */ + stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - + unsigned long freq; - - struct semaphore lock; + + struct mutex lock; } radio_unit = {0, 0, 0, 0, }; @@ -113,7 +128,7 @@ static void outbit(unsigned long bit, __u16 io) outb( power|wren|data|clk ,io); udelay(4); outb( power|wren|data ,io); udelay(4); } - else + else { outb( power|wren ,io); udelay(4); outb( power|wren|clk ,io); udelay(4); @@ -131,12 +146,12 @@ static void set_freq(__u16 io, __u32 data) { unsigned long int si; int bl; - + /* TEA5757 shift register bits (see pdf) */ - outbit(0,io); // 24 search + outbit(0,io); // 24 search outbit(1,io); // 23 search up/down - + outbit(0,io); // 22 stereo/mono outbit(0,io); // 21 band @@ -144,24 +159,24 @@ static void set_freq(__u16 io, __u32 data) outbit(0,io); // 19 port ? outbit(0,io); // 18 port ? - + outbit(0,io); // 17 search level outbit(0,io); // 16 search level - + si = 0x8000; for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; } - + outb(power,io); } static int get_stereo(__u16 io) -{ +{ outb(power,io); udelay(4); return !(inb(io) & mo_st); } static int get_tune(__u16 io) -{ +{ outb(power+clk,io); udelay(4); return !(inb(io) & mo_st); } @@ -174,89 +189,116 @@ static inline int radio_function(struct inode *inode, struct file *file, struct radio_device *card=dev->priv; switch(cmd) { - case VIDIOCGCAP: { - struct video_capability *v = arg; - + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *v = arg; memset(v,0,sizeof(*v)); - strcpy(v->name, "Maxi Radio FM2000 radio"); - v->type=VID_TYPE_TUNER; - v->channels=v->audios=1; + 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; + return 0; } - case VIDIOCGTUNER: { - struct video_tuner *v = arg; - - if(v->tuner) + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *v = arg; + + if (v->index > 0) return -EINVAL; - - card->stereo = 0xffff * get_stereo(card->io); - card->tuned = 0xffff * get_tune(card->io); - - v->flags = VIDEO_TUNER_LOW | card->stereo; - v->signal = card->tuned; - + + memset(v,0,sizeof(*v)); strcpy(v->name, "FM"); - - v->rangelow = FREQ_LO; - v->rangehigh = FREQ_HI; - v->mode = VIDEO_MODE_AUTO; - + 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->audmode = V4L2_TUNER_MODE_STEREO; + else + v->audmode = V4L2_TUNER_MODE_MONO; + v->signal=0xffff*get_tune(card->io); + return 0; } - case VIDIOCSTUNER: { - struct video_tuner *v = arg; - if(v->tuner!=0) + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *v = arg; + + if (v->index > 0) return -EINVAL; + return 0; } - case VIDIOCGFREQ: { - unsigned long *freq = arg; - - *freq = card->freq; - return 0; - } - case VIDIOCSFREQ: { - unsigned long *freq = arg; - - if (*freq < FREQ_LO || *freq > FREQ_HI) + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; - card->freq = *freq; + + card->freq = f->frequency; set_freq(card->io, FREQ2BITS(card->freq)); msleep(125); return 0; } - case VIDIOCGAUDIO: { - struct video_audio *v = arg; - memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - v->flags=VIDEO_AUDIO_MUTABLE | card->muted; - v->mode=VIDEO_SOUND_STEREO; - return 0; - } - - case VIDIOCSAUDIO: { - struct video_audio *v = arg; - - if(v->audio) - return -EINVAL; - card->muted = v->flags & VIDEO_AUDIO_MUTE; - if(card->muted) - turn_power(card->io, 0); - else - set_freq(card->io, FREQ2BITS(card->freq)); + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + f->type = V4L2_TUNER_RADIO; + f->frequency = card->freq; + return 0; } - case VIDIOCGUNIT: { - struct video_unit *v = arg; - - v->video=VIDEO_NO_UNIT; - v->vbi=VIDEO_NO_UNIT; - v->radio=dev->minor; - v->audio=0; - v->teletext=VIDEO_NO_UNIT; - 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=card->muted; + return (0); + } + return -EINVAL; } - default: return -ENOIOCTLCMD; + case VIDIOC_S_CTRL: + { + struct v4l2_control *ctrl= arg; + + 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, FREQ2BITS(card->freq)); + return 0; + } + return -EINVAL; + } + + default: + return v4l_compat_translate_ioctl(inode,file,cmd,arg, + radio_function); + } } @@ -266,10 +308,10 @@ static int radio_ioctl(struct inode *inode, struct file *file, struct video_device *dev = video_devdata(file); struct radio_device *card=dev->priv; int ret; - - down(&card->lock); + + mutex_lock(&card->lock); ret = video_usercopy(inode, file, cmd, arg, radio_function); - up(&card->lock); + mutex_unlock(&card->lock); return ret; } @@ -281,21 +323,21 @@ MODULE_LICENSE("GPL"); static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { 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"); - goto err_out; + pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { + printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); + goto err_out; } if (pci_enable_device(pdev)) - goto err_out_free_region; + goto err_out_free_region; radio_unit.io = pci_resource_start(pdev, 0); - init_MUTEX(&radio_unit.lock); + mutex_init(&radio_unit.lock); maxiradio_radio.priv = &radio_unit; if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { - printk("radio-maxiradio: can't register device!"); - goto err_out_free_region; + printk("radio-maxiradio: can't register device!"); + goto err_out_free_region; } printk(KERN_INFO "radio-maxiradio: version "