diff options
Diffstat (limited to 'linux/drivers/media/video/bt8xx/bttv-driver.c')
-rw-r--r-- | linux/drivers/media/video/bt8xx/bttv-driver.c | 141 |
1 files changed, 75 insertions, 66 deletions
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c index d34898f95..63b0043e2 100644 --- a/linux/drivers/media/video/bt8xx/bttv-driver.c +++ b/linux/drivers/media/video/bt8xx/bttv-driver.c @@ -41,6 +41,7 @@ #include <linux/fs.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/interrupt.h> #include <linux/kdev_t.h> #include "bttvp.h" @@ -171,7 +172,7 @@ static ssize_t show_card(struct class_device *cd, char *buf) #endif { struct video_device *vfd = container_of(cd, struct video_device, dev); - struct bttv *btv = dev_get_drvdata(vfd->parent); + struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) @@ -1181,7 +1182,6 @@ audio_mux(struct bttv *btv, int input, int mute) { int gpio_val, signal; struct v4l2_control ctrl; - struct i2c_client *c; gpio_inout(bttv_tvcards[btv->c.type].gpiomask, bttv_tvcards[btv->c.type].gpiomask); @@ -1220,10 +1220,9 @@ audio_mux(struct bttv *btv, int input, int mute) ctrl.id = V4L2_CID_AUDIO_MUTE; ctrl.value = btv->mute; - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, &ctrl); - c = btv->i2c_msp34xx_client; - if (c) { - struct v4l2_routing route; + bttv_call_all(btv, core, s_ctrl, &ctrl); + if (btv->sd_msp34xx) { + u32 in; /* Note: the inputs tuner/radio/extern/intern are translated to msp routings. This assumes common behavior for all msp3400 @@ -1232,11 +1231,11 @@ audio_mux(struct bttv *btv, int input, int mute) For now this is sufficient. */ switch (input) { case TVAUDIO_INPUT_RADIO: - route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_EXTERN: - route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_INTERN: @@ -1245,7 +1244,7 @@ audio_mux(struct bttv *btv, int input, int mute) input is the BTTV_BOARD_AVERMEDIA98. I wonder how that was tested. My guess is that the whole INTERN input does not work. */ - route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_TUNER: @@ -1254,22 +1253,18 @@ audio_mux(struct bttv *btv, int input, int mute) is the only difference between the VOODOOTV_FM and VOODOOTV_200 */ if (btv->c.type == BTTV_BOARD_VOODOOTV_200) - route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \ + in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \ MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER); else - route.input = MSP_INPUT_DEFAULT; + in = MSP_INPUT_DEFAULT; break; } - route.output = MSP_OUTPUT_DEFAULT; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing, + in, MSP_OUTPUT_DEFAULT, 0); } - c = btv->i2c_tvaudio_client; - if (c) { - struct v4l2_routing route; - - route.input = input; - route.output = 0; - c->driver->command(c, VIDIOC_INT_S_AUDIO_ROUTING, &route); + if (btv->sd_tvaudio) { + v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing, + input, 0, 0); } return 0; } @@ -1360,7 +1355,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm) #endif } id = tvnorm->v4l2_id; - bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id); + bttv_call_all(btv, core, s_std, id); return 0; } @@ -1504,7 +1499,7 @@ static int bttv_g_ctrl(struct file *file, void *priv, case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c); + bttv_call_all(btv, core, g_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1578,12 +1573,12 @@ static int bttv_s_ctrl(struct file *file, void *f, if (btv->volume_gpio) btv->volume_gpio(btv, c->value); - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + bttv_call_all(btv, core, s_ctrl, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -2001,7 +1996,7 @@ static int bttv_s_tuner(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); + bttv_call_all(btv, tuner, s_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 1); @@ -2046,7 +2041,7 @@ static int bttv_s_frequency(struct file *file, void *priv, return -EINVAL; mutex_lock(&btv->lock); btv->freq = f->frequency; - bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f); + bttv_call_all(btv, tuner, s_frequency, f); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv, btv->freq); mutex_unlock(&btv->lock); @@ -2060,7 +2055,7 @@ static int bttv_log_status(struct file *file, void *f) printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); - bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + bttv_call_all(btv, core, log_status); printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n", btv->c.nr, btv->c.nr); return 0; @@ -2685,6 +2680,8 @@ static int bttv_querycap(struct file *file, void *priv, V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + if (btv->has_saa6588) + cap->capabilities |= V4L2_CAP_RDS_CAPTURE; if (no_overlay <= 0) cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; @@ -2956,8 +2953,6 @@ static int bttv_g_parm(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id, &parm->parm.capture.timeperframe); return 0; @@ -2976,7 +2971,7 @@ static int bttv_g_tuner(struct file *file, void *priv, mutex_lock(&btv->lock); t->rxsubchans = V4L2_TUNER_SUB_MONO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); strcpy(t->name, "Television"); t->capability = V4L2_TUNER_CAP_NORM; t->type = V4L2_TUNER_ANALOG_TV; @@ -3188,6 +3183,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) struct bttv_fh *fh = file->private_data; struct bttv_buffer *buf; enum v4l2_field field; + unsigned int rc = POLLERR; if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI)) @@ -3196,9 +3192,10 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) } if (check_btres(fh,RESOURCE_VIDEO_STREAM)) { + mutex_lock(&fh->cap.vb_lock); /* streaming capture */ if (list_empty(&fh->cap.stream)) - return POLLERR; + goto err; buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); } else { /* read() capture */ @@ -3227,11 +3224,12 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) poll_wait(file, &buf->vb.done, wait); if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) - return POLLIN|POLLRDNORM; - return 0; + rc = POLLIN|POLLRDNORM; + else + rc = 0; err: mutex_unlock(&fh->cap.vb_lock); - return POLLERR; + return rc; } static int bttv_open(struct file *file) @@ -3467,7 +3465,7 @@ static int radio_open(struct file *file) btv->radio_user++; - bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); + bttv_call_all(btv, tuner, s_radio); audio_input(btv,TVAUDIO_INPUT_RADIO); mutex_unlock(&btv->lock); @@ -3487,7 +3485,7 @@ static int radio_release(struct file *file) btv->radio_user--; - bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd); return 0; } @@ -3520,7 +3518,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); if (btv->audio_mode_gpio) btv->audio_mode_gpio(btv, t, 0); @@ -3562,7 +3560,7 @@ static int radio_s_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + bttv_call_all(btv, tuner, g_tuner, t); return 0; } @@ -3623,7 +3621,7 @@ static ssize_t radio_read(struct file *file, char __user *data, cmd.instance = file; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_READ, &cmd); return cmd.result; } @@ -3636,7 +3634,7 @@ static unsigned int radio_poll(struct file *file, poll_table *wait) cmd.instance = file; cmd.event_list = wait; cmd.result = -ENODEV; - bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd); + bttv_call_all(btv, core, ioctl, RDS_CMD_POLL, &cmd); return cmd.result; } @@ -3720,14 +3718,14 @@ static void bttv_risc_disasm(struct bttv *btv, unsigned int i,j,n; printk("%s: risc disasm: %p [dma=0x%08lx]\n", - btv->c.name, risc->cpu, (unsigned long)risc->dma); + btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma); for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: 0x%lx: ", btv->c.name, + printk("%s: 0x%lx: ", btv->c.v4l2_dev.name, (unsigned long)(risc->dma + (i<<2))); n = bttv_risc_decode(le32_to_cpu(risc->cpu[i])); for (j = 1; j < n; j++) printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", - btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), + btv->c.v4l2_dev.name, (unsigned long)(risc->dma + ((i+j)<<2)), risc->cpu[i+j], j); if (0 == risc->cpu[i]) break; @@ -4206,8 +4204,7 @@ static struct video_device *vdev_init(struct bttv *btv, if (NULL == vfd) return NULL; *vfd = *template; - vfd->minor = -1; - vfd->parent = &btv->c.pci->dev; + vfd->v4l2_dev = &btv->c.v4l2_dev; vfd->release = video_device_release; vfd->debug = bttv_debug; video_set_drvdata(vfd, btv); @@ -4326,8 +4323,13 @@ static int __devinit bttv_probe(struct pci_dev *dev, return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL); + if (btv == NULL) { + printk(KERN_ERR "bttv: out of memory.\n"); + return -ENOMEM; + } btv->c.nr = bttv_num; - sprintf(btv->c.name,"bttv%d",btv->c.nr); + snprintf(btv->c.v4l2_dev.name, sizeof(btv->c.v4l2_dev.name), + "bttv%d", btv->c.nr); /* initialize structs / fill in defaults */ mutex_init(&btv->lock); @@ -4357,14 +4359,14 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->c.nr); return -EIO; } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) { printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", btv->c.nr); return -EIO; } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), - btv->c.name)) { + btv->c.v4l2_dev.name)) { printk(KERN_WARNING "bttv%d: can't request iomem (0x%llx).\n", btv->c.nr, (unsigned long long)pci_resource_start(dev,0)); @@ -4372,7 +4374,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, } pci_set_master(dev); pci_set_command(dev); - pci_set_drvdata(dev,btv); + + result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev); + if (result < 0) { + printk(KERN_WARNING "bttv%d: v4l2_device_register() failed\n", btv->c.nr); + goto fail0; + } pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); @@ -4396,7 +4403,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); result = request_irq(btv->c.pci->irq, bttv_irq, - IRQF_SHARED | IRQF_DISABLED,btv->c.name,(void *)btv); + IRQF_SHARED | IRQF_DISABLED, btv->c.v4l2_dev.name, (void *)btv); if (result < 0) { printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); @@ -4451,6 +4458,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* some card-specific stuff (needs working i2c) */ bttv_init_card2(btv); + bttv_init_tuner(btv); init_irqreg(btv); /* register video4linux + input */ @@ -4480,21 +4488,24 @@ static int __devinit bttv_probe(struct pci_dev *dev, bttv_num++; return 0; - fail2: +fail2: free_irq(btv->c.pci->irq,btv); - fail1: +fail1: + v4l2_device_unregister(&btv->c.v4l2_dev); + +fail0: if (btv->bt848_mmio) iounmap(btv->bt848_mmio); release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(dev,NULL); return result; } static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); @@ -4528,7 +4539,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) release_mem_region(pci_resource_start(btv->c.pci,0), pci_resource_len(btv->c.pci,0)); - pci_set_drvdata(pci_dev, NULL); + v4l2_device_unregister(&btv->c.v4l2_dev); bttvs[btv->c.nr] = NULL; kfree(btv); @@ -4538,7 +4549,8 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) #ifdef CONFIG_PM static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4573,7 +4585,8 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); + struct bttv *btv = to_bttv(v4l2_dev); unsigned long flags; int err; @@ -4619,14 +4632,10 @@ static int bttv_resume(struct pci_dev *pci_dev) #endif static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, + {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, {0,} }; @@ -4659,7 +4668,7 @@ static int __init bttv_init_module(void) #endif if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) gbuffers = 2; - if (gbufsize < 0 || gbufsize > BTTV_MAX_FBUF) + if (gbufsize > BTTV_MAX_FBUF) gbufsize = BTTV_MAX_FBUF; gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK; if (bttv_verbose) |