📄 iic.c
字号:
// set dma end interrupt if ( mask & CAMERA_INTMASK_END_OF_DMA ) dma_interrupt_on = 1; else dma_interrupt_on = 0; // set fifo0 dma chains' flag end_des_virtual = (pxa_dma_desc*)camera_context->fifo0_descriptors_virtual + camera_context->fifo0_num_descriptors - 1; for(i=0; i<camera_context->block_number; i++) { if (dma_interrupt_on) end_des_virtual->dcmd |= DCMD_ENDIRQEN; else end_des_virtual->dcmd &= ~DCMD_ENDIRQEN; end_des_virtual += camera_context->fifo0_num_descriptors; }} // get interrupt mask unsigned int camera_get_int_mask( p_camera_context_t camera_context ){ pxa_dma_desc *end_des_virtual; unsigned int ret; // get CI mask ret = ci_get_int_mask(); // get dma end mask end_des_virtual = (pxa_dma_desc *)camera_context->fifo0_descriptors_virtual + camera_context->fifo0_num_descriptors - 1; if (end_des_virtual->dcmd & DCMD_ENDIRQEN) ret |= CAMERA_INTMASK_END_OF_DMA; return ret; } // clear interrupt statusvoid camera_clear_int_status( p_camera_context_t camera_context, unsigned int status ){ ci_clear_int_status( (status & 0xFFFF) ); }/************************************************************************************ Application interface ************************************************************************************/static int pxa_camera_open(struct video_device *dev, int flags){ int status = -1; camera_context_t *cam_ctx; printk("pxa_camera_open run start\n"); cam_ctx = g_camera_context; if (atomic_read(&cam_ctx->refcount))// return -EBUSY; atomic_inc(&cam_ctx->refcount); init_waitqueue_head(&camera_wait_q); cam_ctx->sensor_type = CAMERA_TYPE_ADCM_2650; 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 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; cam_ctx->ost_reg_base = 0; cam_ctx->gpio_reg_base = 0; cam_ctx->ci_reg_base = 0; cam_ctx->board_reg_base = 0; /* FIXME: handle camera_init() errors ? */ printk("camera_init call here\n"); status = camera_init(cam_ctx); printk(KERN_DEBUG PREFIX "camera opened\n"); printk("camera open finished\n"); status = 0; return status;}static void pxa_camera_close(struct video_device *dev){ camera_context_t *cam_ctx = g_camera_context; printk(KERN_DEBUG PREFIX "camera closed\n"); atomic_dec(&cam_ctx->refcount); camera_deinit(cam_ctx);}static long pxa_camera_read(struct video_device *dev, char *buf, unsigned long count, int noblock){ camera_context_t *cam_ctx = g_camera_context; int offset = 0; if (still_image_mode == 1 && still_image_rdy == 1) { if (copy_to_user(buf, cam_ctx->buffer_virtual + offset, cam_ctx->block_size)) 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, cam_ctx->block_size)) return -EFAULT; return cam_ctx->block_size;}struct reg_set_s { int val1; int val2;};static int pxa_camera_ioctl(struct video_device *dev, unsigned int cmd, void *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(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(param, &vw, sizeof(struct video_window))) retval = -EFAULT; break; } /* set capture size. */ case VIDIOCSWIN: { struct video_window vw; if (copy_from_user(&vw, 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, 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(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_set_int_mask(cam_ctx, 0x3ff); 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((void *)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, 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(param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCGCIREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, param, sizeof(int) * 2)) { retval = -EFAULT; break; } reg_s.val2 = ci_get_reg_value (reg_s.val1); if (copy_to_user(param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCSCIREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, param, sizeof(int) * 2)) { retval = -EFAULT; break; } ci_set_reg_value (reg_s.val1, reg_s.val2); break; } case WCAM_VIDIOCGCAMREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, param, sizeof(int) * 2)) { retval = -EFAULT; break; } adcm2650_pipeline_read((u16)reg_s.val1, (u16 *)®_s.val2); if (copy_to_user(param, ®_s, sizeof(int) * 2)) retval = -EFAULT; break; } case WCAM_VIDIOCSCAMREG: { struct reg_set_s reg_s; if (copy_from_user(®_s, param, sizeof(int) * 2)) { retval = -EFAULT; break; } adcm2650_pipeline_write ((u16)reg_s.val1, (u16)reg_s.val2); break; } case WCAM_VIDIOCGCAPINFO: { struct camera_capture_info_s cap_info; cap_info.first_frame_id = camera_get_first_frame_buffer_id(cam_ctx); cap_info.last_frame_id = camera_get_last_frame_buffer_id(cam_ctx); cap_info.frames = camera_get_num_frame_buffers(cam_ctx); if (copy_to_user((void *)param, (void *)&cap_info, sizeof(struct camera_capture_info_s))) retval = -EFAULT; break; } default: printk(KERN_WARNING PREFIX "invalid ioctl %x\n", cmd); retval = -ENOIOCTLCMD; break; } return retval;}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 = VMALLOC_VMADDR(adr); kva = uvirt_to_kva(pgd_offset_k(va), va); ret = __pa(kva); return ret;}static int pxa_camera_mmap(struct video_device *dev, const char *adr, unsigned long size){ unsigned long start = (unsigned long)adr; unsigned long page, pos; camera_context_t *cam_ctx = g_camera_context; pos = (unsigned long)(cam_ctx->buffer_virtual); page = kvirt_to_pa(pos); if (remap_page_range(start, page, size, PAGE_SHARED)) { return -EFAULT; } return 0;}unsigned int pxa_camera_poll(struct video_device *dev, struct file *file, poll_table *wait) { camera_context_t *cam_ctx = g_camera_context; static int waited = 0; poll_wait(file, &camera_wait_q, wait); if (still_image_mode == 1 && still_image_rdy == 1) { still_image_rdy = 0; return POLLIN | POLLRDNORM; } if (first_video_frame == 1) first_video_frame = 0; else if (still_image_mode == 0 && waited != 1) cam_ctx->block_tail = (cam_ctx->block_tail + 1) % cam_ctx->block_number; if (cam_ctx->block_header == cam_ctx->block_tail) { //printk ("enter waiting, tail = %d, header = %d \n", cam_ctx->block_tail, cam_ctx->block_header); task_waiting = 1; waited = 1; //interruptible_sleep_on (&camera_wait_q); return 0; } else waited = 0; return POLLIN | POLLRDNORM;}int pxa_camera_video_init(struct video_device *vdev){ printk(KERN_DEBUG PREFIX "camera initialized\n"); return 0;}static struct video_device vd = { owner: THIS_MODULE, name: "PXA Camera", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_PXA_CAMERA, /* FIXME */ open: pxa_camera_open, close: pxa_camera_close, read: pxa_camera_read, poll: pxa_camera_poll,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -