diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/media/sprd_rotation | |
Diffstat (limited to 'drivers/media/sprd_rotation')
| -rw-r--r-- | drivers/media/sprd_rotation/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/Makefile | 7 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/img_rot.c | 390 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/img_rot.h | 17 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/rot_drv.c | 339 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/rot_drv.h | 62 | ||||
| -rw-r--r-- | drivers/media/sprd_rotation/rot_reg.h | 71 |
7 files changed, 891 insertions, 0 deletions
diff --git a/drivers/media/sprd_rotation/Kconfig b/drivers/media/sprd_rotation/Kconfig new file mode 100644 index 00000000..1d7bb99f --- /dev/null +++ b/drivers/media/sprd_rotation/Kconfig @@ -0,0 +1,5 @@ +config SPRD_ROT + depends on ARCH_SCX35 + bool "Spreadtrum Rotation Driver" + help + Say Y to support spreadtrum rotation device driver diff --git a/drivers/media/sprd_rotation/Makefile b/drivers/media/sprd_rotation/Makefile new file mode 100644 index 00000000..f47c67ff --- /dev/null +++ b/drivers/media/sprd_rotation/Makefile @@ -0,0 +1,7 @@ +include drivers/media/sprd_dcam/common/Makefile.inc + +ifeq ($(CONFIG_ARCH_SCX35),y) +sprd_rotation-objs := rot_drv.o img_rot.o +obj-y += sprd_rotation.o +endif + diff --git a/drivers/media/sprd_rotation/img_rot.c b/drivers/media/sprd_rotation/img_rot.c new file mode 100644 index 00000000..ac91f346 --- /dev/null +++ b/drivers/media/sprd_rotation/img_rot.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/poll.h> +#include <linux/fs.h> +#include <linux/irq.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/miscdevice.h> +#include <asm/io.h> +#include <linux/file.h> +#include <linux/sched.h> +#include <video/sprd_rot_k.h> +#include <linux/slab.h> +#include <linux/kthread.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/vmalloc.h> +#include "dcam_drv.h" +#include "rot_drv.h" +#include "img_rot.h" + +#define ROT_DEVICE_NAME "sprd_rotation" +#define ROT_TIMEOUT 5000/*ms*/ +#define ROTATION_MINOR MISC_DYNAMIC_MINOR + +struct rot_k_private { + struct semaphore start_sem; +}; + +struct rot_k_file { + struct rot_k_private *rot_private; + struct semaphore rot_done_sem; + /*for dcam rotation module*/ + struct rot_drv_private drv_private; + struct device_node *dn; +}; + +static void rot_k_irq(void *fd) +{ + struct rot_k_file *rot_file = (struct rot_k_file*)fd; + + if (!rot_file) { + return; + } + + up(&rot_file->rot_done_sem); +} + +static int rot_k_start(struct rot_k_file *fd) +{ + int ret = 0; + ROT_PARAM_CFG_T *s; + + if (!fd) { + ret = -EFAULT; + goto start_exit; + } + s = &(fd->drv_private.cfg); + rot_k_register_cfg(s); + +start_exit: + return ret; +} + +struct platform_device* rot_get_platform_device(void) +{ + struct device *dev; + + dev = bus_find_device_by_name(&platform_bus_type, NULL, ROT_DEVICE_NAME); + if (!dev) { + printk("%s: failed to find device\n", __func__); + return NULL; + } + + return to_platform_device(dev); +} + +static int rot_k_open(struct inode *node, struct file *file) +{ + int ret = 0; + struct rot_k_file *fd = NULL; + struct miscdevice *md = file->private_data ; + struct rot_k_private *rot_private = NULL; + + if (!md) { + ret = -EFAULT; + printk("rot_k_open fail miscdevice NULL \n"); + goto exit; + } + + rot_private = md->this_device->platform_data; + if (!rot_private) { + ret = -EFAULT; + printk("rot_k_open fail rot_private NULL \n"); + goto exit; + } + + fd = vzalloc(sizeof(*fd)); + if (!fd) { + ret = -ENOMEM; + printk("rot_k_open fail alloc \n"); + goto exit; + } + fd->rot_private = rot_private; + fd->drv_private.rot_fd = (void*)fd; + fd ->dn = md->this_device->of_node; + + spin_lock_init(&fd->drv_private.rot_drv_lock); + + sema_init(&fd->rot_done_sem, 0); + + file->private_data = fd; + + ROTATE_TRACE("rot_k_open success\n"); + +exit: + return ret; +} + +static int rot_k_release(struct inode *node, struct file *file) +{ + struct rot_k_private *rot_private; + struct rot_k_file *fd; + + fd = file->private_data; + if (!fd) { + goto release_exit; + } + + rot_private = fd->rot_private; + if (!rot_private) { + goto fd_free; + } + + down(&rot_private->start_sem); + up(&rot_private->start_sem); + +fd_free: + vfree(fd); + fd = NULL; + file->private_data = NULL; + +release_exit: + + ROTATE_TRACE("rot_k_release\n"); + + return 0; +} + +static long rot_k_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct rot_k_private *rot_private; + struct rot_k_file *fd; + ROT_CFG_T params; + ROT_PARAM_CFG_T *s; + + fd = file->private_data; + if (!fd) { + ret = - EFAULT; + printk("rot_k_ioctl fail fd NULL \n"); + goto ioctl_exit; + } + + rot_private = fd->rot_private; + if (!rot_private) { + ret = -EFAULT; + printk("rot_k_ioctl fail rot private NULL \n"); + goto ioctl_exit; + } + + s = &(fd->drv_private.cfg); + + switch (cmd) { + case ROT_IO_START: + down(&rot_private->start_sem); + + ret = rot_k_module_en(fd->dn); + if (unlikely(ret)) { + printk("rot_k_ioctl error : rot_k_module_en\n"); + up(&rot_private->start_sem); + goto ioctl_exit; + } + + ret = rot_k_isr_reg(rot_k_irq, &fd->drv_private); + if (unlikely(ret)) { + printk("rot_k_ioctl error : Failed to register rot ISR \n"); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + goto ioctl_exit; + } + + ret = copy_from_user(¶ms, (ROT_CFG_T *) arg, sizeof(ROT_CFG_T)); + if (ret) { + printk("rot_k_ioctl error, failed get user info \n"); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + goto ioctl_exit; + } + + ret = rot_k_io_cfg(¶ms,&fd->drv_private.cfg); + if (ret) { + printk("rot_k_ioctl error, failed cfg \n"); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + goto ioctl_exit; + } + + ret = rot_k_start(fd); + if (ret) { + printk("rot_k_ioctl error: failed start \n"); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + goto ioctl_exit; + } + + if (0 == rot_k_is_end(s)) { + ret = down_timeout(&fd->rot_done_sem, msecs_to_jiffies(ROT_TIMEOUT)); + //ret = down_interruptible(&fd->rot_done_sem); + if (ret) { + printk("rot_k_ioctl error: rot_k_thread y wait error \n"); + goto ioctl_out; + } + + ROTATE_TRACE("rot_k_ioctl: rot_k_start y done, uv start. \n"); + + rot_k_set_UV_param(s); + ret = rot_k_start(fd); + if (ret) { + printk("rot_k_ioctl error: failed second start \n"); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + goto ioctl_exit; + } + } + + ret = down_timeout(&fd->rot_done_sem, msecs_to_jiffies(ROT_TIMEOUT)); + if (ret) { + printk("rot_k_ioctl error: rot_k_thread wait error \n"); + goto ioctl_out; + } + + rot_k_close(); + + rot_k_module_dis(fd ->dn); + + up(&rot_private->start_sem); + break; + default: + break; + } + +ioctl_exit: + + ROTATE_TRACE("rot_k_ioctl ret=%d \n", ret); + return ret; + +ioctl_out: + rot_k_isr_reg(NULL, NULL); + dcam_rotation_end(); + rot_k_close(); + rot_k_module_dis(fd ->dn); + up(&rot_private->start_sem); + return ret; + +} + +static struct file_operations rotation_fops = { + .owner = THIS_MODULE, + .open = rot_k_open, + .unlocked_ioctl = rot_k_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = rot_k_ioctl, +#endif + .release = rot_k_release, +}; + +static struct miscdevice rotation_dev = { + .minor = ROTATION_MINOR, + .name = ROT_DEVICE_NAME, + .fops = &rotation_fops, +}; + +int rot_k_probe(struct platform_device *pdev) +{ + int ret; + struct rot_k_private *rot_private; + struct device *dev = NULL; + + printk(KERN_ALERT "rot_k_probe called\n"); + + rot_private = devm_kzalloc(&pdev->dev, sizeof(*rot_private), GFP_KERNEL); + if (!rot_private) { + return -ENOMEM; + } + + sema_init(&rot_private->start_sem, 1); + + platform_set_drvdata(pdev, rot_private); + + ret = misc_register(&rotation_dev); + if (ret) { + printk(KERN_ERR "cannot register miscdev on minor=%d (%d)\n", + ROTATION_MINOR, ret); + ret = -EACCES; + goto probe_out; + } + dev = rotation_dev.this_device; + dev->of_node = pdev->dev.of_node; + dev->platform_data = (void *)rot_private; + + printk(KERN_ALERT " rot_k_probe Success\n"); + goto exit; +probe_out: + devm_kfree(&pdev->dev, rot_private); + platform_set_drvdata(pdev, NULL); +exit: + return 0; +} + +static int rot_k_remove(struct platform_device *pdev) +{ + struct rot_k_private *rot_private; + + rot_private = platform_get_drvdata(pdev); + + if (!rot_private) + goto remove_exit; + + printk(KERN_INFO "rot_k_remove called !\n"); + misc_deregister(&rotation_dev); + + devm_kfree(&pdev->dev, rot_private); + platform_set_drvdata(pdev, NULL); + printk(KERN_INFO "rot_k_remove Success !\n"); + +remove_exit: + return 0; +} + +static const struct of_device_id of_match_table_rot[] = { + { .compatible = "sprd,sprd_rotation", }, + { }, +}; + +static struct platform_driver rotation_driver = { + .probe = rot_k_probe, + .remove = rot_k_remove, + .driver = { + .owner = THIS_MODULE, + .name = ROT_DEVICE_NAME, + .of_match_table = of_match_ptr(of_match_table_rot), + }, +}; + +int __init rot_k_init(void) +{ + printk(KERN_INFO "rot_k_init called !\n"); + if (platform_driver_register(&rotation_driver) != 0) { + printk("platform device register Failed \n"); + return -1; + } + return 0; +} + +void rot_k_exit(void) +{ + printk(KERN_INFO "rot_k_exit called !\n"); + platform_driver_unregister(&rotation_driver); +} + +module_init(rot_k_init); +module_exit(rot_k_exit); +MODULE_DESCRIPTION("rotation Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/sprd_rotation/img_rot.h b/drivers/media/sprd_rotation/img_rot.h new file mode 100644 index 00000000..042b1cf3 --- /dev/null +++ b/drivers/media/sprd_rotation/img_rot.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _IMG_ROT_H_ +#define _IMG_ROT_H_ + +#endif diff --git a/drivers/media/sprd_rotation/rot_drv.c b/drivers/media/sprd_rotation/rot_drv.c new file mode 100644 index 00000000..335a8fcf --- /dev/null +++ b/drivers/media/sprd_rotation/rot_drv.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <asm/io.h> +#include <video/sprd_rot_k.h> +#ifndef CONFIG_64BIT +#include <soc/sprd/hardware.h> +#endif +#include <soc/sprd/sci.h> +#include "img_rot.h" +#include "rot_drv.h" +#include "dcam_drv.h" + +#define ALGIN_FOUR 0x03 + +int rot_k_module_en(struct device_node *dn) +{ + int ret = 0; + + ret = dcam_module_en(dn); + + if (ret) { + printk("dcam_module_en, failed %d \n", ret); + } + + return ret; +} + +int rot_k_module_dis(struct device_node *dn) +{ + int ret = 0; + + ret = dcam_module_dis(dn); + + if (ret) { + printk("rot_k_module_dis, failed %d \n", ret); + } + + return ret; +} + +static void rot_k_ahb_reset(void) +{ + sci_glb_set(REG_ROTATION_AHB_RESET, ROT_AHB_RESET_BIT); + sci_glb_clr(REG_ROTATION_AHB_RESET, ROT_AHB_RESET_BIT); +} + +static void rot_k_set_src_addr(uint32_t src_addr) +{ + REG_WR(REG_ROTATION_SRC_ADDR, src_addr); +} + +static void rot_k_set_dst_addr(uint32_t dst_addr) +{ + REG_WR(REG_ROTATION_DST_ADDR, dst_addr); +} + +static void rot_k_set_img_size(ROT_SIZE_T * size) +{ + REG_WR(REG_ROTATION_OFFSET_START, 0x00000000); + REG_WR(REG_ROTATION_IMG_SIZE, + ((size->w & 0x1FFF) | ((size->h & 0x1FFF) << 13))); + REG_WR(REG_ROTATION_ORIGWIDTH, (size->w & 0x1FFF)); +} + +static void rot_k_set_endian(ROT_ENDIAN_E src_end, ROT_ENDIAN_E dst_end) +{ + dcam_glb_reg_awr(REG_ROTATION_ENDIAN_SEL, + (~(ROT_RD_ENDIAN_MASK |ROT_WR_ENDIAN_MASK)), DCAM_ENDIAN_REG); + + dcam_glb_reg_owr(REG_ROTATION_ENDIAN_SEL, + (ROT_AXI_RD_WORD_ENDIAN_BIT | + ROT_AXI_WR_WORD_ENDIAN_BIT | + (src_end << 16) |(dst_end << 14)), DCAM_ENDIAN_REG); +} + +static void rot_k_set_pixel_mode(ROT_PIXEL_FORMAT_E pixel_format) +{ + REG_AWR(REG_ROTATION_PATH_CFG, (~ROT_PIXEL_FORMAT_BIT)); + REG_OWR(REG_ROTATION_PATH_CFG, ((pixel_format & 0x1) << 1)); + return; +} + +static void rot_k_set_UV_mode(ROT_UV_MODE_E uv_mode) +{ + REG_AWR(REG_ROTATION_PATH_CFG, (~ROT_UV_MODE_BIT)); + REG_OWR(REG_ROTATION_PATH_CFG, ((uv_mode & 0x1) << 4)); + return; +} + +static void rot_k_set_dir(ROT_ANGLE_E angle) +{ + REG_AWR(REG_ROTATION_PATH_CFG, (~ROT_MODE_MASK)); + REG_OWR(REG_ROTATION_PATH_CFG, ((angle & 0x3) << 2)); +} + +static void rot_k_enable(void) +{ + REG_OWR(REG_ROTATION_PATH_CFG, ROT_EB_BIT); +} + +static void rot_k_disable(void) +{ + REG_AWR(REG_ROTATION_PATH_CFG, (~ROT_EB_BIT)); +} + +static void rot_k_start(void) +{ + REG_OWR(REG_ROTATION_PATH_CFG, ROT_START_BIT); +} + + +int rot_k_isr(struct dcam_frame* dcam_frm, void* u_data) +{ + unsigned long flag; + rot_isr_func user_isr_func; + struct rot_drv_private *private = (struct rot_drv_private *)u_data; + + (void)dcam_frm; + + if (!private) { + goto isr_exit; + } + + dcam_rotation_end(); + + spin_lock_irqsave(&private->rot_drv_lock, flag); + user_isr_func = private->user_isr_func; + if (user_isr_func) { + (*user_isr_func)(private->rot_fd); + } + spin_unlock_irqrestore(&private->rot_drv_lock, flag); + +isr_exit: + return 0; +} + +int rot_k_isr_reg(rot_isr_func user_func,struct rot_drv_private *drv_private) +{ + int rtn = 0; + unsigned long flag; + + if (user_func) { + if (!drv_private) { + rtn = -EFAULT; + goto reg_exit; + } + + spin_lock_irqsave(&drv_private->rot_drv_lock, flag); + drv_private->user_isr_func = user_func; + spin_unlock_irqrestore(&drv_private->rot_drv_lock, flag); + + dcam_reg_isr(DCAM_ROT_DONE, rot_k_isr, drv_private); + } else { + dcam_reg_isr(DCAM_ROT_DONE, NULL, NULL); + } + +reg_exit: + return rtn; +} + +int rot_k_is_end(ROT_PARAM_CFG_T *s) +{ + return s->is_end ; +} + +static uint32_t rot_k_get_end_mode(ROT_PARAM_CFG_T *s) +{ + uint32_t ret = 1; + + switch (s->format) { + case ROT_YUV422: + case ROT_YUV420: + ret = 0; + break; + case ROT_RGB565: + ret = 1; + break; + default: + ret = 1; + break; + } + return ret; +} + +static ROT_PIXEL_FORMAT_E rot_k_get_pixel_format(ROT_PARAM_CFG_T *s) +{ + ROT_PIXEL_FORMAT_E ret = ROT_ONE_BYTE; + + switch (s->format) { + case ROT_YUV422: + case ROT_YUV420: + ret = ROT_ONE_BYTE; + break; + case ROT_RGB565: + ret = ROT_TWO_BYTES; + break; + default: + ret = ROT_ONE_BYTE; + break; + } + + return ret; +} + +static int rot_k_set_y_param(ROT_CFG_T * param_ptr,ROT_PARAM_CFG_T *s) +{ + int ret = 0; + + if (!param_ptr || !s) { + ret = -EFAULT; + goto param_exit; + } + + memcpy((void *)&(s->img_size), (void *)&(param_ptr->img_size), + sizeof(ROT_SIZE_T)); + memcpy((void *)&(s->src_addr), (void *)&(param_ptr->src_addr), + sizeof(ROT_ADDR_T)); + memcpy((void *)&(s->dst_addr), (void *)&(param_ptr->dst_addr), + sizeof(ROT_ADDR_T)); + + s->s_addr = param_ptr->src_addr.y_addr; + s->d_addr = param_ptr->dst_addr.y_addr; + s->format = param_ptr->format; + s->angle = param_ptr->angle; + s->pixel_format = rot_k_get_pixel_format(s); + s->is_end = rot_k_get_end_mode(s); + s->uv_mode = ROT_NORMAL; + s->src_endian = 1;/*param_ptr->src_addr;*/ + s->dst_endian = 1;/*param_ptr->dst_endian;*/ + +param_exit: + return ret; +} + +int rot_k_set_UV_param(ROT_PARAM_CFG_T *s) +{ + s->s_addr = s->src_addr.u_addr; + s->d_addr = s->dst_addr.u_addr; + s->img_size.w >>= 0x01; + s->pixel_format = ROT_TWO_BYTES; + if (ROT_YUV422 == s->format){ + s->uv_mode = ROT_UV422; + } else if (ROT_YUV420 == s->format) { + s->img_size.h >>= 0x01; + } + return 0; +} + +void rot_k_register_cfg(ROT_PARAM_CFG_T *s) +{ + rot_k_ahb_reset(); + dcam_rotation_start(); + rot_k_set_src_addr(s->s_addr); + rot_k_set_dst_addr(s->d_addr); + rot_k_set_img_size(&(s->img_size)); + rot_k_set_pixel_mode(s->pixel_format); + rot_k_set_UV_mode(s->uv_mode); + rot_k_set_dir(s->angle); + rot_k_set_endian(s->src_endian, s->dst_endian); + rot_k_enable(); + rot_k_start(); + ROTATE_TRACE("rot_k_register_cfg.\n"); +} + +void rot_k_close(void) +{ + rot_k_disable(); +} + +static int rot_k_check_param(ROT_CFG_T * param_ptr) +{ + if (NULL == param_ptr) { + printk("Rotation: the param ptr is null.\n"); + return -1; + } + + if ((param_ptr->src_addr.y_addr & ALGIN_FOUR) + || (param_ptr->src_addr.u_addr & ALGIN_FOUR) + || (param_ptr->src_addr.v_addr & ALGIN_FOUR) + || (param_ptr->dst_addr.y_addr & ALGIN_FOUR) + || (param_ptr->dst_addr.u_addr & ALGIN_FOUR) + || (param_ptr->dst_addr.v_addr & ALGIN_FOUR)) { + printk("Rotation: the addr not algin.\n"); + return -1; + } + + if (!(ROT_YUV422 == param_ptr->format + || ROT_YUV420 == param_ptr->format + ||ROT_RGB565 == param_ptr->format)) { + printk("Rotation: data for err : %d.\n", param_ptr->format); + return -1; + } + + if (ROT_MIRROR < param_ptr->angle) { + printk("Rotation: data angle err : %d.\n", param_ptr->angle); + return -1; + } +#if 0 + if (ROT_ENDIAN_MAX <= param_ptr->src_endian || + ROT_ENDIAN_MAX <= param_ptr->dst_endian ) { + ROTATE_TRACE("Rotation: endian err : %d %d.\n", param_ptr->src_endian, + param_ptr->dst_endian); + return -1; + } +#endif + return 0; +} + +int rot_k_io_cfg(ROT_CFG_T * param_ptr,ROT_PARAM_CFG_T *s) +{ + int ret = 0; + ROT_CFG_T *p = param_ptr; + + ROTATE_TRACE("rot_k_io_cfg start \n"); + ROTATE_TRACE("w=%d, h=%d \n", p->img_size.w, p->img_size.h); + ROTATE_TRACE("format=%d, angle=%d \n", p->format, p->angle); + ROTATE_TRACE("s.y=%x, s.u=%x, s.v=%x \n", p->src_addr.y_addr, p->src_addr.u_addr, p->src_addr.v_addr); + ROTATE_TRACE("d.y=%x, d.u=%x, d.v=%x \n", p->dst_addr.y_addr, p->dst_addr.u_addr, p->dst_addr.v_addr); + + ret = rot_k_check_param(param_ptr); + + if (0 == ret) + ret = rot_k_set_y_param(param_ptr,s); + + return ret; +} diff --git a/drivers/media/sprd_rotation/rot_drv.h b/drivers/media/sprd_rotation/rot_drv.h new file mode 100644 index 00000000..5f4ac9a3 --- /dev/null +++ b/drivers/media/sprd_rotation/rot_drv.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _ROT_DRV_H_ +#define _ROT_DRV_H_ + +#include <linux/of.h> +#include <linux/of_device.h> + +#include "rot_reg.h" + +/*#define ROTATE_DEBUG*/ + +#ifdef ROTATE_DEBUG + #define ROTATE_TRACE printk +#else + #define ROTATE_TRACE pr_debug +#endif + + +typedef void (*rot_isr_func)(void *rot_k_private); + +typedef struct _rot_param_tag { + ROT_SIZE_T img_size; + ROT_DATA_FORMAT_E format; + ROT_ANGLE_E angle; + ROT_ADDR_T src_addr; + ROT_ADDR_T dst_addr; + uint32_t s_addr; + uint32_t d_addr; + ROT_PIXEL_FORMAT_E pixel_format; + ROT_UV_MODE_E uv_mode; + int is_end; + ROT_ENDIAN_E src_endian; + ROT_ENDIAN_E dst_endian; +} ROT_PARAM_CFG_T; + +struct rot_drv_private{ + ROT_PARAM_CFG_T cfg; + rot_isr_func user_isr_func; + spinlock_t rot_drv_lock; + void *rot_fd;/*rot file*/ +}; + +int rot_k_module_en(struct device_node *dn); +int rot_k_module_dis(struct device_node *dn); +int rot_k_isr_reg(rot_isr_func user_func,struct rot_drv_private *drv_private); +int rot_k_is_end(ROT_PARAM_CFG_T *s); +int rot_k_set_UV_param(ROT_PARAM_CFG_T *s); +void rot_k_register_cfg(ROT_PARAM_CFG_T *s); +void rot_k_close(void); +int rot_k_io_cfg(ROT_CFG_T * param_ptr, ROT_PARAM_CFG_T *s); +#endif diff --git a/drivers/media/sprd_rotation/rot_reg.h b/drivers/media/sprd_rotation/rot_reg.h new file mode 100644 index 00000000..33802d9e --- /dev/null +++ b/drivers/media/sprd_rotation/rot_reg.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef _REG_SCALE_TIGER_H_ +#define _REG_SCALE_TIGER_H_ + +#ifndef CONFIG_64BIT +#include <soc/sprd/globalregs.h> +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + +typedef enum { + ROT_ONE_BYTE = 0, + ROT_TWO_BYTES, + ROT_BYTE_MAX +} ROT_PIXEL_FORMAT_E; + +typedef enum { + ROT_NORMAL = 0, + ROT_UV422, + ROT_DATA_FORMAT_MAX +} ROT_UV_MODE_E; + +#define ROT_BASE DCAM_BASE +#define REG_ROTATION_CTRL (ROT_BASE + 0x0004UL) +#define REG_ROTATION_INT_STS (ROT_BASE + 0x003CUL) +#define REG_ROTATION_INT_MASK (ROT_BASE + 0x0040UL) +#define REG_ROTATION_INT_CLR (ROT_BASE + 0x0044UL) +#define REG_ROTATION_INT_RAW (ROT_BASE + 0x0048UL) +#define REG_ROTATION_ENDIAN_SEL (ROT_BASE + 0x006CUL) +#define REG_ROTATION_SRC_ADDR (ROT_BASE + 0x0080UL) +#define REG_ROTATION_DST_ADDR (ROT_BASE + 0x0084UL) +#define REG_ROTATION_PATH_CFG (ROT_BASE + 0x8000UL) +#define REG_ROTATION_ORIGWIDTH (ROT_BASE + 0x8004UL) +#define REG_ROTATION_OFFSET_START (ROT_BASE + 0x8008UL) +#define REG_ROTATION_IMG_SIZE (ROT_BASE + 0x800CUL) +#define REG_ROTATION_AHB_RESET (SPRD_MMAHB_BASE + 0x04UL) + +#define ROT_IRQ_BIT (1 << 15) +#define ROT_START_BIT (1 << 5) +#define ROT_AXI_RD_WORD_ENDIAN_BIT (1 << 19) +#define ROT_AXI_WR_WORD_ENDIAN_BIT (1 << 18) +#define ROT_RD_ENDIAN_MASK (3 << 16) +#define ROT_WR_ENDIAN_MASK (3 << 14) + +#define ROT_EB_BIT (1 << 0) +#define ROT_PIXEL_FORMAT_BIT (1 << 1) +#define ROT_MODE_MASK (3 << 2) +#define ROT_UV_MODE_BIT (1 << 4) + +#define ROT_AHB_RESET_BIT (1 << 10) + +#ifdef __cplusplus +} +#endif + +#endif |
