📄 s3c2440_camif.c
字号:
break; } case VIDIOC_ENUMINPUT: { struct v4l2_input *vi = arg; if (vi->index < 0 || vi->index >= 1) { DPRINTK("ENUMINPUT outof range input=%d\n", vi->index); return -EINVAL; } *vi = dev->source.input; DPRINTK("VIDIOC_ENUMINPUT\n"); break; } case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; int index; index = find_queryctrl(qc->id); if (-EINVAL == index) { qc->flags = V4L2_CTRL_FLAG_DISABLED; break; } if (index < 0) return -EINVAL;#if 0 capture_control[index].category = qc->category; memcpy(capture_control[index].group, qc->group, sizeof(qc->group));#else memcpy(qc, &capture_control[index], sizeof(struct v4l2_queryctrl));#endif DPRINTK("VIDIOC_QUERYCTRL\n"); break; } case VIDIOC_G_CTRL: { struct v4l2_control *vc = arg; int index; index = find_queryctrl(vc->id); if (index < 0) return -EINVAL; vc->value = dev->source.control[index]; DPRINTK("VIDIOC_G_CTRL\n"); break; } case VIDIOC_S_CTRL: { struct v4l2_control *vc = arg; int index; index = find_queryctrl(vc->id); if (index < 0) return -EINVAL;#if 0 // needless /* memcpy */ dev->source.control[index] = vc->value;#endif hw_capture_control(dev, index, vc); DPRINTK("VIDIOC_S_CTRL\n"); break; }#if 0 // NEEDLESS case VIDIOC_QUERYMENU: { DPRINTK("VIDIOC_QUERYMENU\n"); break; } case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *req = arg; if (o->noncapturing) { printk("REQBUFS illegal in non-capturing open\n"); return -EPERM; } if (dev->stream_buffers_mapped) { printk("Can't request buffers if buffers are " "already mapped\n"); return -EPERM; } mmap_unrequest_buffers(dev);#if 0 // TODO capture_begin(dev);#endif if (!mmap_request_buffers(dev, req)) return -EINVAL; DPRINTK("VIDIOC_REQBUFS\n"); break; } case VIDIOC_G_PARM: { struct v4l2_streamparm *sp = arg; if (sp->type != V4L2_BUF_TYPE_CAPTURE) { printk("G_PARM Bad parameter\n"); return -EINVAL; } sp->parm.capture = dev->capture; DPRINTK("VIDIOC_G_PARM\n"); break; } case VIDIOC_S_PARM: { struct v4l2_streamparm *sp = arg; struct v4l2_captureparm *vp = &sp->parm.capture; if (vp->capturemode & ~dev->capture.capability) { printk("PARM unsupported capture capability %08X\n", vp->capturemode); return -EINVAL; } if ((dev->capture.capability & V4L2_CAP_TIMEPERFRAME) && vp->timeperframe < 10000) { printk("PARM time per frame out of range %ld\n", vp->timeperframe); return -EINVAL; } if (vp->capturemode != dev->capture.capturemode && !o->noncapturing && dev->streaming) { printk("???\n"); return -EINVAL; } if (o->noncapturing) break; /// ??? - BUSHI if (vp->capturemode != dev->capture.capturemode) { dev->capture.capturemode = vp->capturemode;#if 0 // TODO capture_new_format(dev);#endif }#if 0 // TODO, needless ??? - BUSHI if ((vp->capturemode & V4L2_CAP_TIMEPERFRAME) && vp->timeperframe >= dev->videc.frame_period) dev->capture.timeperframe = vp->timeperframe; else dev->capture.timeperframe = dev->videc.frame_period;#endif DPRINTK("VIDIOC_S_PARM\n"); break; } case VIDIOC_G_STD: { struct v4l2_standard *std = arg; DPRINTK("VIDIOC_G_STD\n"); v4l2_video_std_construct(std, 0, 0); break; } case VIDIOC_S_STD: { // TODO DPRINTK("VIDIOC_S_STD\n"); break; } case VIDIOC_ENUMSTD: { // TODO DPRINTK("VIDIOC_ENUMSTD\n"); break; } case VIDIOC_QUERYBUF: { struct v4l2_buffer *buf = arg; int i; if (o->noncapturing) { printk("QUERYBUF illegal in non-capturing open\n"); return -EPERM; } i = buf->index; if (i<0 || i >= MAX_NUM_FRAMES || !dev->stream_buf[i].requested || (buf->type & V4L2_BUF_TYPE_field) != (dev->stream_buf[i].vidbuf.type & V4L2_BUF_TYPE_field)) { printk("QUERYBUF bad parameter\n"); return -EINVAL; } *buf = dev->stream_buf[i].vidbuf; DPRINTK("VIDIOC_QUERYBUF\n"); break; } case VIDIOC_QBUF: { struct v4l2_buffer *buf = arg; if (o->noncapturing) { printk("QBUF illegal in non-capturing open\n"); return -EPERM; } if (!dev->stream_buffers_mapped) { printk("QBUF no buffers are mapped\n"); return -EINVAL; }#if 0 // TODO if (!capture_queuebuffer(dev, buf)) return -EINVAL;#endif DPRINTK("VIDIOC_QBUF\n"); break; } case VIDIOC_DQBUF: { struct v4l2_buffer *buf = arg; if (o->noncapturing) { printk("DQBUF illegal in non-capturing open\n"); return -EPERM; }#if 0 // TODO if (!capture_dequeuebuffer(dev, buf)) return -EINVAL;#endif DPRINTK("VIDIOC_DQBUF\n"); break; } case VIDIOC_STREAMON: { unsigned long *type = arg; if (o->noncapturing) { printk("STREAMON illegal in non-capturing open\n"); return -EPERM; }#if 0 // TODO if (!capture_streamon(dev, *type)) return -EINVAL;#endif DPRINTK("VIDIOC_STREAMON\n"); break; } case VIDIOC_STREAMOFF: { unsigned long *type = arg; if (o->noncapturing) { printk("STREAMOFF illegal in non-capturing open\n"); return -EPERM; }#if 0 // TODO capture_streamoff(dev, *type);#endif DPRINTK("VIDIOC_STREAMOFF\n"); break; } case VIDIOC_G_PERF: { memcpy(arg, &dev->perf, sizeof(dev->perf)); DPRINTK("VIDIOC_G_PERF\n"); break; } case VIDIOC_G_WIN: case VIDIOC_S_WIN: case VIDIOC_ENUM_FBUFFMT: case VIDIOC_G_FBUF: case VIDIOC_S_FBUF: case VIDIOC_G_COMP: case VIDIOC_S_COMP: case VIDIOC_PREVIEW: case VIDIOC_G_TUNER: case VIDIOC_S_TUNER: case VIDIOC_G_FREQ: case VIDIOC_S_FREQ: case VIDIOC_G_AUDIO: case VIDIOC_S_AUDIO:#endif // NEEDLESS default: return -ENOIOCTLCMD; // return to V4L2 } return 0;}static long v4l2_cam_read(void *id, char *buf, unsigned long count, int noblock){ struct device_open *o = (struct device_open *)id; struct s3c2440_camif *dev = o->dev; if (o->noncapturing) { printk("read() illegal in non-capturing open\n"); return -EPERM; } if (dev->streaming) { printk("Can't read() when streaming is on\n"); return -EPERM; } if (IS_CAM(CAM_CAPTURING)) wait_for_completion(&dev->capture_done); if (!dev->captured) capture_frame(dev); if (!dev->captured) { DPRINTK("Can't grab frames!\n"); return 0; } dev->captured = 0; return capture_read(dev, buf, count);}#if 0 // needlessstatic int v4l2_cam_mmap(void *id, struct vm_area_struct *vma){ return -EPERM;}static long v4l2_cam_write(void *id, const char *buf, unsigned long count, int noblock){ return -EPERM;}#endifstatic int v4l2_cam_poll(void *id, struct file *file, poll_table * table){ struct device_open *o = (struct device_open *)id; struct s3c2440_camif *dev = o->dev; if (o->noncapturing) { DPRINTK("poll() illegal in non-capturing open\n"); return POLLERR; } if (!IS_CAM(CAM_CAPTURING)) { __pre_capture_frame(dev); poll_wait(file, &(dev->capture_done.wait), table); __post_capture_frame(dev); } else { poll_wait(file, &(dev->capture_done.wait), table); } return (dev->captured) ? (POLLIN | POLLRDNORM) : 0;}static int v4l2_cam_initdone (struct v4l2_device *v){ struct s3c2440_camif *dev = (struct s3c2440_camif *)v; struct v4l2_pix_format *cfmt = &(dev->clientfmt); struct video_source *src = &(dev->source); DPRINTK("%s():\n", __FUNCTION__); cfmt->width = 240; cfmt->height = 160; cfmt->depth = 16; cfmt->pixelformat = V4L2_PIX_FMT_RGB565; cfmt->sizeimage = cfmt->width * (cfmt->depth+7) / 8 * cfmt->height; s3c2440_camif_cfg.use_vpost = 0; /* Not supported */ s3c2440_camif_cfg.dev = dev; src->input.index = 0; src->input.type = V4L2_INPUT_TYPE_CAMERA; src->input.capability = 0; src->control[VCTRL_BRIGHTNESS] = capture_control[VCTRL_BRIGHTNESS].default_value; return 0;}int s3c2440_camif_register_camhw(struct s3c2440_cam_hw *camhw){ if (camif.hw) return -EBUSY; camif.hw = camhw; s3c2440_camif_cfg.src_x = camhw->max_width; s3c2440_camif_cfg.src_y = camhw->max_height; hw_control_func[VCTRL_BRIGHTNESS] = camhw->encode_brightness; hw_control_func[VCTRL_REDBALANCE] = camhw->encode_redbalance; hw_control_func[VCTRL_BLUEBALANCE] = camhw->encode_bluebalance; hw_control_func[VCTRL_AUTOWHITEBALANCE] = camhw->encode_autowhitebalance; hw_control_func[VCTRL_EXPOSURE] = camhw->encode_exposure; snprintf(camif.source.input.name, 31, "%s::%s", camif.v.name, &(camhw->name[0])); return 0;}int s3c2440_camif_unregister_camhw(struct s3c2440_cam_hw *camhw){ if (!camif.hw || camif.hw != camhw) return -ENODEV; if (camif.open_count) return -EBUSY; camif.hw = NULL; snprintf(camif.source.input.name, 31, "%s", camif.v.name); return 0;}void inline config_camif_v4l2(void){ DPRINTK("%s():\n", __FUNCTION__); sprintf(camif.v.name,"%s","S3C2440_CAMIF"); camif.v.priv = (void*)&camif; camif.v.open = v4l2_cam_open; camif.v.close = v4l2_cam_close; camif.v.read = v4l2_cam_read; camif.v.ioctl = v4l2_cam_ioctl; camif.v.poll = v4l2_cam_poll;#if 0 // needless camif.v.mmap = v4l2_cam_mmap; camif.v.write = v4l2_cam_write;#endif camif.v.initialize = v4l2_cam_initdone; camif.hw = NULL;}int __init s3c2440_camif_initialize(void){ int ret = 0; DPRINTK("%s():\n", __FUNCTION__); s3c2440_camif_init(); init_completion(&camif.capture_done); INIT_TQUEUE(&cam_s_task, cam_s_task_handler, (void*)&s3c2440_camif_cfg); camif_yuv_buf = consistent_alloc(GFP_KERNEL, YUV_IMG_BUF_SIZE, &camif_yuv_buf_dma); camif_rgb_buf = consistent_alloc(GFP_KERNEL, RGB_IMG_BUF_SIZE, &camif_rgb_buf_dma); if (!camif_yuv_buf || !camif_rgb_buf ) { ret = -ENOMEM; goto mem_err; } memset(camif_yuv_buf, 0, YUV_IMG_BUF_SIZE); memset(camif_rgb_buf, 0, RGB_IMG_BUF_SIZE); if ((ret = request_irq(IRQ_CAM_S, s3c2440_camif_isr_s, SA_INTERRUPT, "CAM_S", NULL))) { printk("request_irq(CAM_S) failed.\n"); goto err_irq_s; } disable_irq(IRQ_CAM_S); config_camif_v4l2(); if ((ret = v4l2_register_device ((struct v4l2_device *)&camif)) != 0) { printk("V4L2 registering failed!\n"); goto error_v4l2_register; } init_yuvtable();#ifdef MODULE /* CPU : FIXME */ flush_scheduled_tasks();#endif return 0;error_v4l2_register: free_irq(IRQ_CAM_S, NULL);err_irq_s: s3c2440_camif_deinit();mem_err: if (camif_yuv_buf) consistent_free(camif_yuv_buf, YUV_IMG_BUF_SIZE , camif_yuv_buf_dma); if (camif_rgb_buf) consistent_free(camif_rgb_buf, RGB_IMG_BUF_SIZE , camif_rgb_buf_dma); return ret;}void __exit s3c2440_camif_exit(void){ DPRINTK("%s():\n", __FUNCTION__); disable_irq(IRQ_CAM_S); complete(&camif.capture_done); flush_scheduled_tasks(); v4l2_unregister_device((struct v4l2_device *) &camif); s3c2440_camif_deinit(); free_irq(IRQ_CAM_S, NULL); if (camif_yuv_buf) consistent_free(camif_yuv_buf, YUV_IMG_BUF_SIZE , camif_yuv_buf_dma); if (camif_rgb_buf) consistent_free(camif_rgb_buf, RGB_IMG_BUF_SIZE , camif_rgb_buf_dma);}module_exit(s3c2440_camif_exit);module_init(s3c2440_camif_initialize);MODULE_LICENSE("GPL");EXPORT_SYMBOL(s3c2440_camif_register_camhw);EXPORT_SYMBOL(s3c2440_camif_unregister_camhw);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -