📄 omap24xxcam.c
字号:
else vb->state = STATE_DONE; wake_up(&vb->done); spin_unlock(&cam->vbq_lock);}static voidomap24xxcam_vbq_release(struct file *file, struct videobuf_buffer *vb){ videobuf_waiton(vb, 0, 0); videobuf_dma_pci_unmap(NULL, &vb->dma); videobuf_dma_free(&vb->dma); vb->state = STATE_NEEDS_INIT;}/* Limit the number of available kernel image capture buffers based on the * number requested, the currently selected image size, and the maximum * amount of memory permitted for kernel capture buffers. */static intomap24xxcam_vbq_setup(struct file *file, unsigned int *cnt, unsigned int *size){ struct omap24xxcam_fh *fh = file->private_data; struct omap24xxcam_device *cam = fh->cam; if (*cnt <= 0) *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */ if (*cnt > VIDEO_MAX_FRAME) *cnt = VIDEO_MAX_FRAME; spin_lock(&cam->img_lock); *size = cam->pix.sizeimage; spin_unlock(&cam->img_lock); while (*size * *cnt > capture_mem) (*cnt)--; return 0;}static intomap24xxcam_vbq_prepare(struct file *file, struct videobuf_buffer *vb, enum v4l2_field field){ struct omap24xxcam_fh *fh = file->private_data; struct omap24xxcam_device *cam = fh->cam; int err = 0; spin_lock(&cam->img_lock); if (vb->baddr) { /* This is a userspace buffer. */ if (cam->pix.sizeimage > vb->bsize) { /* The buffer isn't big enough. */ err = -EINVAL; } else vb->size = cam->pix.sizeimage; } else if (!vb->baddr) { if (vb->state != STATE_NEEDS_INIT) { /* We have a kernel bounce buffer that has already been * allocated. */ if (cam->pix.sizeimage > vb->size) { /* The image size has been changed to a larger * size since this buffer was allocated, so we * need to free and reallocate it. */ spin_unlock(&cam->img_lock); omap24xxcam_vbq_release(file, vb); spin_lock(&cam->img_lock); vb->size = cam->pix.sizeimage; } } else { /* We need to allocate a new kernel bounce buffer. */ vb->size = cam->pix.sizeimage; } } vb->width = cam->pix.width; vb->height = cam->pix.height; vb->field = field; spin_unlock(&cam->img_lock); if (err) return err; if (vb->state == STATE_NEEDS_INIT) err = videobuf_iolock(NULL, vb, NULL); if (!err) vb->state = STATE_PREPARED; else omap24xxcam_vbq_release(file, vb); return err;}static voidomap24xxcam_vbq_queue(struct file *file, struct videobuf_buffer *vb){ struct omap24xxcam_fh *fh = file->private_data; struct omap24xxcam_device *cam = fh->cam; enum videobuf_state state = vb->state; int err; vb->state = STATE_QUEUED; err = omap24xxcam_sg_dma_queue(cam, vb->dma.sglist, vb->dma.sglen, omap24xxcam_vbq_complete, vb); if (err) { /* Oops. We're not supposed to get any errors here. The only * way we could get an error is if we ran out of scatter-gather * DMA slots, but we are supposed to have at least as many * scatter-gather DMA slots as video buffers so that can't * happen. */ printk(KERN_DEBUG CAM_NAME ": Failed to queue a video buffer for DMA!\n"); vb->state = state; }}/* -------------------------------------------------------------------------- */static intomap24xxcam_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg){ struct omap24xxcam_fh *fh = file->private_data; struct omap24xxcam_device *cam = fh->cam; int err; switch (cmd) { /* for time being below IOCTL cmd is here */ case VIDIOC_ENUMINPUT: { /* default handler assumes 1 video input (the camera) */ struct v4l2_input *input = (struct v4l2_input *) arg; int index = input->index; memset(input, 0, sizeof(*input)); input->index = index; if (index > 0) return -EINVAL; strlcpy(input->name, "camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; } case VIDIOC_G_INPUT: { unsigned int *input = arg; *input = 0; return 0; } case VIDIOC_S_INPUT: { unsigned int *input = arg; if (*input > 0) return -EINVAL; return 0; } case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = (struct v4l2_capability *) arg; memset(cap, 0, sizeof(*cap)); strlcpy(cap->driver, CAM_NAME, sizeof(cap->driver)); strlcpy(cap->card, cam->vfd->name, sizeof(cap->card)); cap->bus_info[0] = '\0'; cap->version = KERNEL_VERSION(0, 0, 0); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; return 0; } case VIDIOC_G_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { struct v4l2_pix_format *pix = &f->fmt.pix; memset(pix, 0, sizeof(*pix)); spin_lock(&cam->img_lock); *pix = cam->pix; spin_unlock(&cam->img_lock); return 0; } case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; memset(win, 0, sizeof(*win)); /* The API has a bit of a problem here. * We're returning a v4l2_window * structure, but that structure * contains pointers to variable-sized * objects for clipping rectangles and * clipping bitmaps. We will just * return NULLs for those pointers. */ spin_lock(&cam->img_lock); win->w = cam->win.w; win->field = cam->win.field; win->chromakey = cam->win.chromakey; spin_unlock(&cam->img_lock); return 0; } default: { return -EINVAL; } } } case VIDIOC_TRY_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; spin_lock(&cam->img_lock); err=omap24xxcam_try_preview_window(cam, win); spin_unlock(&cam->img_lock); return err; } case V4L2_BUF_TYPE_VIDEO_CAPTURE: { return cam->cam_sensor->try_format(&f->fmt.pix, cam->sensor); } default: { return -EINVAL; } } } case VIDIOC_S_FMT: { struct v4l2_format *f = (struct v4l2_format *) arg; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_window *win = &f->fmt.win; spin_lock(&cam->img_lock); if (cam->previewing) { spin_unlock(&cam->img_lock); return -EBUSY; } err=omap24xxcam_new_preview_window(cam, win); spin_unlock(&cam->img_lock); return err; } case V4L2_BUF_TYPE_VIDEO_CAPTURE: { spin_lock(&cam->img_lock); if (cam->streaming || cam->previewing) { spin_unlock(&cam->img_lock); return -EBUSY; } cam->cam_sensor->try_format(&f->fmt.pix, cam->sensor); /* set the new capture format */ cam->pix = f->fmt.pix; /* adjust the capture frame rate */ cam->xclk = cam->cam_sensor->calc_xclk(&cam->pix, &cam->nominal_timeperframe, cam->sensor); omap24xxcam_adjust_xclk(cam); cam->cparm.timeperframe = cam->nominal_timeperframe; /* intialize the preview parameters */ omap24xxcam_new_capture_format(cam); spin_unlock(&cam->img_lock); /* program xclk */ omap24xxcam_set_xclk(cam); /* program the sensor */ err = cam->cam_sensor->configure(&cam->pix, cam->xclk, &cam->cparm.timeperframe, cam->sensor); return err; } default: { return -EINVAL; } } } case VIDIOC_G_FBUF: { struct v4l2_framebuffer *fbuf = (struct v4l2_framebuffer *) arg; spin_lock(&cam->img_lock); *fbuf = cam->fbuf; spin_unlock(&cam->img_lock); return 0; } case VIDIOC_S_FBUF: { struct v4l2_framebuffer *fbuf = (struct v4l2_framebuffer *) arg; unsigned int flags = fbuf->flags; /* The only field the user is allowed to change is * fbuf->flags. */ spin_lock(&cam->img_lock); if (cam->previewing) { spin_unlock(&cam->img_lock); return -EBUSY; } if (flags & V4L2_FBUF_FLAG_CHROMAKEY) cam->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; else cam->fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; spin_unlock(&cam->img_lock); return 0; } case VIDIOC_CROPCAP: { struct v4l2_cropcap *cropcap = (struct v4l2_cropcap *) arg; enum v4l2_buf_type type = cropcap->type; memset(cropcap, 0, sizeof(*cropcap)); cropcap->type = type; switch (type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { struct v4l2_pix_format *pix = &cam->pix; spin_lock(&cam->img_lock); cropcap->bounds.width = pix->width & ~1; cropcap->bounds.height = pix->height & ~1; omap24xxcam_default_crop_rect(cam, &cropcap->defrect); spin_unlock(&cam->img_lock); cropcap->pixelaspect.numerator = 1; cropcap->pixelaspect.denominator = 1; return 0; } case V4L2_BUF_TYPE_VIDEO_CAPTURE: { /* We're required to support the CROPCAP * ioctl even though the G_CROP/S_CROP * ioctls are optional, which seems a * little strange. We don't support * cropping of captured images. */ spin_lock(&cam->img_lock); cropcap->bounds.width = cam->pix.width; cropcap->bounds.height = cam->pix.height; spin_unlock(&cam->img_lock); cropcap->defrect.width = cropcap->bounds.width; cropcap->defrect.height = cropcap->bounds.height; cropcap->pixelaspect.numerator = 1; cropcap->pixelaspect.denominator = 1; return 0; } default: { return -EINVAL; } } } case VIDIOC_G_CROP: { struct v4l2_crop *crop = (struct v4l2_crop *) arg; switch (crop->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { spin_lock(&cam->img_lock); crop->c = cam->crop; spin_unlock(&cam->img_lock); return 0; } case V4L2_BUF_TYPE_VIDEO_CAPTURE: { /* We don't support cropping of captured * images. */ return -EINVAL; } default: { return -EINVAL; } } } case VIDIOC_S_CROP: { struct v4l2_crop *crop = (struct v4l2_crop *) arg; switch (crop->type) { case V4L2_BUF_TYPE_VIDEO_OVERLAY: { spin_lock(&cam->img_lock); if (cam->previewing) { spin_unlock(&cam->img_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -