📄 ppcore.c
字号:
static unsigned intpp_poll(struct file *file, poll_table *table){ if (pp_suspended) return -EPERM; if (!frame_in_process) return (POLLIN | POLLRDNORM); poll_wait (file, &frame_complete, table); return 0;}static int pp_open(struct inode *inode, struct file *file){ if (pp_suspended) return -EPERM; if (pp_busy) return -EBUSY; pp_busy = 1; mx_module_clk_open(HCLK_MODULE_EMMA); mx_module_clk_open(IPG_MODULE_EMMA); EMMA_PP_CNTL |= PP_CNTL_SWRST; mdelay(5); if (EMMA_PP_CNTL & PP_CNTL_SWRST) { err("PP Reset error\n"); return -EIO; } MOD_INC_USE_COUNT; enable_irq(INT_EMMAPP); return 0;}static intpp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ if (pp_suspended) return -EPERM; if (frame_in_process) return -EAGAIN; switch (cmd) { /* Set ouput format*/ case VIDIOC_S_FMT: { struct v4l2_format *fmt = (void*)arg; struct v4l2_pix_format *pfmt = &(fmt->fmt.pix); if (!fmt) { return -EINVAL; } switch (pfmt->pixelformat) { case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_RGB565: /*TODO additioanl format can be support * (RGB555, RGB 888)*/ pfmt->depth = 16; break; default: /*XXX Add adtitinal YUVdata types from book */ return -EINVAL; } this->out_format = *fmt; return set_frame_parameters(&(this->in_format.fmt.pix), &(this->out_format.fmt.pix)); } /* Get ouput format */ case VIDIOC_G_FMT: { struct v4l2_format *fmt = (void*)arg; if (!fmt) { return -EINVAL; } *fmt = this->out_format; return 0; /* Set input format*/ } case VIDIOC_S_IN_FMT: { struct v4l2_format *fmt = (void*)arg; struct v4l2_pix_format *pfmt = &(fmt->fmt.pix); int oldfrmsize, frmsize; if (!fmt) { return -EINVAL; } if (pfmt->pixelformat != V4L2_PIX_FMT_YUV420) { return -EINVAL; } frmsize = pfmt->width * pfmt->height * 2; oldfrmsize = this->in_format.fmt.pix.width * this->in_format.fmt.pix.height * 2; if (frmsize > oldfrmsize) { if (frame_buf) { consistent_free(frame_buf, oldfrmsize, frame_buf_phys); } frame_buf = consistent_alloc(GFP_KERNEL | GFP_DMA, frmsize, &frame_buf_phys); frame_size = frmsize; if (!frame_buf) { return -ENOMEM; } } this->in_format = *fmt; return set_frame_parameters(&(this->in_format.fmt.pix), &(this->out_format.fmt.pix)); } /* Get input format */ case VIDIOC_G_IN_FMT: { struct v4l2_format *fmt = (void*)arg; if (!fmt) { return -EINVAL; } *fmt = this->in_format; if (this->Yptr) { set_in_pointers(this->Yptr); } return 0; } case VIDIOC_S_IN_PTR: { if (!arg) return -EINVAL; this->Yptr = (unsigned int)arg; set_in_pointers(this->Yptr); return 0; } case VIDIOC_S_OUT_PTR: { if (!arg) return -EINVAL; this->outptr = (void *)arg; return 0; } case VIDIOC_START: { return pp_start(); } case VIDIOC_POLL: { return frame_in_process; } case VIDIOC_S_OUT_STRIDE: { if (!((int)arg)) { return -EINVAL; } this->out_stride = (int)arg; return 0; } default: { return -ENOIOCTLCMD; } } return -ENOIOCTLCMD;}static ssize_tpp_write (struct file *file, const char *buf, size_t count, loff_t *ppos){ int ret; if (pp_suspended) return -EPERM; if (frame_in_process) return -EAGAIN; copy_from_user(frame_buf, buf, count); set_in_pointers(frame_buf_phys); if ((ret = pp_start())) { return ret; } return count;}static intpp_fasync(int fd, struct file *filp, int mode){ return 0;}static intpp_close(struct inode *inode, struct file *file){ disable_irq(INT_EMMAPP); if (!check_mem_region(EMMA_PRP_BASE, EMMA_PRP_IO_SIZE)) { /* If no PRP modules exists in same time stop clocks */ mx_module_clk_close(HCLK_MODULE_EMMA); mx_module_clk_close(IPG_MODULE_EMMA); } MOD_DEC_USE_COUNT; pp_busy = 0; return 0;}static struct file_operations pp_fops = { open: pp_open, write: pp_write, ioctl: pp_ioctl, release: pp_close, fasync: pp_fasync, poll: pp_poll,};static void __initpp_exit(void){ if (irq_requested) { free_irq(INT_EMMAPP, NULL); irq_requested = 0;#if 1 /* power management */ mx21_ldm_bus_unregister( &mx2ads_pp_device_ldm, &mx2ads_pp_driver_ldm);#ifdef CONFIG_PM if (mx2ads_pp_pmdev) pm_unregister(mx2ads_pp_pmdev);#endif#endif /* power management */ } if (frame_buf) { consistent_free(frame_buf, frame_size, frame_buf_phys); } if(major > 0) { if(devfs_unregister_chrdev(major, "emma_pp") < 0) { err("failed to unregister from devfs\n"); return; } } if(devfs_handle != NULL) { devfs_unregister(devfs_handle); } else { err("failed to unregister from devfs, devfs_handle = 0x%p\n", devfs_handle); return; } if (mem_region_reserved) { release_mem_region(EMMA_PP_BASE, EMMA_PP_IO_SIZE); }}#define PP_MIN_HCLK 33000int __initpp_init(void){#if 1 /*CEE LDM*/ if (PP_MIN_HCLK > mx_module_get_clk(HCLK) / 1000) { err("cannot initialize - HCLK too slow\n"); return -EPERM; }#endif this = &pp_dev; memset(&pp_dev, 0, sizeof(pp_dev)); major = devfs_register_chrdev(0, "emma_pp", &pp_fops); if ( major < 0 ) { err("unable to register character device\n"); pp_exit(); return -ENODEV; } devfs_handle = devfs_register(NULL, "emma_pp", DEVFS_FL_DEFAULT, major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &pp_fops, NULL); if(devfs_handle == NULL) { err("unable to register devfs driver\n"); pp_exit(); return -ENODEV; } if (!request_mem_region(EMMA_PP_BASE, EMMA_PP_IO_SIZE, "MX21.EMMA PP registers")) { err("EMMA PP memory region is already in use\n"); dbg("Address=0x%08x, size=0x%x\n", EMMA_PP_BASE, EMMA_PP_IO_SIZE); pp_exit(); return -1; } mem_region_reserved = 1; if (request_irq(INT_EMMAPP, pp_isr, SA_INTERRUPT, "eMMa PP", NULL)) { err("Error requesting IRQ\n"); pp_exit(); return -ENODEV; } irq_requested = 1; disable_irq(INT_EMMAPP); init_waitqueue_head (&frame_complete);#if 1 /* power management */#ifdef CONFIG_DPM mx2ads_pp_constraints.param[0].min = PP_MIN_HCLK; /*in KHz */ mx2ads_pp_constraints.param[0].max = mx_module_get_clk(MPLL) / 1000; /* unlimited */#endif mx21_ldm_bus_register(&mx2ads_pp_device_ldm, &mx2ads_pp_driver_ldm);#ifdef CONFIG_PM mx2ads_pp_pmdev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, mx2ads_pp_pm_callback); if (!mx2ads_pp_pmdev) warn("failed to initialize static power management\n");#endif /* CONFIG_PM */#endif /* power management */ return 0;}#ifdef MODULEmodule_init(pp_init);module_exit(pp_exit);#endif MODULE_LICENSE ("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -