📄 saa7134-video.c
字号:
return videobuf_mmap_mapper(saa7134_queue(fh), vma);}/* ------------------------------------------------------------------ */static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; struct saa7134_tvnorm *norm = dev->tvnorm; f->fmt.vbi.sampling_rate = 6750000 * 4; f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */; f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; f->fmt.vbi.offset = 64 * 4; f->fmt.vbi.start[0] = norm->vbi_v_start_0; f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1; f->fmt.vbi.start[1] = norm->vbi_v_start_1; f->fmt.vbi.count[1] = f->fmt.vbi.count[0]; f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */#if 0 if (V4L2_STD_PAL == norm->id) { /* FIXME */ f->fmt.vbi.start[0] += 3; f->fmt.vbi.start[1] += 3*2; }#endif return 0;}static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; f->fmt.pix.width = fh->width; f->fmt.pix.height = fh->height; f->fmt.pix.field = fh->cap.field; f->fmt.pix.pixelformat = fh->fmt->fourcc; f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; return 0;}static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } f->fmt.win = fh->win; return 0;}static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; struct saa7134_format *fmt; enum v4l2_field field; unsigned int maxw, maxh; fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (NULL == fmt) return -EINVAL; field = f->fmt.pix.field; maxw = min(dev->crop_current.width*4, dev->crop_bounds.width); maxh = min(dev->crop_current.height*4, dev->crop_bounds.height); if (V4L2_FIELD_ANY == field) { field = (f->fmt.pix.height > maxh/2) ? V4L2_FIELD_INTERLACED : V4L2_FIELD_BOTTOM; } switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: maxh = maxh / 2; break; case V4L2_FIELD_INTERLACED: break; default: return -EINVAL; } f->fmt.pix.field = field; if (f->fmt.pix.width < 48) f->fmt.pix.width = 48; if (f->fmt.pix.height < 32) f->fmt.pix.height = 32; if (f->fmt.pix.width > maxw) f->fmt.pix.width = maxw; if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; f->fmt.pix.width &= ~0x03; f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; return 0;}static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } return verify_preview(dev, &f->fmt.win);}static int saa7134_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; int err; err = saa7134_try_fmt_vid_cap(file, priv, f); if (0 != err) return err; fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; fh->cap.field = f->fmt.pix.field; return 0;}static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int err; unsigned long flags; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } err = verify_preview(dev, &f->fmt.win); if (0 != err) return err; mutex_lock(&dev->lock); fh->win = f->fmt.win; fh->nclips = f->fmt.win.clipcount; if (fh->nclips > 8) fh->nclips = 8; if (copy_from_user(fh->clips, f->fmt.win.clips, sizeof(struct v4l2_clip)*fh->nclips)) { mutex_unlock(&dev->lock); return -EFAULT; } if (res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock, flags); stop_preview(dev, fh); start_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); } mutex_unlock(&dev->lock); return 0;}int saa7134_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) && (c->id < V4L2_CID_PRIVATE_BASE || c->id >= V4L2_CID_PRIVATE_LASTP1)) return -EINVAL; ctrl = ctrl_by_id(c->id); *c = (NULL != ctrl) ? *ctrl : no_ctrl; return 0;}EXPORT_SYMBOL_GPL(saa7134_queryctrl);static int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; unsigned int n; n = i->index; if (n >= SAA7134_INPUT_MAX) return -EINVAL; if (NULL == card_in(dev, i->index).name) return -EINVAL; memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, card_in(dev, n).name); if (card_in(dev, n).tv) i->type = V4L2_INPUT_TYPE_TUNER; i->audioset = 1; if (n == dev->ctl_input) { int v1 = saa_readb(SAA7134_STATUS_VIDEO1); int v2 = saa_readb(SAA7134_STATUS_VIDEO2); if (0 != (v1 & 0x40)) i->status |= V4L2_IN_ST_NO_H_LOCK; if (0 != (v2 & 0x40)) i->status |= V4L2_IN_ST_NO_SYNC; if (0 != (v2 & 0x0e)) i->status |= V4L2_IN_ST_MACROVISION; } i->std = SAA7134_NORMS; return 0;}static int saa7134_g_input(struct file *file, void *priv, unsigned int *i){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; *i = dev->ctl_input; return 0;}static int saa7134_s_input(struct file *file, void *priv, unsigned int i){ 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 (i < 0 || i >= SAA7134_INPUT_MAX) return -EINVAL; if (NULL == card_in(dev, i).name) return -EINVAL; mutex_lock(&dev->lock); video_mux(dev, i); mutex_unlock(&dev->lock); return 0;}static int saa7134_querycap(struct file *file, void *priv, struct v4l2_capability *cap){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; unsigned int tuner_type = dev->tuner_type; 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_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_TUNER; if (saa7134_no_overlay <= 0) cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET)) cap->capabilities &= ~V4L2_CAP_TUNER; return 0;}int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id){ unsigned long flags; unsigned int i; v4l2_std_id fixup; int err; /* When called from the empress code fh == NULL. That needs to be fixed somehow, but for now this is good enough. */ if (fh) { err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; } else if (res_locked(dev, RESOURCE_OVERLAY)) { /* Don't change the std from the mpeg device if overlay is active. */ return -EBUSY; } for (i = 0; i < TVNORMS; i++) if (*id == tvnorms[i].id) break; if (i == TVNORMS) for (i = 0; i < TVNORMS; i++) if (*id & tvnorms[i].id) break; if (i == TVNORMS) return -EINVAL; if ((*id & V4L2_STD_SECAM) && (secam[0] != '-')) { if (secam[0] == 'L' || secam[0] == 'l') { if (secam[1] == 'C' || secam[1] == 'c') fixup = V4L2_STD_SECAM_LC; else fixup = V4L2_STD_SECAM_L; } else { if (secam[0] == 'D' || secam[0] == 'd') fixup = V4L2_STD_SECAM_DK; else fixup = V4L2_STD_SECAM; } for (i = 0; i < TVNORMS; i++) if (fixup == tvnorms[i].id) break; } *id = tvnorms[i].id; mutex_lock(&dev->lock); if (fh && res_check(fh, RESOURCE_OVERLAY)) { spin_lock_irqsave(&dev->slock, flags); stop_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); set_tvnorm(dev, &tvnorms[i]); spin_lock_irqsave(&dev->slock, flags); start_preview(dev, fh); spin_unlock_irqrestore(&dev->slock, flags); } else set_tvnorm(dev, &tvnorms[i]); saa7134_tvaudio_do_scan(dev); mutex_unlock(&dev->lock); return 0;}EXPORT_SYMBOL_GPL(saa7134_s_std_internal);static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id){ struct saa7134_fh *fh = priv; return saa7134_s_std_internal(fh->dev, fh, id);}static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; *id = dev->tvnorm->id; return 0;}static int saa7134_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) return -EINVAL; cap->bounds = dev->crop_bounds; cap->defrect = dev->crop_defrect; cap->pixelaspect.numerator = 1; cap->pixelaspect.denominator = 1; if (dev->tvnorm->id & V4L2_STD_525_60) { cap->pixelaspect.numerator = 11; cap->pixelaspect.denominator = 10; } if (dev->tvnorm->id & V4L2_STD_625_50) { cap->pixelaspect.numerator = 54; cap->pixelaspect.denominator = 59; } return 0;}static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) return -EINVAL; crop->c = dev->crop_current; return 0;}static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop){ struct saa7134_fh *fh = f; struct saa7134_dev *dev = fh->dev; struct v4l2_rect *b = &dev->crop_bounds; if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) return -EINVAL; if (crop->c.height < 0) return -EINVAL; if (crop->c.width < 0) return -EINVAL; if (res_locked(fh->dev, RESOURCE_OVERLAY)) return -EBUSY; if (res_locked(fh->dev, RESOURCE_VIDEO)) return -EBUSY; if (crop->c.top < b->top) crop->c.top = b->top; if (crop->c.top > b->top + b->height) crop->c.top = b->top + b->height; if (crop->c.height > b->top - crop->c.top + b->height) crop->c.height = b->top - crop->c.top + b->height; if (crop->c.left < b->left) crop->c.left = b->left; if (crop->c.left > b->left + b->width) crop->c.left = b->left + b->width; if (crop->c.width > b->left - crop->c.left + b->width) crop->c.width = b->left - crop->c.left + b->width; dev->crop_current = crop->c; return 0;}static int saa7134_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int n; if (0 != t->index) return -EINVAL; memset(t, 0, sizeof(*t)); for (n = 0; n < SAA7134_INPUT_MAX; n++) if (card_in(dev, n).tv) break; if (NULL != card_in(dev, n).name) { strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; t->rangehigh = 0xffffffffUL; t->rxsubchans = saa7134_tvaudio_getstereo(dev); t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans); } if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03)) t->signal = 0xffff; return 0;}static int saa7134_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; int rx, mode, err; err = v4l2_prio_check(&dev->prio, &fh->prio); if (0 != err) return err; mode = dev->thread.mode; if (UNSET == mode) { rx = saa7134_tvaudio_getstereo(dev); mode = saa7134_tvaudio_rx2mode(t->rxsubchans); } if (mode != t->audmode) dev->thread.mode = t->audmode; return 0;}static int saa7134_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -