📄 cx23885-video.c
字号:
/* When changing channels it is required to reset TVAUDIO */ msleep(10); mutex_unlock(&dev->lock); return 0;}static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) return -EINVAL; if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) return -EINVAL; return cx23885_set_freq(dev, f);}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int vidioc_g_register(struct file *file, void *fh, struct v4l2_register *reg){ struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg); return 0;}static int vidioc_s_register(struct file *file, void *fh, struct v4l2_register *reg){ struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg); return 0;}#endif#if 0/* ----------------------------------------------------------- *//* RADIO ESPECIFIC IOCTLS *//* ----------------------------------------------------------- */static int radio_querycap(struct file *file, void *priv, struct v4l2_capability *cap){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; strcpy(cap->driver, "cx23885"); strlcpy(cap->card, cx23885_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); cap->version = CX23885_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; return 0;}static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; if (unlikely(t->index > 0)) return -EINVAL; strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t); return 0;}static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i){ if (i->index != 0) return -EINVAL; strcpy(i->name, "Radio"); i->type = V4L2_INPUT_TYPE_TUNER; return 0;}static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a){ if (unlikely(a->index)) return -EINVAL; memset(a, 0, sizeof(*a)); strcpy(a->name, "Radio"); return 0;}/* FIXME: Should add a standard for radio */static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; if (0 != t->index) return -EINVAL; cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_TUNER, t); return 0;}static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a){ return 0;}static int radio_s_input(struct file *file, void *fh, unsigned int i){ return 0;}static int radio_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c){ int i; if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { for (i = 0; i < CX23885_CTLS; i++) if (cx23885_ctls[i].v.id == c->id) break; *c = cx23885_ctls[i].v; } else *c = no_ctl; return 0;}#endif/* ----------------------------------------------------------- */static void cx23885_vid_timeout(unsigned long data){ struct cx23885_dev *dev = (struct cx23885_dev *)data; struct cx23885_dmaqueue *q = &dev->vidq; struct cx23885_buffer *buf; unsigned long flags; cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); cx_clear(VID_A_DMA_CTL, 0x11); spin_lock_irqsave(&dev->slock, flags); while (!list_empty(&q->active)) { buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue); list_del(&buf->vb.queue); buf->vb.state = VIDEOBUF_ERROR; wake_up(&buf->vb.done); printk(KERN_ERR "%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name, buf, buf->vb.i, (unsigned long)buf->risc.dma); } cx23885_restart_video_queue(dev, q); spin_unlock_irqrestore(&dev->slock, flags);}int cx23885_video_irq(struct cx23885_dev *dev, u32 status){ u32 mask, count; int handled = 0; mask = cx_read(VID_A_INT_MSK); if (0 == (status & mask)) return handled; cx_write(VID_A_INT_STAT, status); dprintk(2, "%s() status = 0x%08x\n", __func__, status); /* risc op code error */ if (status & (1 << 16)) { printk(KERN_WARNING "%s/0: video risc op code error\n", dev->name); cx_clear(VID_A_DMA_CTL, 0x11); cx23885_sram_channel_dump(dev, &dev->sram_channels[SRAM_CH01]); } /* risc1 y */ if (status & 0x01) { spin_lock(&dev->slock); count = cx_read(VID_A_GPCNT); cx23885_video_wakeup(dev, &dev->vidq, count); spin_unlock(&dev->slock); handled++; }#if 0 /* risc1 vbi */ if (status & 0x08) { spin_lock(&dev->slock); count = cx_read(MO_VBI_GPCNT); cx88_wakeup(core, &dev->vbiq, count); spin_unlock(&dev->slock); handled++; }#endif /* risc2 y */ if (status & 0x10) { dprintk(2, "stopper video\n"); spin_lock(&dev->slock); cx23885_restart_video_queue(dev, &dev->vidq); spin_unlock(&dev->slock); handled++; }#if 0 /* risc2 vbi */ if (status & 0x80) { dprintk(2, "stopper vbi\n"); spin_lock(&dev->slock); cx8800_restart_vbi_queue(dev, &dev->vbiq); spin_unlock(&dev->slock); handled++; }#endif return handled;}/* ----------------------------------------------------------- *//* exported stuff */static const struct file_operations video_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, .read = video_read, .poll = video_poll, .mmap = video_mmap, .ioctl = video_ioctl2, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek,};static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_g_fmt_vbi_cap = cx23885_vbi_fmt, .vidioc_try_fmt_vbi_cap = cx23885_vbi_fmt, .vidioc_s_fmt_vbi_cap = cx23885_vbi_fmt, .vidioc_reqbufs = vidioc_reqbufs, .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff,#ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf,#endif .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency,#ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register,#endif};static struct video_device cx23885_vbi_template;static struct video_device cx23885_video_template = { .name = "cx23885-video", .fops = &video_fops, .minor = -1, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX23885_NORMS, .current_norm = V4L2_STD_NTSC_M,};static const struct file_operations radio_fops = { .owner = THIS_MODULE, .open = video_open, .release = video_release, .ioctl = video_ioctl2, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek,};#if 0static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_querycap = radio_querycap, .vidioc_g_tuner = radio_g_tuner, .vidioc_enum_input = radio_enum_input, .vidioc_g_audio = radio_g_audio, .vidioc_s_tuner = radio_s_tuner, .vidioc_s_audio = radio_s_audio, .vidioc_s_input = radio_s_input, .vidioc_queryctrl = radio_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency,};static struct video_device cx23885_radio_template = { .name = "cx23885-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, .minor = -1,};#endifvoid cx23885_video_unregister(struct cx23885_dev *dev){ dprintk(1, "%s()\n", __func__); cx_clear(PCI_INT_MSK, 1);#if 0 if (dev->radio_dev) { if (-1 != dev->radio_dev->minor) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); dev->radio_dev = NULL; } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL; btcx_riscmem_free(dev->pci, &dev->vbiq.stopper); }#endif if (dev->video_dev) { if (-1 != dev->video_dev->minor) video_unregister_device(dev->video_dev); else video_device_release(dev->video_dev); dev->video_dev = NULL; btcx_riscmem_free(dev->pci, &dev->vidq.stopper); }}int cx23885_video_register(struct cx23885_dev *dev){ int err; dprintk(1, "%s()\n", __func__); spin_lock_init(&dev->slock); /* Initialize VBI template */ memcpy(&cx23885_vbi_template, &cx23885_video_template, sizeof(cx23885_vbi_template)); strcpy(cx23885_vbi_template.name, "cx23885-vbi"); dev->tvnorm = cx23885_video_template.current_norm; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); dev->vidq.timeout.function = cx23885_vid_timeout; dev->vidq.timeout.data = (unsigned long)dev; init_timer(&dev->vidq.timeout); cx23885_risc_stopper(dev->pci, &dev->vidq.stopper, VID_A_DMA_CTL, 0x11, 0x00); /* Don't enable VBI yet */#if 0 /* init vbi dma queues */ INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); dev->vbiq.timeout.function = cx23885_vbi_timeout; dev->vbiq.timeout.data = (unsigned long)dev; init_timer(&dev->vbiq.timeout); cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper, VID_A_DMA_CTL, 0x88, 0x00);#endif cx_set(PCI_INT_MSK, 1);#if 0 /* FIXME: These should be correctly defined */ /* load and configure helper modules */ if (TUNER_ABSENT != core->tuner_type) request_module("tuner"); if (cx23885_boards[dev->board].audio_chip == V4L2_IDENT_WM8775) request_module("wm8775");#endif /* register v4l devices */ dev->video_dev = cx23885_vdev_init(dev, dev->pci, &cx23885_video_template, "video"); err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, video_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s: can't register video device\n", dev->name); goto fail_unreg; } printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", dev->name, dev->video_dev->num);#if 0 dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, &cx23885_vbi_template, "vbi"); err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s/0: can't register vbi device\n", dev->name); goto fail_unreg; } printk(KERN_INFO "%s/0: registered device vbi%d\n", dev->name, dev->vbi_dev->num); if (dev->has_radio) { dev->radio_dev = cx23885_vdev_init(dev, dev->pci, &cx23885_radio_template, "radio"); err = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, radio_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s/0: can't register radio device\n", dev->name); goto fail_unreg; } printk(KERN_INFO "%s/0: registered device radio%d\n", dev->name, dev->radio_dev->num); }#endif /* initial device configuration */ mutex_lock(&dev->lock); cx23885_set_tvnorm(dev, dev->tvnorm); init_controls(dev); cx23885_video_mux(dev, 0); mutex_unlock(&dev->lock); return 0;fail_unreg: cx23885_video_unregister(dev); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -