📄 cx23885-video.c
字号:
/* stop vbi capture */ if (res_check(fh, RESOURCE_VBI)) { if (fh->vbiq.streaming) videobuf_streamoff(&fh->vbiq); if (fh->vbiq.reading) videobuf_read_stop(&fh->vbiq); res_free(dev, fh, RESOURCE_VBI); } videobuf_mmap_free(&fh->vidq);#if 0 videobuf_mmap_free(&fh->vbiq);#endif file->private_data = NULL; kfree(fh); /* We are not putting the tuner to sleep here on exit, because * we want to use the mpeg encoder in another session to capture * tuner video. Closing this will result in no video to the encoder. */#if 0 cx23885_call_i2c_clients(&dev->i2c_bus[1], TUNER_SET_STANDBY, NULL);#endif return 0;}static int video_mmap(struct file *file, struct vm_area_struct *vma){ struct cx23885_fh *fh = file->private_data; return videobuf_mmap_mapper(get_queue(fh), vma);}/* ------------------------------------------------------------------ *//* VIDEO CTRL IOCTLS */static int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl){ dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_CTRL, ctl); return 0;}static int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl){ dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)" " (disabled - no action)\n", __func__);#if 0 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);#endif return 0;}static void init_controls(struct cx23885_dev *dev){ struct v4l2_control ctrl; int i; for (i = 0; i < CX23885_CTLS; i++) { ctrl.id = cx23885_ctls[i].v.id; ctrl.value = cx23885_ctls[i].v.default_value; cx23885_set_control(dev, &ctrl); }}/* ------------------------------------------------------------------ *//* VIDEO IOCTLS */static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_fh *fh = priv; f->fmt.pix.width = fh->width; f->fmt.pix.height = fh->height; f->fmt.pix.field = fh->vidq.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 vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; struct cx23885_fmt *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 = norm_maxw(dev->tvnorm); maxh = norm_maxh(dev->tvnorm); 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.height < 32) f->fmt.pix.height = 32; if (f->fmt.pix.height > maxh) f->fmt.pix.height = maxh; if (f->fmt.pix.width < 48) f->fmt.pix.width = 48; if (f->fmt.pix.width > maxw) f->fmt.pix.width = maxw; 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 vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; int err; dprintk(2, "%s()\n", __func__); err = vidioc_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->vidq.field = f->fmt.pix.field; dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field); cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_FMT, f); return 0;}static int vidioc_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 =#if 0 V4L2_CAP_VIDEO_OVERLAY |#endif V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE; if (UNSET != dev->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0;}static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f){ if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; strlcpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0;}#ifdef CONFIG_VIDEO_V4L1_COMPATstatic int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf){ struct cx23885_fh *fh = priv; struct videobuf_queue *q; struct v4l2_requestbuffers req; unsigned int i; int err; q = get_queue(fh); memset(&req, 0, sizeof(req)); req.type = q->type; req.count = 8; req.memory = V4L2_MEMORY_MMAP; err = videobuf_reqbufs(q, &req); if (err < 0) return err; mbuf->frames = req.count; mbuf->size = 0; for (i = 0; i < mbuf->frames; i++) { mbuf->offsets[i] = q->bufs[i]->boff; mbuf->size += q->bufs[i]->bsize; } return 0;}#endifstatic int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p){ struct cx23885_fh *fh = priv; return videobuf_reqbufs(get_queue(fh), p);}static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p){ struct cx23885_fh *fh = priv; return videobuf_querybuf(get_queue(fh), p);}static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p){ struct cx23885_fh *fh = priv; return videobuf_qbuf(get_queue(fh), p);}static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p){ struct cx23885_fh *fh = priv; return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);}static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; dprintk(1, "%s()\n", __func__); if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) return -EINVAL; if (unlikely(i != fh->type)) return -EINVAL; if (unlikely(!res_get(dev, fh, get_resource(fh)))) return -EBUSY; return videobuf_streamon(get_queue(fh));}static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; int err, res; dprintk(1, "%s()\n", __func__); if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; if (i != fh->type) return -EINVAL; res = get_resource(fh); err = videobuf_streamoff(get_queue(fh)); if (err < 0) return err; res_free(dev, fh, res); return 0;}static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; dprintk(1, "%s()\n", __func__); mutex_lock(&dev->lock); cx23885_set_tvnorm(dev, *tvnorms); mutex_unlock(&dev->lock); return 0;}static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i){ static const char *iname[] = { [CX23885_VMUX_COMPOSITE1] = "Composite1", [CX23885_VMUX_COMPOSITE2] = "Composite2", [CX23885_VMUX_COMPOSITE3] = "Composite3", [CX23885_VMUX_COMPOSITE4] = "Composite4", [CX23885_VMUX_SVIDEO] = "S-Video", [CX23885_VMUX_TELEVISION] = "Television", [CX23885_VMUX_CABLE] = "Cable TV", [CX23885_VMUX_DVB] = "DVB", [CX23885_VMUX_DEBUG] = "for debug only", }; unsigned int n; dprintk(1, "%s()\n", __func__); n = i->index; if (n >= 4) return -EINVAL; if (0 == INPUT(n)->type) return -EINVAL; memset(i, 0, sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; strcpy(i->name, iname[INPUT(n)->type]); if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) || (CX23885_VMUX_CABLE == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; i->std = CX23885_NORMS; return 0;}static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; dprintk(1, "%s()\n", __func__); return cx23885_enum_input(dev, i);}static int vidioc_g_input(struct file *file, void *priv, unsigned int *i){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; *i = dev->input; dprintk(1, "%s() returns %d\n", __func__, *i); return 0;}static int vidioc_s_input(struct file *file, void *priv, unsigned int i){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; dprintk(1, "%s(%d)\n", __func__, i); if (i >= 4) { dprintk(1, "%s() -EINVAL\n", __func__); return -EINVAL; } mutex_lock(&dev->lock); cx23885_video_mux(dev, i); mutex_unlock(&dev->lock); return 0;}static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl){ qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); if (unlikely(qctrl->id == 0)) return -EINVAL; return cx23885_ctrl_query(qctrl);}static int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; return cx23885_get_control(dev, ctl);}static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctl){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; return cx23885_set_control(dev, ctl);}static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; if (unlikely(UNSET == dev->tuner_type)) return -EINVAL; if (0 != t->index) return -EINVAL; strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL;#if 0 cx23885_get_stereo(dev, t);#endif t->signal = 0xffff ; /* LOCKED */ return 0;}static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t){ struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; if (UNSET == dev->tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL;#if 0 cx23885_set_stereo(dev, t->audmode, 1);#endif return 0;}static int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f){ struct cx23885_fh *fh = priv; struct cx23885_dev *dev = fh->dev; if (unlikely(UNSET == dev->tuner_type)) return -EINVAL; /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->freq; cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f); return 0;}static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f){ if (unlikely(UNSET == dev->tuner_type)) return -EINVAL; if (unlikely(f->tuner != 0)) return -EINVAL; mutex_lock(&dev->lock); dev->freq = f->frequency; cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -