📄 saa7134-video.c
字号:
f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; return 0;}static int saa7134_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int err; err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; if (0 != f->tuner) return -EINVAL; if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) return -EINVAL; if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) return -EINVAL; mutex_lock(&dev->lock); dev->ctl_freq = f->frequency; saa7134_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); saa7134_tvaudio_do_scan(dev); mutex_unlock(&dev->lock); return 0;}static int saa7134_g_audio(struct file *file, void *priv, struct v4l2_audio *a){ strcpy(a->name, "audio"); return 0;}static int saa7134_s_audio(struct file *file, void *priv, struct v4l2_audio *a){ return 0;}static int saa7134_g_priority(struct file *file, void *f, enum v4l2_priority *p){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; *p = v4l2_prio_max(&dev->prio); return 0;}static int saa7134_s_priority(struct file *file, void *f, enum v4l2_priority prio){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; return v4l2_prio_change(&dev->prio, &fh->prio, prio);}static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f){ if (f->index >= FORMATS) return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0;}static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_fmtdesc *f){ if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } if ((f->index >= FORMATS) || formats[f->index].planar) return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0;}static int saa7134_g_fbuf(struct file *file, void *f, struct v4l2_framebuffer *fb){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; *fb = dev->ovbuf; fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; return 0;}static int saa7134_s_fbuf(struct file *file, void *f, struct v4l2_framebuffer *fb){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; struct saa7134_format *fmt; if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) return -EPERM; /* check args */ fmt = format_by_fourcc(fb->fmt.pixelformat); if (NULL == fmt) return -EINVAL; /* ok, accept it */ dev->ovbuf = *fb; dev->ovfmt = fmt; if (0 == dev->ovbuf.fmt.bytesperline) dev->ovbuf.fmt.bytesperline = dev->ovbuf.fmt.width*fmt->depth/8; return 0;}static int saa7134_overlay(struct file *file, void *f, unsigned int on){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; unsigned long flags; if (on) { if (saa7134_no_overlay > 0) { dprintk("no_overlay\n"); return -EINVAL; } if (!res_get(dev, fh, RESOURCE_OVERLAY)) return -EBUSY; spin_lock_irqsave(&dev->slock, flags); start_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); } if (!on) { if (!res_check(fh, RESOURCE_OVERLAY)) return -EINVAL; spin_lock_irqsave(&dev->slock, flags); stop_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); res_free(dev, fh, RESOURCE_OVERLAY); } return 0;}#ifdef CONFIG_VIDEO_V4L1_COMPATstatic int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf){ struct saa7134_fh *fh = file->private_data; return videobuf_cgmbuf(saa7134_queue(fh), mbuf, 8);}#endifstatic int saa7134_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p){ struct saa7134_fh *fh = priv; return videobuf_reqbufs(saa7134_queue(fh), p);}static int saa7134_querybuf(struct file *file, void *priv, struct v4l2_buffer *b){ struct saa7134_fh *fh = priv; return videobuf_querybuf(saa7134_queue(fh), b);}static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b){ struct saa7134_fh *fh = priv; return videobuf_qbuf(saa7134_queue(fh), b);}static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b){ struct saa7134_fh *fh = priv; return videobuf_dqbuf(saa7134_queue(fh), b, file->f_flags & O_NONBLOCK);}static int saa7134_streamon(struct file *file, void *priv, enum v4l2_buf_type type){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int res = saa7134_resource(fh); if (!res_get(dev, fh, res)) return -EBUSY; return videobuf_streamon(saa7134_queue(fh));}static int saa7134_streamoff(struct file *file, void *priv, enum v4l2_buf_type type){ int err; struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int res = saa7134_resource(fh); err = videobuf_streamoff(saa7134_queue(fh)); if (err < 0) return err; res_free(dev, fh, res); return 0;}static int saa7134_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm){ return 0;}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int vidioc_g_register (struct file *file, void *priv, struct v4l2_register *reg){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; reg->val = saa_readb(reg->reg); return 0;}static int vidioc_s_register (struct file *file, void *priv, struct v4l2_register *reg){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; saa_writeb(reg->reg&0xffffff, reg->val); return 0;}#endifstatic int radio_querycap(struct file *file, void *priv, struct v4l2_capability *cap){ struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->version = SAA7134_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; return 0;}static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; if (0 != t->index) return -EINVAL; memset(t, 0, sizeof(*t)); strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t); if (dev->input->amux == TV) { t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11); t->rxsubchans = (saa_readb(0x529) & 0x08) ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; } return 0;}static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; if (0 != t->index) return -EINVAL; saa7134_i2c_call_clients(dev, VIDIOC_S_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_input(struct file *filp, void *priv, unsigned int *i){ *i = 0; return 0;}static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a){ memset(a, 0, sizeof(*a)); strcpy(a->name, "Radio"); return 0;}static int radio_s_audio(struct file *file, void *priv, struct v4l2_audio *a){ return 0;}static int radio_s_input(struct file *filp, void *priv, unsigned int i){ return 0;}static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm){ return 0;}static int radio_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c){ const struct v4l2_queryctrl *ctrl; if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1) return -EINVAL; if (c->id == V4L2_CID_AUDIO_MUTE) { ctrl = ctrl_by_id(c->id); *c = *ctrl; } else *c = no_ctrl; return 0;}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 = saa7134_querycap, .vidioc_enum_fmt_vid_cap = saa7134_enum_fmt_vid_cap, .vidioc_g_fmt_vid_cap = saa7134_g_fmt_vid_cap, .vidioc_try_fmt_vid_cap = saa7134_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = saa7134_s_fmt_vid_cap, .vidioc_enum_fmt_vid_overlay = saa7134_enum_fmt_vid_overlay, .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay, .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay, .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay, .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap, .vidioc_g_audio = saa7134_g_audio, .vidioc_s_audio = saa7134_s_audio, .vidioc_cropcap = saa7134_cropcap, .vidioc_reqbufs = saa7134_reqbufs, .vidioc_querybuf = saa7134_querybuf, .vidioc_qbuf = saa7134_qbuf, .vidioc_dqbuf = saa7134_dqbuf, .vidioc_s_std = saa7134_s_std, .vidioc_g_std = saa7134_g_std, .vidioc_enum_input = saa7134_enum_input, .vidioc_g_input = saa7134_g_input, .vidioc_s_input = saa7134_s_input, .vidioc_queryctrl = saa7134_queryctrl, .vidioc_g_ctrl = saa7134_g_ctrl, .vidioc_s_ctrl = saa7134_s_ctrl, .vidioc_streamon = saa7134_streamon, .vidioc_streamoff = saa7134_streamoff, .vidioc_g_tuner = saa7134_g_tuner, .vidioc_s_tuner = saa7134_s_tuner,#ifdef CONFIG_VIDEO_V4L1_COMPAT .vidiocgmbuf = vidiocgmbuf,#endif .vidioc_g_crop = saa7134_g_crop, .vidioc_s_crop = saa7134_s_crop, .vidioc_g_fbuf = saa7134_g_fbuf, .vidioc_s_fbuf = saa7134_s_fbuf, .vidioc_overlay = saa7134_overlay, .vidioc_g_priority = saa7134_g_priority, .vidioc_s_priority = saa7134_s_priority, .vidioc_g_parm = saa7134_g_parm, .vidioc_g_frequency = saa7134_g_frequency, .vidioc_s_frequency = saa7134_s_frequency,#ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register,#endif};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,};static 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_s_std = radio_s_std, .vidioc_queryctrl = radio_queryctrl, .vidioc_g_input = radio_g_input, .vidioc_g_ctrl = saa7134_g_ctrl, .vidioc_s_ctrl = saa7134_s_ctrl, .vidioc_g_frequency = saa7134_g_frequency, .vidioc_s_frequency = saa7134_s_frequency,};/* ----------------------------------------------------------- *//* exported stuff */struct video_device saa7134_video_template = { .name = "saa7134-video", .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .minor = -1, .tvnorms = SAA7134_NORMS, .current_norm = V4L2_STD_PAL,};struct video_device saa7134_radio_template = { .name = "saa7134-radio", .fops = &radio_fops, .ioctl_ops = &radio_ioctl_ops, .minor = -1,};int saa7134_video_init1(struct saa7134_dev *dev){ /* sanitycheck insmod options */ if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME) gbuffers = 2; if (gbufsize < 0 || gbufsize > gbufsize_max) gbufsize = gbufsize_max; gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK; /* put some sensible defaults into the data structures ... */ dev->ctl_bright = ctrl_by_id(V4L2_CID_BRIGHTNESS)->default_value; dev->ctl_contrast = ctrl_by_id(V4L2_CID_CONTRAST)->default_value; dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value; dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value; dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value; dev->ctl_mute = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value; dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value; dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value; if (dev->tda9887_conf && dev->ctl_automute) dev->tda9887_conf |= TDA9887_AUTOMUTE; dev->automute = 0; INIT_LIST_HEAD(&dev->video_q.queue); init_timer(&dev->video_q.timeout); dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.dev = dev; if (saa7134_boards[dev->board].video_out) saa7134_videoport_init(d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -