📄 pxa_camera.c
字号:
camera_context_t *cam_ctx; cam_ctx = g_camera_context; if (atomic_read(&cam_ctx->refcount)) return -EBUSY; atomic_inc(&cam_ctx->refcount); init_waitqueue_head(&camera_wait_q);#ifdef ADCM2650 cam_ctx->sensor_type = CAMERA_TYPE_ADCM_2650;#endif #ifdef OV9640 cam_ctx->sensor_type = CAMERA_TYPE_OMNIVISION_9640;#endif #ifdef OV9650 //hzh cam_ctx->sensor_type = CAMERA_TYPE_OMNIVISION_9650;#endif cam_ctx->capture_width = WIDTH_DEFT; cam_ctx->capture_height = HEIGHT_DEFT; cam_ctx->capture_input_format = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR; cam_ctx->capture_output_format = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR; cam_ctx->frame_rate = FRAMERATE_DEFT; // init function dispatch table#ifdef ADCM2650 adcm2650_func.init = camera_func_adcm2650_init; adcm2650_func.deinit = camera_func_adcm2650_deinit; adcm2650_func.set_capture_format = camera_func_adcm2650_set_capture_format; adcm2650_func.start_capture = camera_func_adcm2650_start_capture; adcm2650_func.stop_capture = camera_func_adcm2650_stop_capture; cam_ctx->camera_functions = &adcm2650_func;#endif#ifdef OV9640 ov9640_func.init = camera_func_ov9640_init; ov9640_func.deinit = camera_func_ov9640_deinit; ov9640_func.set_capture_format = camera_func_ov9640_set_capture_format; ov9640_func.start_capture = camera_func_ov9640_start_capture; ov9640_func.stop_capture = camera_func_ov9640_stop_capture; cam_ctx->camera_functions = &ov9640_func;#endif#ifdef OV9650 //hzh ov9650_func.init = camera_func_ov9650_init; ov9650_func.deinit = camera_func_ov9650_deinit; ov9650_func.set_capture_format = camera_func_ov9650_set_capture_format; ov9650_func.start_capture = camera_func_ov9650_start_capture; ov9650_func.stop_capture = camera_func_ov9650_stop_capture; cam_ctx->camera_functions = &ov9650_func;#endif cam_ctx->ost_reg_base = 0; cam_ctx->gpio_reg_base = 0; cam_ctx->ci_reg_base = 0; cam_ctx->board_reg_base = 0; cam_ctx->dma_descriptors_virtual = dma_alloc_writecombine( g_camera_device, MAX_DESC_NUM * sizeof(pxa_dma_desc), (void *)&cam_ctx->dma_descriptors_physical, GFP_KERNEL); if (!cam_ctx->dma_descriptors_virtual) goto open_error; cam_ctx->buf_size = BUF_SIZE_DEFT; cam_ctx->buffer_virtual = dma_alloc_writecombine( g_camera_device, cam_ctx->buf_size, (void *)&cam_ctx->buffer_physical, GFP_KERNEL); if (!cam_ctx->buffer_virtual) goto open_error; cam_ctx->dma_descriptors_size = MAX_DESC_NUM; status = camera_init(cam_ctx); printk("PXA_CAMERA: pxa_camera_open, status = %d \n", status); return status;open_error: if (cam_ctx->dma_descriptors_virtual) dma_free_writecombine (g_camera_device, MAX_DESC_NUM * sizeof (pxa_dma_desc), cam_ctx->dma_descriptors_virtual, (int)cam_ctx->dma_descriptors_physical); return -1;}static int pxa_camera_close(struct inode *inode, struct file *file) { camera_context_t *cam_ctx = g_camera_context;// if(still_image_mode==0) //mased by hzh, stop DMA no contion camera_stop_video_capture(cam_ctx); camera_deinit(cam_ctx); if (cam_ctx->dma_descriptors_virtual) dma_free_writecombine (g_camera_device, MAX_DESC_NUM * sizeof (pxa_dma_desc), cam_ctx->dma_descriptors_virtual, (int)cam_ctx->dma_descriptors_physical); if (cam_ctx->buffer_virtual) dma_free_writecombine (g_camera_device, cam_ctx->buf_size, cam_ctx->buffer_virtual, (int)cam_ctx->buffer_physical); atomic_dec(&cam_ctx->refcount); printk("PXA_CAMERA: pxa_camera_close\n"); return 0; }static ssize_t pxa_camera_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ camera_context_t *cam_ctx = g_camera_context; int offset = 0; count = min(count, cam_ctx->block_size); //add by hzh if (still_image_mode == 1 && still_image_rdy == 1) { if (copy_to_user(buf, cam_ctx->buffer_virtual + offset, count)) //hzh return -EFAULT; still_image_rdy = 0; return cam_ctx->block_size; } if (first_video_frame == 1) first_video_frame = 0; else if (still_image_mode == 0) cam_ctx->block_tail = (cam_ctx->block_tail + 1) % cam_ctx->block_number; offset = cam_ctx->block_tail * cam_ctx->block_size; if (cam_ctx->block_header == cam_ctx->block_tail) { task_waiting = 1; interruptible_sleep_on (&camera_wait_q); } if (copy_to_user(buf, cam_ctx->buffer_virtual + offset, count)) //hzh return -EFAULT; return cam_ctx->block_size;}struct reg_set_s { int val1; int val2;};static int pxa_camera_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param){ int retval = 0; camera_context_t *cam_ctx = g_camera_context; switch (cmd) {/* V4L Standard IOCTL. */ case VIDIOCGCAP: { struct video_capability vc; strcpy (vc.name, "Bulverde Camera"); vc.maxwidth = MAX_WIDTH; vc.maxheight = MAX_HEIGHT; vc.minwidth = MIN_WIDTH; vc.minheight = MIN_HEIGHT; if (copy_to_user((int __user*)param, &vc, sizeof(struct video_capability))) return -EFAULT; break; } /* get capture size */ case VIDIOCGWIN: { struct video_window vw; vw.width = cam_ctx->capture_width; vw.height = cam_ctx->capture_height; if (copy_to_user((int __user*)param, &vw, sizeof(struct video_window))) retval = -EFAULT; break; } /* set capture size. */ case VIDIOCSWIN: { struct video_window vw; if (copy_from_user(&vw, (int __user*)param, sizeof(vw))) { retval = -EFAULT; break; } if (vw.width > MAX_WIDTH || vw.height > MAX_HEIGHT || vw.width < MIN_WIDTH || vw.height < MIN_HEIGHT) { retval = -EFAULT; break; } cam_ctx->capture_width = vw.width; cam_ctx->capture_height = vw.height; camera_set_capture_format(cam_ctx); break; } case VIDIOCSPICT: { struct video_picture vp; if (copy_from_user(&vp, (int __user*)param, sizeof(vp))) { retval = -EFAULT; break; } cam_ctx->capture_output_format = vp.palette; retval = camera_set_capture_format(cam_ctx); break; } case VIDIOCGPICT: { struct video_picture vp; vp.palette = cam_ctx->capture_output_format; if (copy_to_user((int __user*)param, &vp, sizeof(struct video_picture))) retval = -EFAULT; break; } case VIDIOCCAPTURE: { int capture_flag; capture_flag = (int)param;/* Still Image Capture */ if (capture_flag == STILL_IMAGE) { camera_set_int_mask(cam_ctx, 0x3f9 | 0x0400); cam_ctx->block_header = 0; cam_ctx->block_tail = 0; still_image_mode = 1; camera_capture_still_image(cam_ctx, 0); break; }/* Video Capture Start */ else if (capture_flag == VIDEO_START) { camera_set_int_mask(cam_ctx, 0x3f9 | 0x0400); cam_ctx->block_header = 0; cam_ctx->block_tail = 0; still_image_mode = 0; first_video_frame = 1; camera_start_video_capture (cam_ctx, 0); break; }/* Video Capture Stop */ else if (capture_flag == VIDEO_STOP) { camera_stop_video_capture(cam_ctx); break; } else { retval = -EFAULT; break; } }/* mmap interface */ case VIDIOCGMBUF: { struct video_mbuf vm; int i; memset(&vm, 0, sizeof(vm)); vm.size = cam_ctx->buf_size; vm.frames = cam_ctx->block_number; for (i = 0; i < vm.frames; i++) vm.offsets[i] = cam_ctx->block_size * i; if (copy_to_user((int __user*)param, (void *)&vm, sizeof(vm))) retval = -EFAULT; break; }/* Application extended IOCTL. *//* Register access interface */ case WCAM_VIDIOCSINFOR: { struct reg_set_s reg_s; if (copy_from_user(®_s, (int __user*)param, sizeof(int) * 2)) { retval = -EFAULT; break; } cam_ctx->capture_input_format = reg_s.val1; cam_ctx->capture_output_format = reg_s.val2; retval = camera_set_capture_format(cam_ctx); break; } case WCAM_VIDIOCGINFOR: { struct reg_set_s reg_s; reg_s.val1 = cam_ctx->capture_input_format; reg_s.val2 = cam_ctx->capture_output_format; if (copy_to_user((int __user*)param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCGCIREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, (int __user*)param, sizeof(int) * 2)) { retval = -EFAULT; break; } reg_s.val2 = ci_get_reg_value (reg_s.val1); if (copy_to_user((int __user*)param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCSCIREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, (int __user*)param, sizeof(int) * 2)) { retval = -EFAULT; break; } ci_set_reg_value (reg_s.val1, reg_s.val2); break; }#ifdef ADCM2650 case WCAM_VIDIOCGCAMREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, (int __user*)param, sizeof(int) * 2)) { retval = -EFAULT; break; } adcm2650_pipeline_read((u16)reg_s.val1, (u16 *)®_s.val2); if (copy_to_user((int __user*)param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCSCAMREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, (int __user*)param, sizeof(int) * 2)) { retval = -EFAULT; break; } adcm2650_pipeline_write ((u16)reg_s.val1, (u16)reg_s.val2); break; }#endif#ifdef OV9650#ifndef CONFIG_USER_I2C_INIT case WCAM_VIDIOCGCAMREG: { u16 val; if (copy_from_user(&val, (int __user*)param, sizeof(u16))) { retval = -EFAULT; break; } val &= ~0xff; val |= sccb_receivebyte(val>>8); if (copy_to_user((int __user*)param, &val, sizeof(u16))) retval = -EFAULT; break; } case WCAM_VIDIOCSCAMREG: { u16 val; if (copy_from_user(&val, (int __user*)param, sizeof(u16))) { retval = -EFAULT; break; } sccb_sendbyte(val>>8, val); break; }#endif case WCAM_VIDIOCSPRLVL: camera_ov9650_set_level(param); break;#endif default: { printk ("Invalid ioctl parameters.\n"); retval = -ENOIOCTLCMD; break; } } return retval;}#define pte_offset(dir, addr) ((pte_t *)pmd_page(*(dir)) + __pte_index(addr))static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr){ unsigned long ret = 0UL; pmd_t *pmd; pte_t *ptep, pte; if (!pgd_none(*pgd)) { pmd = pmd_offset(pgd, adr); if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; if (pte_present(pte)) { ret = (unsigned long) page_address(pte_page(pte)); ret |= (adr & (PAGE_SIZE-1)); } } } return ret;}static inline unsigned long kvirt_to_pa(unsigned long adr){ unsigned long va, kva, ret; va=(unsigned long) (adr); kva = uvirt_to_kva(pgd_offset_k(va), va); ret = __pa(kva); return ret;}static int pxa_camera_mmap(struct file *file, struct vm_area_struct *vma){ unsigned long start = (unsigned long)vma->vm_start; unsigned long end = (unsigned long)vma->vm_end; unsigned long size=end-start; unsigned long page, pos; camera_context_t *cam_ctx = g_camera_context;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -