diff options
Diffstat (limited to 'drivers/media/radio/radio-cadet.c')
| -rw-r--r-- | drivers/media/radio/radio-cadet.c | 94 |
1 files changed, 51 insertions, 43 deletions
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 643d80ac28f..d719e59e217 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -90,6 +90,26 @@ static u16 sigtable[2][4] = { { 2185, 4369, 13107, 65535 }, }; +static const struct v4l2_frequency_band bands[] = { + { + .index = 0, + .type = V4L2_TUNER_RADIO, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 8320, /* 520 kHz */ + .rangehigh = 26400, /* 1650 kHz */ + .modulation = V4L2_BAND_MODULATION_AM, + }, { + .index = 1, + .type = V4L2_TUNER_RADIO, + .capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | + V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW | + V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 1400000, /* 87.5 MHz */ + .rangehigh = 1728000, /* 108.0 MHz */ + .modulation = V4L2_BAND_MODULATION_FM, + }, +}; + static int cadet_getstereo(struct cadet *dev) { @@ -196,6 +216,8 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq) int i, j, test; int curvol; + freq = clamp(freq, bands[dev->is_fm_band].rangelow, + bands[dev->is_fm_band].rangehigh); dev->curfreq = freq; /* * Formulate a fifo command @@ -248,6 +270,16 @@ reset_rds: outb(inb(dev->io + 1) & 0x7f, dev->io + 1); } +static bool cadet_has_rds_data(struct cadet *dev) +{ + bool result; + + mutex_lock(&dev->lock); + result = dev->rdsin != dev->rdsout; + mutex_unlock(&dev->lock); + return result; +} + static void cadet_handler(unsigned long data) { @@ -257,13 +289,12 @@ static void cadet_handler(unsigned long data) 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"); + pr_err("cadet: RDS fifo overflow\n"); outb(0x80, dev->io); /* Select RDS fifo */ + while ((inb(dev->io) & 0x80) != 0) { dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); - if (dev->rdsin + 1 == dev->rdsout) - printk(KERN_WARNING "cadet: RDS buffer overflow\n"); - else + if (dev->rdsin + 1 != dev->rdsout) dev->rdsin++; } mutex_unlock(&dev->lock); @@ -272,7 +303,7 @@ static void cadet_handler(unsigned long data) /* * Service pending read */ - if (dev->rdsin != dev->rdsout) + if (cadet_has_rds_data(dev)) wake_up_interruptible(&dev->read_queue); /* @@ -305,22 +336,21 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo mutex_lock(&dev->lock); if (dev->rdsstat == 0) cadet_start_rds(dev); - if (dev->rdsin == dev->rdsout) { - if (file->f_flags & O_NONBLOCK) { - i = -EWOULDBLOCK; - goto unlock; - } - mutex_unlock(&dev->lock); - interruptible_sleep_on(&dev->read_queue); - mutex_lock(&dev->lock); - } + mutex_unlock(&dev->lock); + + if (!cadet_has_rds_data(dev) && (file->f_flags & O_NONBLOCK)) + return -EWOULDBLOCK; + i = wait_event_interruptible(dev->read_queue, cadet_has_rds_data(dev)); + if (i) + return i; + + mutex_lock(&dev->lock); while (i < count && dev->rdsin != dev->rdsout) readbuf[i++] = dev->rdsbuf[dev->rdsout++]; + mutex_unlock(&dev->lock); if (i && copy_to_user(data, readbuf, i)) - i = -EFAULT; -unlock: - mutex_unlock(&dev->lock); + return -EFAULT; return i; } @@ -330,33 +360,13 @@ static int vidioc_querycap(struct file *file, void *priv, { 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)); + strlcpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -static const struct v4l2_frequency_band bands[] = { - { - .index = 0, - .type = V4L2_TUNER_RADIO, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 8320, /* 520 kHz */ - .rangehigh = 26400, /* 1650 kHz */ - .modulation = V4L2_BAND_MODULATION_AM, - }, { - .index = 1, - .type = V4L2_TUNER_RADIO, - .capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | - V4L2_TUNER_CAP_RDS_BLOCK_IO | V4L2_TUNER_CAP_LOW | - V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 1400000, /* 87.5 MHz */ - .rangehigh = 1728000, /* 108.0 MHz */ - .modulation = V4L2_BAND_MODULATION_FM, - }, -}; - static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { @@ -388,7 +398,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, } static int vidioc_s_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) + const struct v4l2_tuner *v) { return v->index ? -EINVAL : 0; } @@ -418,7 +428,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, static int vidioc_s_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) + const struct v4l2_frequency *f) { struct cadet *dev = video_drvdata(file); @@ -426,8 +436,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, return -EINVAL; dev->is_fm_band = f->frequency >= (bands[0].rangehigh + bands[1].rangelow) / 2; - clamp(f->frequency, bands[dev->is_fm_band].rangelow, - bands[dev->is_fm_band].rangehigh); cadet_setfreq(dev, f->frequency); return 0; } @@ -491,7 +499,7 @@ static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait cadet_start_rds(dev); mutex_unlock(&dev->lock); } - if (dev->rdsin != dev->rdsout) + if (cadet_has_rds_data(dev)) res |= POLLIN | POLLRDNORM; return res; } |
