summaryrefslogtreecommitdiff
path: root/drivers/media/sprd_isp/isp1.0
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/media/sprd_isp/isp1.0
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/media/sprd_isp/isp1.0')
-rw-r--r--drivers/media/sprd_isp/isp1.0/Shark_reg_isp.h70
-rw-r--r--drivers/media/sprd_isp/isp1.0/Tiger_reg_isp.h91
-rw-r--r--drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.c327
-rw-r--r--drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.h26
-rw-r--r--drivers/media/sprd_isp/isp1.0/isp_drv_kernel.c1494
-rw-r--r--drivers/media/sprd_isp/isp1.0/isp_drv_null.c305
6 files changed, 2313 insertions, 0 deletions
diff --git a/drivers/media/sprd_isp/isp1.0/Shark_reg_isp.h b/drivers/media/sprd_isp/isp1.0/Shark_reg_isp.h
new file mode 100644
index 00000000..6b99f9ea
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/Shark_reg_isp.h
@@ -0,0 +1,70 @@
+/*
+ * 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 _TIGER_REG_ISP_H_
+#define _TIGER_REG_ISP_H_
+#ifndef CONFIG_64BIT
+#include <soc/sprd/globalregs.h>
+#else
+#include <soc/sprd/irqs.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+
+#define ISP_DCAM_BASE DCAM_BASE
+#define ISP_DCAM_INT_STS (ISP_DCAM_BASE + 0x003CUL)
+#define ISP_DCAM_INT_CLR (ISP_DCAM_BASE + 0x0044UL)
+
+#define ISP_BASE_ADDR ISP_BASE
+#define ISP_LNC_STATUS (ISP_BASE_ADDR+0x0200UL)
+#define ISP_LNC_LOAD (ISP_BASE_ADDR+0x0220UL)
+#define ISP_AXI_MASTER (ISP_BASE_ADDR+0x2000UL)
+#define ISP_INT_RAW (ISP_BASE_ADDR+0x2080UL)
+#define ISP_INT_STATUS (ISP_BASE_ADDR+0x2084UL)
+#define ISP_INT_EN (ISP_BASE_ADDR+0x2078UL)
+#define ISP_INT_CLEAR (ISP_BASE_ADDR+0x207cUL)
+#define ISP_REG_MAX_SIZE SPRD_ISP_SIZE
+#define ISP_AXI_MASTER_STOP (ISP_BASE_ADDR + 0X2054UL)
+
+#define ISP_AHB_BASE SPRD_MMAHB_BASE
+#define ISP_MODULE_EB (ISP_AHB_BASE + 0x0000UL)
+#define ISP_MODULE_RESET (ISP_AHB_BASE + 0x0004UL)
+#define ISP_CORE_CLK_EB (ISP_AHB_BASE + 0x0008UL)
+
+#define ISP_CLOCK_BASE SPRD_MMCKG_BASE
+#define ISP_CLOCK (ISP_CLOCK_BASE + 0X34)
+
+
+/*irq line number in system*/
+#define ISP_IRQ IRQ_ISP_INT
+
+#define ISP_EB_BIT BIT_2
+#define ISP_RST_LOG_BIT BIT_2
+#define ISP_RST_CFG_BIT BIT_3
+#define ISP_CORE_CLK_EB_BIT BIT_4
+#define ISP_AXI_MASTER_STOP_BIT BIT_0
+
+#define ISP_IRQ_HW_MASK_V0001 (0x1fffffff)
+#define ISP_IRQ_NUM_V0001 (29)
+#define ISP_TMP_BUF_SIZE_MAX_V0001 (32 * 1024)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_TIGER_REG_ISP_H_
diff --git a/drivers/media/sprd_isp/isp1.0/Tiger_reg_isp.h b/drivers/media/sprd_isp/isp1.0/Tiger_reg_isp.h
new file mode 100644
index 00000000..d68a8ff9
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/Tiger_reg_isp.h
@@ -0,0 +1,91 @@
+/*
+ * 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 _TIGER_REG_ISP_H_
+#define _TIGER_REG_ISP_H_
+#include <mach/globalregs.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define BIT_0 0x01
+#define BIT_1 0x02
+#define BIT_2 0x04
+#define BIT_3 0x08
+#define BIT_4 0x10
+#define BIT_5 0x20
+#define BIT_6 0x40
+#define BIT_7 0x80
+#define BIT_8 0x0100
+#define BIT_9 0x0200
+#define BIT_10 0x0400
+#define BIT_11 0x0800
+#define BIT_12 0x1000
+#define BIT_13 0x2000
+#define BIT_14 0x4000
+#define BIT_15 0x8000
+#define BIT_16 0x010000
+#define BIT_17 0x020000
+#define BIT_18 0x040000
+#define BIT_19 0x080000
+#define BIT_20 0x100000
+#define BIT_21 0x200000
+#define BIT_22 0x400000
+#define BIT_23 0x800000
+#define BIT_24 0x01000000
+#define BIT_25 0x02000000
+#define BIT_26 0x04000000
+#define BIT_27 0x08000000
+#define BIT_28 0x10000000
+#define BIT_29 0x20000000
+#define BIT_30 0x40000000
+#define BIT_31 0x80000000
+
+
+#define ISP_DCAM_BASE DCAM_BASE
+#define ISP_DCAM_INT_STS (ISP_DCAM_BASE + 0x0030UL)
+#define ISP_DCAM_INT_CLR (ISP_DCAM_BASE + 0x0038UL)
+
+#define ISP_BASE_ADDR ISP_BASE
+#define ISP_LNC_LOAD (ISP_BASE_ADDR+0x0220UL)
+#define ISP_AXI_MASTER (ISP_BASE_ADDR+0x2000UL)
+#define ISP_INT_RAW (ISP_BASE_ADDR+0x2080UL)
+#define ISP_INT_STATUS (ISP_BASE_ADDR+0x2084UL)
+#define ISP_INT_EN (ISP_BASE_ADDR+0x2078UL)
+#define ISP_INT_CLEAR (ISP_BASE_ADDR+0x207cUL)
+#define ISP_REG_MAX_SIZE SPRD_ISP_SIZE
+
+#define ISP_AHB_BASE SPRD_AHB_BASE
+#define ISP_AHB_CTL0 (ISP_AHB_BASE + 0x0200UL)
+#define ISP_MODULE_EB (ISP_AHB_CTL0 + 0x0000UL)
+#define ISP_MODULE_RESET (ISP_AHB_CTL0 + 0x0010UL)
+
+#define ISP_CORE_CLK_EB (ISP_AHB_BASE + 0x0208UL)
+
+/*irq line number in system*/
+#define ISP_IRQ IRQ_ISP_INT
+#define DCAM_IRQ IRQ_DCAM_INT
+
+#define ISP_EB_BIT BIT_12
+#define ISP_RST_BIT BIT_8
+#define ISP_CORE_CLK_EB_BIT BIT_7
+#define ISP_IRQ_HW_MASK_V0000 (0xfff)
+#define ISP_IRQ_NUM_V0000 (12)
+#define ISP_TMP_BUF_SIZE_MAX_V0000 (36 * 1024)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_TIGER_REG_ISP_H_ \ No newline at end of file
diff --git a/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.c b/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.c
new file mode 100644
index 00000000..ae0ad4f0
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.c
@@ -0,0 +1,327 @@
+#include <linux/compat.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <video/isp_drv_kernel.h>
+#include "compat_isp_drv_kernel.h"
+
+struct compat_isp_irq_param {
+ compat_uint_t isp_irq_val;
+ compat_uint_t dcam_irq_val;
+ compat_uint_t irq_val;
+ compat_int_t ret_val;
+};
+
+struct compat_isp_reg_bits {
+ compat_ulong_t reg_addr;
+ compat_ulong_t reg_value;
+} ;
+
+struct compat_isp_reg_param {
+ compat_ulong_t reg_param;
+ uint32_t counts;
+} ;
+
+
+#define COMPAT_ISP_IO_READ _IOR(ISP_IO_MAGIC, 1, struct compat_isp_reg_param)
+#define COMPAT_ISP_IO_WRITE _IOW(ISP_IO_MAGIC, 2, struct compat_isp_reg_param)
+#define COMPAT_ISP_IO_LNC_PARAM _IOW(ISP_IO_MAGIC, 8, struct compat_isp_reg_param)
+#define COMPAT_ISP_IO_LNC _IOW(ISP_IO_MAGIC, 9, struct compat_isp_reg_param)
+#define COMPAT_ISP_IO_ALLOC _IOW(ISP_IO_MAGIC, 10, struct compat_isp_reg_param)
+
+
+static int compat_get_rw_param(
+ struct compat_isp_reg_param __user *data32,
+ struct isp_reg_param __user *data)
+{
+ int err = 0;
+ compat_ulong_t addr;
+ uint32_t cnt;
+
+ err = get_user(addr, &data32->reg_param);
+ err |= put_user(addr, &data->reg_param);
+ err |= get_user(cnt, &data32->counts);
+ err |= put_user(cnt, &data->counts);
+
+ //printk("compat_get_rw_param, addr: 0x%x data32->reg_param: 0x%x data->reg_param: 0x%lx cnt: %d\n",
+ // addr, data32->reg_param, data->reg_param, cnt);
+
+ return err;
+}
+
+static int compat_get_rw_param_detail(struct isp_reg_param __user *data)
+{
+ struct compat_isp_reg_bits __user *data32;
+ struct isp_reg_bits __user *reg_data;
+ int err = 0;
+ int i = 0;
+ int cnt = data->counts;
+ compat_ulong_t addr;
+ compat_ulong_t val;
+ struct isp_reg_bits __user *data_tmp;
+
+ data32 = compat_ptr(data->reg_param);
+// printk("compat_get_rw_param_detail param: %p cnt %d\n", data32, cnt);
+ reg_data = (struct isp_reg_bits __user*)((unsigned long)data + sizeof(struct isp_reg_param));
+ data->reg_param = reg_data;
+ if (reg_data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+// printk("compat_get_rw_param_detail param: data %p \n", reg_data);
+ data_tmp = reg_data;
+ for (i=0 ; i< cnt; i++) {
+ err = get_user(addr, &data32->reg_addr);
+ err |= put_user(addr, &data_tmp->reg_addr);
+ err |= get_user(val, &data32->reg_value);
+ err |= put_user(val, &data_tmp->reg_value);
+ if (err) {
+ printk("compat_isp_k, read_param_detail failed cnt %d ret %d\n", cnt, err);
+ break;
+ }
+ data32++;
+ data_tmp++;
+ }
+ return err;
+}
+
+static int compat_put_read_param(
+ struct compat_isp_reg_param __user *data32,
+ struct isp_reg_param __user *data)
+
+{
+ int err = 0;
+ compat_ulong_t val;
+ uint32_t cnt;
+ int i = 0;
+ struct compat_isp_reg_bits __user *reg_data32;
+ struct isp_reg_bits __user *reg_data;
+
+ cnt = data->counts;
+ reg_data32 = (struct compat_isp_reg_bits __user *)data32->reg_param;
+ reg_data = (struct isp_reg_bits __user *)data->reg_param;
+ for (i=0 ; i<cnt; i++) {
+ err = get_user(val, &reg_data->reg_value);
+ err |= put_user(val, &reg_data32->reg_value);
+ if (err) {
+ printk("compat_isp_k, compat_put_read_param ret %d\n", err);
+ break;
+ }
+ reg_data32++;
+ reg_data++;
+ }
+
+ return err;
+}
+
+static int compat_get_alloc_param(
+ struct compat_isp_reg_param __user *data32,
+ struct isp_reg_param __user *data)
+{
+ int err = 0;
+ compat_ulong_t addr;
+ uint32_t cnt;
+ struct compat_isp_reg_bits __user *reg_data32;
+ struct isp_reg_bits __user *reg_data;
+
+ err = get_user(addr, &data32->reg_param);
+ err |= put_user(addr, &data->reg_param);
+ err |= get_user(cnt, &data32->counts);
+ err |= put_user(cnt, &data->counts);
+
+ return err;
+}
+
+static int compat_put_alloc(
+ struct compat_isp_reg_param __user *data32,
+ struct isp_reg_param __user *data)
+
+{
+ int err = 0;
+ compat_ulong_t addr;
+ uint32_t cnt;
+ struct compat_isp_reg_bits __user *reg_data32;
+ struct isp_reg_bits __user *reg_data;
+
+ err = get_user(addr, &data->reg_param);
+ err |= put_user(addr, &data32->reg_param);
+ err |= get_user(cnt, &data->counts);
+ err |= put_user(cnt, &data32->counts);
+
+ return err;
+}
+
+
+
+
+long compat_isp_kernel_ioctl( struct file *fl, unsigned int cmd, unsigned long param)
+{
+ long ret;
+ int err = 0;
+ void __user *up = compat_ptr(param);
+
+ if(ISP_IO_IRQ == cmd) {
+ ret = fl->f_op->unlocked_ioctl(fl, cmd, (unsigned long)up);
+ } else {
+ switch (cmd) {
+ case COMPAT_ISP_IO_READ:
+ {
+ struct compat_isp_reg_param __user *data32;
+ struct isp_reg_param __user *data;
+ uint32_t cnt;
+
+
+ data32 = compat_ptr(param);
+ err = get_user(cnt, &data32->counts);
+
+// printk("COMPAT_ISP_IO_WRITE param: %p \n", data32);
+ data = compat_alloc_user_space(sizeof(struct isp_reg_param)+cnt*sizeof(struct isp_reg_bits));
+ if (data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+// printk("@@1 %p", data);
+ err = compat_get_rw_param(data32, data);
+ if (err) {
+ return err;
+ }
+ err = compat_get_rw_param_detail(data);
+ if (err) {
+ printk("compat_isp_k error %d\n", err);
+ return err;
+ }
+ err = fl->f_op->unlocked_ioctl(fl, ISP_IO_READ, (unsigned long)data);
+ err = compat_put_read_param(data32, data);
+ ret = ret ? ret : err;
+ break;
+ }
+ case COMPAT_ISP_IO_WRITE:
+ {
+ struct compat_isp_reg_param __user *data32;
+ struct isp_reg_param __user *data;
+ uint32_t cnt;
+
+
+ data32 = compat_ptr(param);
+ err = get_user(cnt, &data32->counts);
+
+// printk("COMPAT_ISP_IO_WRITE param: %p \n", data32);
+ data = compat_alloc_user_space(sizeof(struct isp_reg_param)+cnt*sizeof(struct isp_reg_bits));
+ if (data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+// printk("@@1 %p", data);
+ err = compat_get_rw_param(data32, data);
+ if (err) {
+ return err;
+ }
+ err = compat_get_rw_param_detail(data);
+ if (err) {
+ printk("compat_isp_k error %d\n", err);
+ return err;
+ }
+ err = fl->f_op->unlocked_ioctl(fl, ISP_IO_WRITE, (unsigned long)data);
+ break;
+ }
+ case COMPAT_ISP_IO_LNC_PARAM:
+ {
+ struct compat_isp_reg_param __user *data32;
+ struct isp_reg_param __user *data;
+ char __user *lnc_data;
+
+
+ data32 = compat_ptr(param);
+ data = compat_alloc_user_space(sizeof(*data));
+ if (data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+ err = compat_get_rw_param(data32, data);
+ if (err) {
+ printk("compat_isp_k COMPAT_ISP_IO_LNC_PARAM error\n");
+ return err;
+ }
+ /*lnc_data = compat_alloc_user_space(sizeof(*lnc_data)*data->counts);
+ data->reg_param = (unsigned long)lnc_data;
+ ret = copy_from_user((void*)data->reg_param, (void*)data32->reg_param, data->counts);
+ if (ret) {
+ return ret;
+ }*/
+// printk("test 123\n");
+ ret = fl->f_op->unlocked_ioctl(fl, ISP_IO_LNC_PARAM, (unsigned long)data);
+// printk("test 123 end\n");
+ break;
+ }
+ case COMPAT_ISP_IO_LNC:
+ {
+ struct compat_isp_reg_param __user *data32;
+ struct isp_reg_param __user *data;
+ uint32_t cnt;
+
+
+ data32 = compat_ptr(param);
+ err = get_user(cnt, &data32->counts);
+
+// printk("COMPAT_ISP_IO_WRITE param: %p \n", data32);
+ data = compat_alloc_user_space(sizeof(struct isp_reg_param)+cnt*sizeof(struct isp_reg_bits));
+ if (data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+// printk("@@1 %p", data);
+ err = compat_get_rw_param(data32, data);
+ if (err) {
+ return err;
+ }
+ err = compat_get_rw_param_detail(data);
+ if (err) {
+ printk("compat_isp_k error %d\n", err);
+ return err;
+ }
+ // printk("test ISP_IO_LNC\n");
+ err = fl->f_op->unlocked_ioctl(fl, ISP_IO_LNC, (unsigned long)data);
+ // printk("test ISP_IO_LNC end\n");
+ break;
+ }
+ case COMPAT_ISP_IO_ALLOC:
+ {
+ struct compat_isp_reg_param __user *data32;
+ struct isp_reg_param __user *data;
+
+ data32 = compat_ptr(param);
+ data = compat_alloc_user_space(sizeof(*data));
+ if (data == NULL) {
+ printk("compat_isp_k failed to compat_alloc_user_space \n");
+ return -EFAULT;
+ }
+ err = compat_get_alloc_param(data32, data);
+ if (err) {
+ return err;
+ }
+ ret = fl->f_op->unlocked_ioctl(fl, ISP_IO_ALLOC, (unsigned long)data);
+ if (ret) {
+ printk("compat_isp_k,failed to ISP_IO_ALLOC %ld", ret);
+ goto exit;
+ }
+ err = compat_put_alloc(data32, data);
+ ret = err;
+ break;
+ }
+
+ case ISP_IO_RST:
+ case ISP_IO_SETCLK:
+ case ISP_IO_STOP:
+ case ISP_IO_INT:
+ case ISP_IO_DCAM_INT:
+ {
+ ret = fl->f_op->unlocked_ioctl(fl, cmd, (unsigned long)up);
+ break;
+ }
+ default:
+ printk("compat_isp_k, don't support cmd 0x%x", cmd);
+ break;
+ }
+ }
+exit:
+ return ret;
+}
diff --git a/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.h b/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.h
new file mode 100644
index 00000000..a24cce52
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/compat_isp_drv_kernel.h
@@ -0,0 +1,26 @@
+/*
+ * 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 _COMPAT_ISP_DRV_KERNEL_H_
+#define _COMPAT_ISP_DRV_KERNEL_H_
+
+#if IS_ENABLED(CONFIG_COMPAT)
+
+long compat_isp_kernel_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+
+#else
+
+#define compat_isp_kernel_ioctl NULL
+
+#endif /* CONFIG_COMPAT */
+
+#endif
diff --git a/drivers/media/sprd_isp/isp1.0/isp_drv_kernel.c b/drivers/media/sprd_isp/isp1.0/isp_drv_kernel.c
new file mode 100644
index 00000000..9a6acbef
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/isp_drv_kernel.c
@@ -0,0 +1,1494 @@
+/*
+ * 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/slab.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <video/isp_drv_kernel.h>
+#include <soc/sprd/sci.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
+#ifndef CONFIG_64BIT
+#include <soc/sprd/hardware.h>
+#endif
+#include "compat_isp_drv_kernel.h"
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/vmalloc.h>
+#include <linux/kthread.h>
+
+#include "Shark_reg_isp.h"
+#include "parse_hwinfo.h"
+
+
+#define DEBUG_ISP_DRV
+#ifdef DEBUG_ISP_DRV
+#define ISP_PRINT printk
+#else
+#define ISP_PRINT(...)
+#endif
+
+#define ISP_QUEUE_LENGTH 16
+#define SA_SHIRQ IRQF_SHARED
+static uint32_t g_isp_irq = 0x12345678;/*for share irq handler function*/
+//static uint32_t g_dcam_irq = 0x12345678;/*for share irq handler function*/
+
+#define ISP_MINOR MISC_DYNAMIC_MINOR/*isp minor number*/
+#define init_MUTEX(sem) sema_init(sem, 1)
+#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
+#define IO_PTR volatile void __iomem *
+#define ISP_READL(a) __raw_readl((IO_PTR)a)
+#define ISP_WRITEL(a,v) __raw_writel(v,(IO_PTR)a)
+#define ISP_OWR(a,v) __raw_writel((__raw_readl((IO_PTR)a) | v), (IO_PTR)a)
+#define ISP_AWR(a,v) __raw_writel((__raw_readl((IO_PTR)a) & v), (IO_PTR)a)
+#define ISP_NAWR(a,v) __raw_writel((__raw_readl((IO_PTR)a) & ~v), (IO_PTR)a)
+#define ISP_REG_RD(a) ISP_READL(((IO_PTR)a))
+#define DEBUG_STR "Error L %d, %s \n"
+#define DEBUG_ARGS __LINE__,__FUNCTION__
+#define ISP_LOWEST_ADDR 0x800
+#define ISP_ADDR_INVALID(addr) ((unsigned long)(addr) < (unsigned long)ISP_LOWEST_ADDR)
+#define ISP_CHECK_ZERO(a) \
+ do { \
+ if (ISP_ADDR_INVALID(a)) { \
+ printk("isp_k, zero pointer \n"); \
+ printk(DEBUG_STR, DEBUG_ARGS); \
+ return -EFAULT; \
+ } \
+ } while(0)
+
+#define ISP_CHECK_ZERO_VOID(a) \
+ do { \
+ if (ISP_ADDR_INVALID(a)) { \
+ printk("isp_k, zero pointer \n"); \
+ printk(DEBUG_STR, DEBUG_ARGS); \
+ return; \
+ } \
+ } while(0)
+
+#define ISP_DCAM_IRQ_MASK 0x03
+#define ISP_DCAM_IRQ_NUM 0x02
+#define ISP_BUF_MAX_SIZE ISP_TMP_BUF_SIZE_MAX_V0001
+#define ISP_IRQ_NUM ISP_IRQ_NUM_V0001
+#define ISP_IRQ_HW_MASK ISP_IRQ_HW_MASK_V0001
+#define ISP_TIME_OUT_MAX (500)
+
+struct isp_node {
+ uint32_t isp_irq_val;
+ uint32_t dcam_irq_val;
+ uint64_t system_time;
+};
+
+struct isp_queue {
+ struct isp_node node[ISP_QUEUE_LENGTH];
+ struct isp_node *write;
+ struct isp_node *read;
+};
+
+struct isp_lnc_load {
+ uint8_t load_lnc_flag;
+ uint8_t cap_eof_flag;
+ uint32_t param_counts;
+ unsigned long load_buf;
+ struct semaphore load_done_sem;
+};
+struct isp_device_t
+{
+ unsigned long reg_base_addr;/*the pointer of isp register context*/
+ uint32_t size;/* struct size*/
+ unsigned long buf_addr;
+ uint32_t buf_len;
+ struct isp_queue queue;
+ struct semaphore sem_isr;/*for interrupts*/
+ struct semaphore sem_isp;/*for the isp device, protect the isp hardware; protect only one caller use the oi*/
+ /*controll/read/write functions*/
+ struct clk* s_isp_clk_mm_i;
+ struct clk *s_isp_clk;
+ struct semaphore kernel_sem;
+ struct task_struct* kernel_thread;
+ struct isp_lnc_load lnc_load;
+ uint32_t is_kernel_thread_stop;
+};
+enum dcam_irq_id {
+ DCAM_SN_SOF = 0,
+ DCAM_SN_EOF,
+ DCAM_CAP_SOF,
+ DCAM_CAP_EOF,
+ DCAM_PATH0_DONE,
+ DCAM_PATH0_OV,
+ DCAM_PATH1_DONE,
+ DCAM_PATH1_OV,
+ DCAM_PATH2_DONE,
+ DCAM_PATH2_OV,
+ DCAM_SN_LINE_ERR,
+ DCAM_SN_FRAME_ERR,
+ DCAM_JPEG_BUF_OV,
+ DCAM_ISP_OV,
+ DCAM_MIPI_OV,
+ DCAM_ROT_DONE,
+ DCAM_PATH1_SLICE_DONE,
+ DCAM_PATH2_SLICE_DONE,
+ DCAM_RAW_SLICE_DONE,
+ DCAM_PATH1_SOF,
+ DCAM_PATH2_SOF,
+ DCAM_IRQ_NUMBER
+};
+struct dcam_frame {
+ uint32_t type;
+ uint32_t lock;
+ uint32_t flags;
+ uint32_t fid;
+ uint32_t width;
+ uint32_t height;
+ uint32_t yaddr;
+ uint32_t uaddr;
+ uint32_t vaddr;
+ struct dcam_frame *prev;
+ struct dcam_frame *next;
+};
+typedef int (*dcam_isr_func)(struct dcam_frame* frame, void* u_data);
+extern int32_t dcam_reg_isr(enum dcam_irq_id id, dcam_isr_func user_func, void* user_data);
+
+static atomic_t s_isp_users = ATOMIC_INIT(0);
+static struct mutex s_isp_lock; /*for the isp driver, protect the isp module; protect only one user open this module*/
+static struct proc_dir_entry* isp_proc_file;
+static struct isp_device_t *g_isp_dev_ptr = NULL;
+
+uint32_t s_dcam_int_eb = 0x00;
+unsigned long s_isp_alloc_addr = 0x00;
+uint32_t s_isp_alloc_order = 0x00;
+uint32_t s_isp_alloc_len = 0x00;
+
+static DEFINE_SPINLOCK(isp_spin_lock);
+static int32_t _isp_set_clk(enum isp_clk_sel clk_sel);
+static int32_t _isp_module_eb(void);
+static int32_t _isp_module_dis(void);
+static int _isp_registerirq(void);
+static void _isp_unregisterirq(void);
+static irqreturn_t _isp_irq_root(int irq, void *dev_id);
+void _dcam_isp_root(void);
+static int _isp_queue_init(struct isp_queue *queue);
+static int _isp_queue_write(struct isp_queue *queue, struct isp_node *node);
+static int _isp_queue_read(struct isp_queue *queue, struct isp_node *node);
+static inline void _isp_regread(char *dst, char *src, size_t n);
+static inline void _isp_regwrite(char *dst, char *src, size_t n);
+static void _read_reg(struct isp_reg_bits *reg_bits_ptr, uint32_t counts);
+static void _write_reg(struct isp_reg_bits *reg_bits_ptr, uint32_t counts);
+
+/**file operation functions declare**/
+static int32_t _isp_kernel_open(struct inode *node, struct file *filp);
+static int32_t _isp_kernel_release(struct inode *node, struct file *filp);
+static long _isp_kernel_ioctl( struct file *fl, unsigned int cmd, unsigned long param);
+/**driver' functions declare**/
+static int32_t _isp_probe(struct platform_device *pdev);
+static int32_t _isp_remove(struct platform_device *dev);
+/**module' functions declare**/
+static int32_t __init isp_kernel_init(void);
+static void isp_kernel_exit(void);
+static int32_t _isp_lnc_param_load_ex(struct isp_reg_bits *reg_bits_ptr, uint32_t counts);
+static int _isp_stop_kernel_thread(void* param);
+
+static struct file_operations isp_fops = {
+ .owner = THIS_MODULE,
+ .open = _isp_kernel_open,
+ .unlocked_ioctl = _isp_kernel_ioctl,
+ .compat_ioctl = compat_isp_kernel_ioctl,
+ .release = _isp_kernel_release,
+};
+
+static struct miscdevice isp_dev = {
+ .minor = ISP_MINOR,
+ .name = "sprd_isp",
+ .fops = &isp_fops,
+};
+
+static const struct of_device_id of_match_table_isp[] = {
+ { .compatible = "sprd,sprd_isp", },
+ { },
+};
+
+static struct platform_driver isp_driver = {
+ .probe = _isp_probe,
+ .remove = _isp_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sprd_isp",
+ .of_match_table = of_match_ptr(of_match_table_isp),
+ },
+};
+
+static int32_t _isp_get_systemtime(struct timeval *tv)
+{
+ struct timespec ts;
+
+ ktime_get_ts(&ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ return 0;
+}
+
+static int32_t _isp_module_eb(void)
+{
+ int32_t ret = 0;
+
+ if (0x01 == atomic_inc_return(&s_isp_users)) {
+
+ ret = clk_mm_i_eb(isp_dev.this_device->of_node,1);
+ ret = _isp_set_clk(ISP_CLK_312M);
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: set clock error\n");
+ ret = -EIO;
+ }
+ }
+
+ ISP_PRINT("_isp_module_eb: end\n");
+
+ return ret;
+}
+
+static int32_t _isp_module_dis(void)
+{
+ int32_t ret = 0;
+
+ if (0x00 == atomic_dec_return(&s_isp_users)) {
+
+ ret = _isp_set_clk(ISP_CLK_NONE);
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: close clock error\n");
+ ret = -EFAULT;
+ return ret;
+ }
+ ret = clk_mm_i_eb(isp_dev.this_device->of_node,0);
+ }
+ return ret;
+}
+
+static int32_t _isp_module_rst(void)
+{
+ int32_t ret = 0;
+ uint32_t reg_value=0x00;
+ int32_t time_out_cnt = 0;
+
+ if (0x00 != atomic_read(&s_isp_users)) {
+
+ ISP_OWR(ISP_AXI_MASTER_STOP, BIT_0);
+
+ reg_value=ISP_READL(ISP_AXI_MASTER);
+ while((0x00==(reg_value&0x08)) && (time_out_cnt < (ISP_TIME_OUT_MAX * 2)))
+ {
+ time_out_cnt++;
+ udelay(50);
+ reg_value=ISP_READL(ISP_AXI_MASTER);
+ }
+ if (time_out_cnt >= ISP_TIME_OUT_MAX) {
+ ret = -1;
+ ISP_PRINT("_isp_module_rst: time out\n");
+ }
+
+ ISP_WRITEL(ISP_INT_CLEAR, ISP_IRQ_HW_MASK);
+
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_LOG_BIT);
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_CFG_BIT);
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_LOG_BIT);
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_CFG_BIT);
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_LOG_BIT);
+ sci_glb_set(ISP_MODULE_RESET, ISP_RST_CFG_BIT);
+
+ sci_glb_clr(ISP_MODULE_RESET, ISP_RST_CFG_BIT);
+ sci_glb_clr(ISP_MODULE_RESET, ISP_RST_LOG_BIT);
+ }
+
+ ISP_PRINT("_isp_module_rst: exit\n");
+
+ return 0;
+}
+
+void* _isp_cap_eof(struct dcam_frame* frame, void* u_data)
+{
+ struct isp_device_t * p_isp = (struct isp_device_t *)u_data;
+ if (p_isp) {
+ p_isp->lnc_load.cap_eof_flag = 1;
+ if (p_isp->lnc_load.load_lnc_flag) {
+ up(&p_isp->kernel_sem);
+ p_isp->lnc_load.load_lnc_flag = 0;
+ } else {
+ }
+ }
+}
+int _isp_kernel_proc(void *arg)
+{
+ struct isp_device_t *dev = (struct isp_device_t*)arg;
+ int32_t time_out_cnt = 0;
+ uint32_t reg_value=0x00;
+ int ret = 0;
+ struct isp_reg_bits *reg_bits_ptr;
+ uint32_t counts;
+ while(1) {
+ if (0 == down_interruptible(&dev->kernel_sem)) {
+ if (dev->is_kernel_thread_stop) {
+ printk("isp_k: _isp_kernel_proc stop \n");
+ break;
+ }
+ reg_bits_ptr = (struct isp_reg_bits*) g_isp_dev_ptr->lnc_load.load_buf;
+ counts = g_isp_dev_ptr->lnc_load.param_counts;
+ ret = _isp_lnc_param_load_ex(reg_bits_ptr, counts);
+ memset((void *)g_isp_dev_ptr->lnc_load.load_buf, 0x00, ISP_BUF_MAX_SIZE);
+ }
+ }
+ dev->is_kernel_thread_stop = 0;
+ return 0;
+}
+int _isp_kernel_thread(void* param)
+{
+ struct isp_device_t *dev = (struct isp_device_t*)param;
+ if (dev == NULL) {
+ printk("isp_k: _isp_kernel_thread, dev is NULL \n");
+ return -1;
+ }
+ dev->lnc_load.load_lnc_flag = 0;
+ dev->lnc_load.cap_eof_flag = 0;
+ dev->is_kernel_thread_stop = 0;
+ sema_init(&dev->kernel_sem, 0);
+ sema_init(&dev->lnc_load.load_done_sem, 0);
+ dev->kernel_thread = kthread_run(_isp_kernel_proc, param, "isp_kernel_proc_thread");
+ if (IS_ERR(dev->kernel_thread)) {
+ printk("isp_k: _isp_kernel_thread error!\n");
+ return -1;
+ }
+ return 0;
+}
+static int _isp_stop_kernel_thread(void* param)
+{
+ struct isp_device_t *dev = (struct isp_device_t*)param;
+ int cnt = 0;
+ if (dev == NULL) {
+ printk("SPRD_IMG: sprd_img_opt_flash, dev is NULL \n");
+ return -1;
+ }
+ if (dev->kernel_thread) {
+ dev->is_kernel_thread_stop = 1;
+ up(&dev->kernel_sem);
+ if (0 != dev->is_kernel_thread_stop) {
+ while (cnt < 500) {
+ cnt++;
+ if (0 == dev->is_kernel_thread_stop)
+ break;
+ msleep(1);
+ }
+ }
+ dev->kernel_thread = NULL;
+ }
+ return 0;
+}
+static int32_t _isp_lnc_param_load_ex(struct isp_reg_bits *reg_bits_ptr, uint32_t counts)
+{
+ int32_t ret = 0;
+ int32_t time_out_cnt = 0;
+ volatile uint32_t reg_value=0x00;
+
+ if((0x00!=s_isp_alloc_addr)
+ &&(0x00!=s_isp_alloc_len)) {
+
+ void *ptr = (void*)s_isp_alloc_addr;
+ uint32_t len=s_isp_alloc_len;
+
+ #ifndef CONFIG_64BIT
+ dmac_flush_range(ptr, ptr + len);
+ outer_flush_range(__pa(ptr), __pa(ptr) + len);
+ #endif
+
+ reg_bits_ptr->reg_value=(uint32_t)__pa(reg_bits_ptr->reg_value);
+//#if defined(CONFIG_MACH_CORE3)
+
+
+ reg_value=ISP_READL(ISP_LNC_STATUS);
+ while((0x00==(reg_value&ISP_LNC_STATUS_OK)) && (time_out_cnt < (ISP_TIME_OUT_MAX*1000))) {
+ udelay(1);
+ reg_value=ISP_READL(ISP_LNC_STATUS);
+ time_out_cnt++;
+ }
+ if (time_out_cnt >= (ISP_TIME_OUT_MAX*1000)) {
+ ret = -1;
+ ISP_PRINT("isp_k: isp lnc status time out\n");
+ }
+ ISP_OWR(ISP_INT_EN, ISP_INT_LENS_LOAD);
+ _write_reg(reg_bits_ptr, counts);
+ }else {
+ ISP_PRINT("isp_k: isp load lnc param error\n");
+ }
+ return ret;
+}
+static int32_t _isp_lnc_param_load(struct isp_reg_bits *reg_bits_ptr, uint32_t counts)
+{
+ int32_t ret = 0;
+ int32_t time_out_cnt = 0;
+ uint32_t reg_value=0x00;
+ printk("isp_k: _isp_lnc_param_load \n");
+ if((0x00!=s_isp_alloc_addr)
+ &&(0x00!=s_isp_alloc_len)) {
+ void *ptr = (void*)s_isp_alloc_addr;
+ uint32_t len=s_isp_alloc_len;
+ #ifndef CONFIG_64BIT
+ dmac_flush_range(ptr, ptr + len);
+ outer_flush_range(__pa(ptr), __pa(ptr) + len);
+ #endif
+ reg_bits_ptr->reg_value=(uint32_t)__pa(reg_bits_ptr->reg_value);
+ {
+ unsigned long flags;
+ reg_value=ISP_READL(ISP_LNC_STATUS);
+ while((0x00==(reg_value&ISP_LNC_STATUS_OK)) && (time_out_cnt < (ISP_TIME_OUT_MAX*1000))) {
+ udelay(1);
+ reg_value=ISP_READL(ISP_LNC_STATUS);
+ time_out_cnt++;
+ }
+ if (time_out_cnt >= (ISP_TIME_OUT_MAX*1000)) {
+ ret = -1;
+ ISP_PRINT("isp_k: isp lnc status time out\n");
+ }
+ _write_reg(reg_bits_ptr, counts);
+ printk("isp_k: load, 0x%x: 0x%x, 0x%x, counts %d \n", reg_bits_ptr, reg_bits_ptr->reg_addr, reg_bits_ptr->reg_value, counts);
+ }
+
+ time_out_cnt = 0;
+ reg_value=ISP_READL(ISP_INT_RAW);
+
+ while ((0x00 == (reg_value&ISP_INT_LENS_LOAD)) && (time_out_cnt < ISP_TIME_OUT_MAX)) {
+ udelay(1);
+ reg_value=ISP_READL(ISP_INT_RAW);
+ time_out_cnt++;
+ }
+ if (time_out_cnt >= ISP_TIME_OUT_MAX) {
+ ret = -1;
+ ISP_PRINT("isp_k: isp load lnc param time out\n");
+ }
+ ISP_OWR(ISP_INT_CLEAR, ISP_INT_LENS_LOAD);
+ }else {
+ ISP_PRINT("isp_k: isp load lnc param error\n");
+ }
+
+ return ret;
+}
+
+static int32_t _isp_lnc_param_set(uint32_t* addr, uint32_t len)
+{
+ int32_t ret = 0;
+
+ if((0x00!=s_isp_alloc_addr)
+ &&(0x00!=addr)) {
+ memcpy((void*)s_isp_alloc_addr, (void*)addr, len);
+ }
+
+ return ret;
+}
+
+static int32_t _isp_free(void)
+{
+ int32_t ret = 0;
+
+ if((0x00!=s_isp_alloc_addr)
+ &&(0x00!=s_isp_alloc_order)) {
+ free_pages(s_isp_alloc_addr, s_isp_alloc_order);
+ s_isp_alloc_order = 0x00;
+ s_isp_alloc_addr = 0x00;
+ s_isp_alloc_len=0x00;
+ }
+
+ return ret;
+}
+
+static int32_t _isp_alloc(unsigned long* addr, uint32_t len)
+{
+ int32_t ret = 0x00;
+ unsigned long buf=0x00;
+ void *ptr = 0x00;
+
+ if((0x00!=s_isp_alloc_addr)
+ &&(len<=s_isp_alloc_len)) {
+ *addr = s_isp_alloc_addr;
+ } else {
+ _isp_free();
+ }
+
+ if(0x00==s_isp_alloc_addr) {
+ s_isp_alloc_len=len;
+ s_isp_alloc_order = get_order(len);
+ s_isp_alloc_addr = __get_free_pages(GFP_KERNEL | __GFP_COMP, s_isp_alloc_order);
+ if (NULL == (void*)s_isp_alloc_addr) {
+ ISP_PRINT("ISP_RAW:_isp_alloc order:0x%x, addr:0x%lx, len:0x%x error\n", s_isp_alloc_order, s_isp_alloc_addr, s_isp_alloc_len);
+ return 1;
+ }
+ ptr = (void*)s_isp_alloc_addr;
+ *addr = s_isp_alloc_addr;
+ buf = virt_to_phys((volatile void *)s_isp_alloc_addr);
+
+ #ifndef CONFIG_64BIT
+ dmac_flush_range(ptr, ptr + len);
+ outer_flush_range(__pa(ptr), __pa(ptr) + len);
+ #endif
+ }
+
+ return ret;
+}
+
+static int32_t _isp_set_clk(enum isp_clk_sel clk_sel)
+{
+ struct clk *clk_parent;
+ char *parent = "clk_256m";
+ int32_t rtn = 0;
+
+ ISP_CHECK_ZERO(g_isp_dev_ptr);
+
+#ifdef CONFIG_SC_FPGA
+ return 0;
+#endif
+
+ switch (clk_sel) {
+ case ISP_CLK_312M:
+ parent = "clk_312m";
+ break;
+ case ISP_CLK_256M:
+ parent = "clk_256m";
+ break;
+ case ISP_CLK_128M:
+ parent = "clk_128m";
+ break;
+ case ISP_CLK_48M:
+ parent = "clk_48m";
+ break;
+ case ISP_CLK_76M8:
+ parent = "clk_76p8m";
+ break;
+
+ case ISP_CLK_NONE:
+ ISP_PRINT("isp_k: ISP close CLK %d \n", (int)clk_get_rate(g_isp_dev_ptr->s_isp_clk));
+ if (g_isp_dev_ptr->s_isp_clk) {
+ clk_disable(g_isp_dev_ptr->s_isp_clk);
+ clk_put(g_isp_dev_ptr->s_isp_clk);
+ g_isp_dev_ptr->s_isp_clk = NULL;
+ }
+ return 0;
+ default:
+ parent = "clk_128m";
+ break;
+ }
+
+ if (NULL == g_isp_dev_ptr->s_isp_clk) {
+ g_isp_dev_ptr->s_isp_clk = parse_clk(isp_dev.this_device->of_node, "clk_isp");
+ if (IS_ERR(g_isp_dev_ptr->s_isp_clk)) {
+ ISP_PRINT("isp_k: parse_clk fail, %p \n", (int)g_isp_dev_ptr->s_isp_clk);
+ return -1;
+ } else {
+ ISP_PRINT("isp_k: get clk_parent ok \n");
+ }
+ } else {
+ clk_disable(g_isp_dev_ptr->s_isp_clk);
+ }
+
+ clk_parent = clk_get(NULL, parent);
+ if (IS_ERR(clk_parent)) {
+ ISP_PRINT("isp_k: dcam_set_clk fail, %p \n", clk_parent);
+ return -1;
+ } else {
+ ISP_PRINT("isp_k: get clk_parent ok \n");
+ }
+
+ rtn = clk_set_parent(g_isp_dev_ptr->s_isp_clk, clk_parent);
+ if(rtn){
+ ISP_PRINT("isp_k: clk_set_parent fail, %d \n", rtn);
+ }
+
+ rtn = clk_enable(g_isp_dev_ptr->s_isp_clk);
+ if (rtn) {
+ ISP_PRINT("isp_k: enable isp clk error.\n");
+ return -1;
+ }
+
+ return rtn;
+}
+
+static int _isp_queue_init(struct isp_queue *queue)
+{
+ if (NULL == queue)
+ return -EINVAL;
+
+ memset(queue, 0x00, sizeof(*queue));
+ queue->write = &queue->node[0];
+ queue->read = &queue->node[0];
+
+ return 0;
+}
+
+static int _isp_queue_write(struct isp_queue *queue, struct isp_node *node)
+{
+ struct isp_node *ori_node;
+
+ if (NULL == queue || NULL == node)
+ return -EINVAL;
+
+ ori_node = queue->write;
+
+ //ISP_PRINT("_isp_queue_write called!\n");
+ *queue->write++ = *node;
+ if (queue->write > &queue->node[ISP_QUEUE_LENGTH-1]) {
+ queue->write = &queue->node[0];
+ }
+
+ if (queue->write == queue->read) {
+ queue->write = ori_node;
+ }
+
+ //ISP_PRINT("_isp_queue_write finished!\n");
+ return 0;
+}
+
+static int _isp_queue_read(struct isp_queue *queue, struct isp_node *node)
+{
+ int ret = 0;
+
+ if (NULL == queue || NULL == node)
+ return -EINVAL;
+ //ISP_PRINT("_isp_queue_read called!\n");
+ if (queue->read != queue->write) {
+ *node = *queue->read++;
+ if (queue->read > &queue->node[ISP_QUEUE_LENGTH-1]) {
+ queue->read = &queue->node[0];
+ }
+ }
+ //ISP_PRINT("_isp_queue_read finished!\n");
+ return ret;
+}
+
+static inline void _isp_regread(char *dst, char *src, size_t n)
+{
+ char tmp = 0;
+ uint32_t tmp2 = 0;
+ char *char_src = 0,*d = 0;
+ uint32_t *d2 = (uint32_t*) dst;
+ uint32_t *int_src = (uint32_t*) src;
+ uint32_t counts = (n>>2)<<2;
+ uint32_t res_counts = n -counts;
+ counts = counts>>2;
+
+ while (counts--) {
+ tmp2 = ISP_READL(int_src);
+ *d2++ = tmp2;
+ int_src++;
+ }
+
+ if(res_counts) {
+ d = (char*) d2;
+ char_src = (char*) int_src;
+ while(res_counts--) {
+ tmp = __raw_readb(char_src);
+ *d = tmp;
+ char_src++;
+ }
+ }
+}
+
+static inline void _isp_regwrite(char *dst, char *src, size_t n)
+{
+ uint32_t tmp2 = 0;
+ char *char_src = 0, *d = 0;
+ uint32_t *int_src = 0, *d2 = 0;
+ uint32_t counts = 0, res_counts = 0;
+
+ int_src = (uint32_t*) src;
+ d2 = (uint32_t*) dst;
+ counts = (n>>2)<<2;
+ res_counts = n - counts;
+ counts = counts>>2;
+
+ while (counts--) {
+ tmp2 = *int_src++;
+ ISP_WRITEL(d2, tmp2);
+ d2++;
+ }
+
+ if(res_counts) {
+ d = (char*) d2;
+ char_src = (char*) int_src;
+
+ while(res_counts--) {
+ tmp2 = *char_src++;
+ __raw_writeb(tmp2, d);
+ d++;
+ }
+ }
+
+}
+static int32_t _isp_get_ctlr(void *param)
+{
+ struct isp_device_t *dev_ptr = (struct isp_device_t *) param;
+
+ down(&dev_ptr->sem_isp);
+
+ return 0;
+}
+static int32_t _isp_put_ctlr(void *param)
+{
+ struct isp_device_t *dev_ptr = (struct isp_device_t *) param;
+
+ up(&dev_ptr->sem_isp);
+
+ return 0;
+}
+
+static int _isp_en_irq(unsigned long int_num)
+{
+ uint32_t ret = 0;
+
+ ISP_WRITEL(ISP_INT_CLEAR, ISP_IRQ_HW_MASK);
+ ISP_WRITEL(ISP_INT_EN, int_num);
+
+ return ret;
+}
+
+static int _isp_registerirq(void)
+{
+ uint32_t ret = 0;
+
+ ret = request_irq(ISP_IRQ, _isp_irq_root, IRQF_SHARED, "ISP", &g_isp_irq);
+
+ return ret;
+}
+static void _isp_unregisterirq(void)
+{
+ free_irq (ISP_IRQ, &g_isp_irq);
+}
+
+static int _isp_cfg_dcam_int(uint32_t param)
+{
+ uint32_t ret = 0;
+
+ s_dcam_int_eb = param;
+
+ return ret;
+}
+
+static void _read_reg(struct isp_reg_bits *reg_bits_ptr, uint32_t counts)
+{
+ uint32_t i = 0;
+ unsigned long reg_val = 0;
+ unsigned long reg_addr = 0;
+
+ for (i = 0; i<counts; ++i) {
+ //reg_addr = reg_bits_ptr[i].reg_addr;
+ reg_addr = ISP_BASE_ADDR + reg_bits_ptr[i].reg_addr;
+ reg_val = ISP_READL(reg_addr);
+ reg_bits_ptr[i].reg_value = reg_val;
+ }
+
+}
+
+static void _write_reg(struct isp_reg_bits *reg_bits_ptr, uint32_t counts)
+{
+ uint32_t i = 0;
+ unsigned long reg_val = 0;
+ unsigned long reg_addr = 0;
+
+ for (i = 0; i<counts; ++i) {
+ reg_addr = reg_bits_ptr[i].reg_addr+ISP_BASE_ADDR;
+ reg_val = reg_bits_ptr[i].reg_value;
+ ISP_WRITEL(reg_addr, reg_val);
+ }
+}
+
+/**********************************************************
+*open the device
+*
+***********************************************************/
+static int32_t _isp_kernel_open (struct inode *node, struct file *pf)
+{
+ int32_t ret = 0;
+ ISP_PRINT ("isp_k: open start \n");
+
+ ISP_CHECK_ZERO(g_isp_dev_ptr);
+
+ ret = _isp_get_ctlr(g_isp_dev_ptr);
+ if (unlikely(ret)) {
+ ISP_PRINT ("isp_k: get control error \n");
+ ret = -EFAULT;
+ return ret;
+ }
+
+ g_isp_dev_ptr->reg_base_addr = (unsigned long)ISP_BASE_ADDR;
+ g_isp_dev_ptr->size = ISP_REG_MAX_SIZE;
+
+ ret = _isp_queue_init(&(g_isp_dev_ptr->queue));
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: queue init error\n");
+ ret = -EIO;
+ goto ISP_K_OPEN_ERROR_EXIT;
+ }
+
+ ret = _isp_module_eb();
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: enable isp module error\n");
+ ret = -EIO;
+ goto ISP_K_OPEN_ERROR_EXIT;
+ }
+
+ ret = _isp_module_rst();
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: reset isp module error \n");
+ ret = -EIO;
+ _isp_module_dis();
+ goto ISP_K_OPEN_ERROR_EXIT;
+ }
+
+ dcam_reg_isr(DCAM_CAP_EOF, _isp_cap_eof, g_isp_dev_ptr);
+ ret = _isp_kernel_thread(g_isp_dev_ptr);
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: create isp_kernel_thread fail \n");
+ ret = -EIO;
+ _isp_module_dis();
+ goto ISP_K_OPEN_ERROR_EXIT;
+ }
+
+ ret = _isp_registerirq();
+ if (unlikely(0 != ret)) {
+ ISP_PRINT("isp_k: reg irq fail \n");
+ ret = -EIO;
+ _isp_stop_kernel_thread(g_isp_dev_ptr);
+ _isp_module_dis();
+ goto ISP_K_OPEN_ERROR_EXIT;
+ }
+
+ ISP_PRINT ("isp_k: open end \n");
+ return ret;
+
+ISP_K_OPEN_ERROR_EXIT:
+ ret = _isp_put_ctlr(g_isp_dev_ptr);
+ if (unlikely(ret)) {
+ ISP_PRINT ("isp_k: get control error \n");
+ ret = -EFAULT;
+ }
+ ISP_PRINT ("isp_k: open error \n");
+ return -EIO;
+}
+
+static irqreturn_t _isp_irq_root(int irq, void *dev_id)
+{
+ int32_t ret = 0;
+ uint32_t status = 0;
+ uint32_t irq_line = 0;
+ uint32_t irq_status = 0;
+ unsigned long flag = 0;
+ int32_t i = 0;
+ struct isp_node node = { 0 };
+ struct timeval system_time;
+
+ status = ISP_REG_RD(ISP_INT_STATUS);
+ irq_line = status&ISP_IRQ_HW_MASK;
+ //ISP_PRINT("ISP_RAW:isp_k: isp irq: 0x%x\n", irq_line);
+ if ( 0 == irq_line ) {
+ return IRQ_NONE;
+ }
+
+ spin_lock_irqsave(&isp_spin_lock,flag);
+ if ((ISP_INT_LENS_LOAD & irq_line) == ISP_INT_LENS_LOAD) {
+ irq_line &= ~ISP_INT_LENS_LOAD;
+ ISP_OWR(ISP_INT_CLEAR, ISP_INT_LENS_LOAD);
+ up(&g_isp_dev_ptr->lnc_load.load_done_sem);
+ if (!irq_line) {
+ spin_unlock_irqrestore(&isp_spin_lock, flag);
+ return IRQ_HANDLED;
+ }
+ }
+ for (i = ISP_IRQ_NUM- 1; i >= 0; i--) {
+ if (irq_line & (1 << (uint32_t)i)) {
+ irq_status |= 1 << (uint32_t)i;
+ }
+ irq_line &= ~(uint32_t)(1 << (uint32_t)i); //clear the interrupt flag
+ if(!irq_line) //no interrupt source left
+ break;
+ }
+
+ ISP_WRITEL(ISP_INT_CLEAR, irq_status);
+ node.isp_irq_val = irq_status;
+ _isp_get_systemtime(&system_time);
+ system_time.tv_sec = system_time.tv_sec * 1000000;
+ node.system_time = (uint64_t)(system_time.tv_sec+system_time.tv_usec);
+ ret = _isp_queue_write((struct isp_queue *)&g_isp_dev_ptr->queue, (struct isp_node*)&node);
+ spin_unlock_irqrestore(&isp_spin_lock, flag);
+ up(&g_isp_dev_ptr->sem_isr);
+
+ return IRQ_HANDLED;
+}
+//static irqreturn_t _dcam_irq_root(int irq, void *dev_id)
+void _dcam_isp_root(void)
+{
+ int32_t ret = 0;
+ unsigned long flag = 0;
+ struct isp_node node = { 0 };
+ struct timeval system_time;
+
+ //ISP_PRINT ("ISP_RAW: isp_k: _dcam_isp_root %d \n", s_dcam_int_eb);
+
+ if(0x00 !=s_dcam_int_eb)
+ {
+ spin_lock_irqsave(&isp_spin_lock,flag);
+ #if defined(CONFIG_MACH_CORE3)
+ node.dcam_irq_val = ISP_INT_FETCH_EOF;
+ #else
+ node.dcam_irq_val = ISP_INT_FETCH_SOF;
+ #endif
+
+ //ISP_PRINT("isp_k: dcam sof irq :0x%x\n", node.dcam_irq_val);
+ _isp_get_systemtime(&system_time);
+ system_time.tv_sec = system_time.tv_sec * 1000000;
+ node.system_time = (uint64_t)(system_time.tv_sec+system_time.tv_usec);
+ ret = _isp_queue_write((struct isp_queue *)&g_isp_dev_ptr->queue, (struct isp_node*)&node);
+ spin_unlock_irqrestore(&isp_spin_lock, flag);
+ up(&g_isp_dev_ptr->sem_isr);
+ }
+
+ //return IRQ_HANDLED;
+}
+
+/**********************************************************
+*release the device
+*
+***********************************************************/
+static int32_t _isp_kernel_release (struct inode *node, struct file *pf)
+{
+ int ret = 0;
+ ISP_PRINT ("isp_k: release start \n");
+
+ mutex_lock(&s_isp_lock);
+
+ _isp_unregisterirq();
+ ret = _isp_module_dis();
+
+ mutex_unlock(&s_isp_lock);
+
+ _isp_stop_kernel_thread(g_isp_dev_ptr);
+ ISP_CHECK_ZERO(g_isp_dev_ptr);
+ ret = _isp_put_ctlr(g_isp_dev_ptr);
+ if (unlikely (ret) ) {
+ ISP_PRINT ("isp_k: release control error \n");
+ return -EFAULT;
+ }
+ ISP_PRINT ("isp_k: release end \n");
+ return ret;
+}
+/**********************************************************
+*read info from file
+*size_t size:
+*loff_t p:
+***********************************************************/
+#if 0
+static int32_t _isp_kernel_proc_read (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+ uint32_t reg_buf_len = 200;
+ uint32_t print_len = 0, print_cnt = 0;
+ uint32_t *reg_ptr = 0;
+
+ ISP_PRINT ("isp_k: _isp_kernel_proc_read 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x \n", (uint32_t)page, (uint32_t)start, (uint32_t)off, (uint32_t)count, (uint32_t)eof, (uint32_t)data);
+
+ (void)start; (void)off; (void)count; (void)eof;
+
+ if(0x00==g_isp_device.reg_base_addr)
+ {
+ return 0x00;
+ }
+
+ reg_ptr = (uint32_t*)g_isp_device.reg_base_addr;
+ len += sprintf(page + len, "Context for ISP device \n");
+ len += sprintf(page + len, "********************************************* \n");
+ while (print_len < reg_buf_len) {
+ len += sprintf(page + len, "offset 0x%x : 0x%x, 0x%x, 0x%x, 0x%x \n",
+ print_len,
+ reg_ptr[print_cnt],
+ reg_ptr[print_cnt+1],
+ reg_ptr[print_cnt+2],
+ reg_ptr[print_cnt+3]);
+ print_cnt += 4;
+ print_len += 16;
+ }
+ len += sprintf(page + len, "********************************************* \n");
+ len += sprintf(page + len, "The end of ISP device \n");
+ return len;
+}
+#endif
+/**********************************************************
+*the io controller of isp
+*unsigned int cmd:
+*unsigned long param:
+***********************************************************/
+static long _isp_kernel_ioctl( struct file *fl, unsigned int cmd, unsigned long param)
+{
+ long ret = 0;
+ uint32_t isp_irq, dcam_irq;
+ struct isp_irq_param irq_param = { 0 };
+ struct isp_node isp_node = { 0 };
+ struct isp_reg_param reg_param = { 0 };
+ struct isp_reg_bits *reg_bits_ptr = 0;
+
+ //ISP_PRINT("isp_k:_ioctl called, cmd: %x\n", cmd);
+
+ if (!fl) {
+ return -EINVAL;
+ }
+
+ ISP_CHECK_ZERO(g_isp_dev_ptr);
+
+ if(ISP_IO_IRQ==cmd)
+ {
+ ret = down_interruptible(&g_isp_dev_ptr->sem_isr);
+ if (ret) {
+ ISP_PRINT("isp_k: ioctl irq: down failed ret = %ld",ret);
+ memset(&irq_param, 0, sizeof(irq_param));
+ irq_param.ret_val = ret;
+ ret = copy_to_user ((void*) param, (void*)&irq_param, sizeof(irq_param));
+ if ( 0 != ret) {
+ ISP_PRINT("isp_k: ioctl irq: copy_to_user failed ret = %ld", ret);
+ }
+ ret = -ERESTARTSYS;
+ goto ISP_IOCTL_EXIT;
+ }
+ ret=_isp_queue_read(&g_isp_dev_ptr->queue, &isp_node);
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl irq: _isp_queue_read error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto ISP_IOCTL_EXIT;
+ }
+
+ irq_param.dcam_irq_val = isp_node.dcam_irq_val;
+ irq_param.isp_irq_val = isp_node.isp_irq_val;
+ isp_irq = isp_node.isp_irq_val;
+ dcam_irq = isp_node.dcam_irq_val;
+ irq_param.irq_val = dcam_irq|isp_irq;
+ irq_param.system_time = isp_node.system_time;
+ ret = copy_to_user ((void*) param, (void*)&irq_param, sizeof(struct isp_irq_param));
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl irq: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ }
+
+ } else {
+
+ mutex_lock(&s_isp_lock);
+
+ switch (cmd)
+ {
+ case ISP_IO_READ: {
+ uint32_t buf_size = 0;
+ //ISP_PRINT(" isp_k:_ioctl read called \n");
+ ret = copy_from_user((void*)&reg_param, (void*)param, sizeof(struct isp_reg_param));
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl read: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_READ_EXIT;
+ }
+ buf_size = reg_param.counts*sizeof(struct isp_reg_bits);
+ if (buf_size > g_isp_dev_ptr->buf_len) {
+ ret =-EFAULT;
+ goto IO_READ_EXIT;
+ }
+ reg_bits_ptr = (struct isp_reg_bits*) g_isp_dev_ptr->buf_addr;
+ ret = copy_from_user((void*)reg_bits_ptr, (void*)reg_param.reg_param, buf_size);
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl read: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret =-EFAULT;
+ goto IO_READ_EXIT;
+ }
+ _read_reg(reg_bits_ptr, reg_param.counts);
+
+ ret = copy_to_user((void*)reg_param.reg_param, (void*)reg_bits_ptr, buf_size);
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl read: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_READ_EXIT;
+ }
+ IO_READ_EXIT:
+ if(reg_bits_ptr) {
+ memset((void *)g_isp_dev_ptr->buf_addr, 0x00, buf_size);
+ reg_bits_ptr = NULL;
+ }
+ }
+ break;
+
+ case ISP_IO_WRITE: {
+ uint32_t buf_size = 0;
+ //ISP_PRINT(" isp_k:_ioctl write called \n");
+ ret = copy_from_user((void*)&reg_param, (void*)param, sizeof(struct isp_reg_param));
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl write: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_WRITE_EXIT;
+ }
+ buf_size = reg_param.counts*sizeof(struct isp_reg_bits);
+ if(buf_size > g_isp_dev_ptr->buf_len)
+ {
+ ret = -EFAULT;
+ goto IO_WRITE_EXIT;
+ }
+ reg_bits_ptr = (struct isp_reg_bits*) g_isp_dev_ptr->buf_addr;
+
+ ret = copy_from_user((void*)reg_bits_ptr, (void*)reg_param.reg_param, buf_size);
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl write: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_WRITE_EXIT;
+ }
+ _write_reg(reg_bits_ptr, reg_param.counts);
+
+ IO_WRITE_EXIT:
+ if(reg_bits_ptr) {
+ memset((void *)g_isp_dev_ptr->buf_addr, 0x00, buf_size);
+ reg_bits_ptr = NULL;
+ }
+
+ }
+ break;
+
+ case ISP_IO_RST: {
+ ISP_PRINT(" isp_k:ioctl restet start \n");
+ g_isp_dev_ptr->lnc_load.cap_eof_flag = 0;
+ ret = _isp_module_rst();
+ if (ret) {
+
+ ISP_PRINT("isp_k: ioctl restet error!\n");
+ ret = -EFAULT;
+ }
+ }
+ break;
+
+ case ISP_IO_SETCLK: {
+ ISP_PRINT(" isp_k:ioctl set clock start \n");
+ }
+ break;
+
+ case ISP_IO_STOP: {
+ unsigned long flag = 0;
+ struct isp_node node = { 0 };
+ ret = _isp_en_irq(0);//dis-enable the interrupt
+ ISP_PRINT("isp_k: ioctl stop start !\n");
+ spin_lock_irqsave(&isp_spin_lock,flag);
+ node.dcam_irq_val = ISP_INT_STOP;
+ ret = _isp_queue_write((struct isp_queue *)&g_isp_dev_ptr->queue, (struct isp_node*)&node);
+ spin_unlock_irqrestore(&isp_spin_lock, flag);
+ up(&g_isp_dev_ptr->sem_isr);
+ }
+ break;
+
+ case ISP_IO_INT: {
+ unsigned long int_num;
+ ret = copy_from_user((void*)&int_num, (void*)param, 0x04);
+ if (ret) {
+ ISP_PRINT ("isp_k:io int copy param error, ret = %d \n", (uint32_t)ret);
+ ret = -EFAULT;
+ goto ISP_IOCTL_LOCKED_CMD_EXIT;
+ }
+ ret = _isp_en_irq(int_num);
+ //ret = _isp_registerirq();
+ if (unlikely(ret)) {
+ ISP_PRINT ("isp_k:enable interrupt error \n");
+ ret = -EFAULT;
+ }
+ }
+ break;
+
+ case ISP_IO_DCAM_INT: {
+ unsigned long int_param;
+ ret = copy_from_user((void*)&int_param, (void*)param, 0x04);
+ if (ret) {
+ ISP_PRINT ("isp_k:dcam int copy params error, ret = %d \n", (uint32_t)ret);
+ ret = -EFAULT;
+ goto ISP_IOCTL_LOCKED_CMD_EXIT;
+ }
+ ret = _isp_cfg_dcam_int(int_param);
+ if (unlikely(ret)) {
+ ISP_PRINT ("isp_k:cfg dcam interrupt error \n");
+ ret = -EFAULT;
+ }
+ }
+ break;
+
+ case ISP_IO_LNC_PARAM: {
+ uint32_t buf_size = 0;
+ uint32_t* addr = 0;
+ ret = copy_from_user((void*)&reg_param, (void*)param, sizeof(struct isp_reg_param));
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl lnc param: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_LNC_PARAM_EXIT;
+ }
+ buf_size = reg_param.counts;
+ if(buf_size > g_isp_dev_ptr->buf_len){
+
+ ret = -EFAULT;
+ goto IO_LNC_PARAM_EXIT;
+ }
+ addr = (uint32_t*) g_isp_dev_ptr->buf_addr;
+ ret = copy_from_user((void*)addr, (void*)reg_param.reg_param, buf_size);
+ if ( 0 != ret) {
+
+ ISP_PRINT("isp_k: ioctl lnc param: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_LNC_PARAM_EXIT;
+ }
+ ret = _isp_lnc_param_set(addr, buf_size);
+ if ( 0 != ret) {
+ ISP_PRINT("isp_k: ioctl lnc param error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_LNC_PARAM_EXIT;
+ }
+
+ IO_LNC_PARAM_EXIT:
+ if(addr) {
+ memset((void *)g_isp_dev_ptr->buf_addr, 0x00, buf_size);
+ addr = NULL;
+ }
+ }
+ break;
+
+ case ISP_IO_LNC: {
+ uint32_t buf_size = 0;
+ ret = copy_from_user((void*)&reg_param, (void*)param, sizeof(struct isp_reg_param));
+ if ( 0 != ret) {
+ ISP_PRINT("isp_k: ioctl lnc: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_LNC_EXIT;
+ }
+ buf_size = reg_param.counts*sizeof(struct isp_reg_bits);
+ if(buf_size > g_isp_dev_ptr->buf_len)
+ {
+ ret = -EFAULT;
+ ISP_PRINT("isp_k: isp_io_lnc: buf len failed\n");
+ goto IO_LNC_EXIT;
+ }
+ reg_bits_ptr = (struct isp_reg_bits*) g_isp_dev_ptr->buf_addr;
+ ret = copy_from_user((void*)reg_bits_ptr, (void*)reg_param.reg_param, buf_size);
+ if ( 0 != ret) {
+ ISP_PRINT("isp_k: ioctl lnc: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ goto IO_LNC_EXIT;
+ }
+
+ if (g_isp_dev_ptr->lnc_load.cap_eof_flag == 0) {
+ ret = _isp_lnc_param_load(reg_bits_ptr, reg_param.counts);
+ } else {
+ memcpy((void *)g_isp_dev_ptr->lnc_load.load_buf, (void *)reg_bits_ptr, buf_size);
+ g_isp_dev_ptr->lnc_load.param_counts = reg_param.counts;
+ g_isp_dev_ptr->lnc_load.load_lnc_flag = 1;
+ ret = down_timeout(&g_isp_dev_ptr->lnc_load.load_done_sem, msecs_to_jiffies(500));
+ }
+ if (unlikely(ret)) {
+ ISP_PRINT ("isp_k:load lnc error \n");
+ ret = -EFAULT;
+ }
+ IO_LNC_EXIT:
+ if(reg_bits_ptr) {
+ memset((void *)g_isp_dev_ptr->buf_addr, 0x00, buf_size);
+ reg_bits_ptr = NULL;
+ }
+ }
+ break;
+
+ case ISP_IO_ALLOC: {
+
+ ret = copy_from_user((void*)&reg_param, (void*)param, sizeof(struct isp_reg_param));
+ if ( 0 != ret) {
+ ISP_PRINT("isp_k: ioctl write: copy_to_user error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ break;
+ }
+ ret = _isp_alloc(&reg_param.reg_param, reg_param.counts);
+ if ( 0 == ret) {
+ ret = copy_to_user((void*)param, (void*)&reg_param, sizeof(struct isp_reg_param));
+ } else {
+ ISP_PRINT("isp_k: ioctl alloc error, ret = 0x%x", (uint32_t)ret);
+ ret = -EFAULT;
+ }
+ }
+ break;
+
+ default:
+ mutex_unlock(&s_isp_lock);
+ ISP_PRINT("isp_k:_ioctl cmd is unsupported, cmd = %x\n", (int32_t)cmd);
+ return -EFAULT;
+ }
+
+ ISP_IOCTL_LOCKED_CMD_EXIT:
+ mutex_unlock(&s_isp_lock);
+ }
+
+ //ISP_PRINT("isp_k:_ioctl finished\n");
+ ISP_IOCTL_EXIT:
+ return ret;
+}
+
+static int _isp_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ ISP_PRINT ("isp_k:probe start\n");
+
+ ret = misc_register(&isp_dev);
+ if (ret) {
+ ISP_PRINT ( "isp_k:probe cannot register miscdev on minor=%d (%d)\n",(int32_t)ISP_MINOR, (int32_t)ret);
+ return ret;
+ }
+ mutex_init(&s_isp_lock);
+/*
+ isp_proc_file = create_proc_read_entry("driver/sprd_isp" ,
+ 0444,
+ NULL,
+ _isp_kernel_proc_read,
+ NULL);
+ if (unlikely(NULL == isp_proc_file)) {
+ ISP_PRINT("isp_k:probe Can't create an entry for isp in /proc \n");
+ ret = ENOMEM;
+ return ret;
+ }
+*/
+ isp_dev.this_device->of_node = pdev->dev.of_node;
+ parse_baseaddress(pdev->dev.of_node);
+ ISP_PRINT (" isp_k:probe end\n");
+ return 0;
+}
+
+static int _isp_remove(struct platform_device * dev)
+{
+ ISP_PRINT ("isp_k: remove start \n");
+
+ misc_deregister(&isp_dev);
+
+ if (isp_proc_file) {
+ remove_proc_entry("driver/sprd_isp", NULL);
+ }
+
+ ISP_PRINT ("isp_k: remove end !\n");
+
+ return 0;
+}
+
+static int32_t __init isp_kernel_init(void)
+{
+ int32_t ret = 0;
+ unsigned long addr = 0;
+ ISP_PRINT ("isp_k: init start \n");
+ if (platform_driver_register(&isp_driver) != 0) {
+ ISP_PRINT ("isp_kernel_init: platform device register error \n");
+ return -1;
+ }
+
+ g_isp_dev_ptr = (struct isp_device_t*)vzalloc(sizeof(struct isp_device_t));
+ ISP_CHECK_ZERO(g_isp_dev_ptr);
+ init_MUTEX(&g_isp_dev_ptr->sem_isp);
+ init_MUTEX_LOCKED(&g_isp_dev_ptr->sem_isr); /*for interrupt */
+ g_isp_dev_ptr->s_isp_clk = NULL;
+ g_isp_dev_ptr->s_isp_clk_mm_i = NULL;
+ g_isp_dev_ptr->buf_addr = 0;
+ g_isp_dev_ptr->buf_len = 0;
+
+ g_isp_dev_ptr->buf_addr = (unsigned long)vzalloc(ISP_BUF_MAX_SIZE);
+ if (0 == g_isp_dev_ptr->buf_addr) {
+ ret = -1;
+ ISP_PRINT ("isp_kernel_init 1: alloc error \n");
+ goto ISP_K_INIT_EXIT;
+ }
+ g_isp_dev_ptr->buf_len = ISP_BUF_MAX_SIZE;
+
+ g_isp_dev_ptr->lnc_load.load_buf = (unsigned long)vzalloc(ISP_BUF_MAX_SIZE);
+ if (0 == g_isp_dev_ptr->lnc_load.load_buf) {
+ ret = -1;
+ ISP_PRINT ("isp_kernel_init 3: alloc error \n");
+ goto ISP_K_INIT_EXIT;
+ }
+ ret = _isp_alloc(&addr, ISP_BUF_MAX_SIZE);
+ if (ret) {
+ ret = -1;
+ ISP_PRINT ("isp_kernel_init 2: alloc error \n");
+ goto ISP_K_INIT_EXIT;
+ }
+
+ ISP_PRINT ("isp_k: init end\n");
+
+ return ret;
+
+ISP_K_INIT_EXIT:
+ _isp_free();
+ if (g_isp_dev_ptr->buf_addr) {
+ vfree((void *)g_isp_dev_ptr->buf_addr);
+ g_isp_dev_ptr->buf_addr = 0;
+ g_isp_dev_ptr->buf_len = 0;
+ }
+ if (g_isp_dev_ptr->lnc_load.load_buf) {
+ vfree((void *)g_isp_dev_ptr->lnc_load.load_buf);
+ g_isp_dev_ptr->lnc_load.load_buf = 0;
+ }
+ if (g_isp_dev_ptr) {
+ vfree(g_isp_dev_ptr);
+ g_isp_dev_ptr = 0;
+ }
+
+ return ret;
+}
+
+static void isp_kernel_exit(void)
+{
+ ISP_PRINT ("isp_k: exit start \n");
+
+ platform_driver_unregister(&isp_driver);
+ mutex_destroy(&s_isp_lock);
+ _isp_free();
+ ISP_CHECK_ZERO_VOID(g_isp_dev_ptr);
+ if (g_isp_dev_ptr->buf_addr) {
+ vfree((void *)g_isp_dev_ptr->buf_addr);
+ g_isp_dev_ptr->buf_addr = 0;
+ g_isp_dev_ptr->buf_len = 0;
+ }
+ if(g_isp_dev_ptr->lnc_load.load_buf) {
+ vfree((void *)g_isp_dev_ptr->lnc_load.load_buf);
+ g_isp_dev_ptr->lnc_load.load_buf = 0;
+ }
+ vfree(g_isp_dev_ptr);
+ g_isp_dev_ptr = NULL;
+
+ ISP_PRINT ("isp_k: exit end \n");
+}
+
+module_init(isp_kernel_init);
+module_exit(isp_kernel_exit);
+
+MODULE_DESCRIPTION("Isp Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/sprd_isp/isp1.0/isp_drv_null.c b/drivers/media/sprd_isp/isp1.0/isp_drv_null.c
new file mode 100644
index 00000000..4e8b84e0
--- /dev/null
+++ b/drivers/media/sprd_isp/isp1.0/isp_drv_null.c
@@ -0,0 +1,305 @@
+/*
+ * 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/slab.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <video/isp_drv_kernel.h>
+
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include "Shark_reg_isp.h"
+
+
+#define DEBUG_ISP_DRV
+#ifdef DEBUG_ISP_DRV
+#define ISP_PRINT printk
+#else
+#define ISP_PRINT(...)
+#endif
+#define ISP_MINOR MISC_DYNAMIC_MINOR/*isp minor number*/
+static struct proc_dir_entry* isp_proc_file;
+
+/**file operation functions declare**/
+static int32_t _isp_kernel_open(struct inode *node, struct file *filp);
+static int32_t _isp_kernel_release(struct inode *node, struct file *filp);
+static long _isp_kernel_ioctl( struct file *fl, unsigned int cmd, unsigned long param);
+/**driver' functions declare**/
+static int32_t _isp_probe(struct platform_device *pdev);
+static int32_t _isp_remove(struct platform_device *dev);
+/**module' functions declare**/
+static int32_t __init isp_kernel_init(void);
+static void isp_kernel_exit(void);
+
+static struct file_operations isp_fops = {
+ .owner = THIS_MODULE,
+ .open = _isp_kernel_open,
+ .unlocked_ioctl = _isp_kernel_ioctl,
+ .release = _isp_kernel_release,
+};
+
+static struct miscdevice isp_dev = {
+ .minor = ISP_MINOR,
+ .name = "sprd_isp",
+ .fops = &isp_fops,
+};
+
+static const struct of_device_id of_match_table_isp[] = {
+ { .compatible = "sprd,sprd_isp", },
+ { },
+};
+
+static struct platform_driver isp_driver = {
+ .probe = _isp_probe,
+ .remove = _isp_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "sprd_isp",
+ .of_match_table = of_match_ptr(of_match_table_isp),
+ },
+};
+
+/**********************************************************
+*open the device
+*
+***********************************************************/
+static int32_t _isp_kernel_open (struct inode *node, struct file *pf)
+{
+ int32_t ret = 0;
+ ISP_PRINT ("isp_k: open start \n");
+
+ return ret;
+}
+
+//static irqreturn_t _dcam_irq_root(int irq, void *dev_id)
+void _dcam_isp_root(void)
+{
+ int32_t ret = 0;
+
+ return IRQ_HANDLED;
+}
+
+/**********************************************************
+*release the device
+*
+***********************************************************/
+static int32_t _isp_kernel_release (struct inode *node, struct file *pf)
+{
+ int ret = 0;
+ ISP_PRINT ("isp_k: release start \n");
+
+ ISP_PRINT ("isp_k: release end \n");
+ return ret;
+}
+/**********************************************************
+*read info from file
+*size_t size:
+*loff_t p:
+***********************************************************/
+static int32_t _isp_kernel_proc_read (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ int len = 0;
+#if 0
+ uint32_t reg_buf_len = 200;
+ uint32_t print_len = 0, print_cnt = 0;
+ uint32_t *reg_ptr = 0;
+
+ ISP_PRINT ("isp_k: _isp_kernel_proc_read 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x \n", (uint32_t)page, (uint32_t)start, (uint32_t)off, (uint32_t)count, (uint32_t)eof, (uint32_t)data);
+
+ (void)start; (void)off; (void)count; (void)eof;
+
+ if(0x00==g_isp_device.reg_base_addr)
+ {
+ return 0x00;
+ }
+
+ reg_ptr = (uint32_t*)g_isp_device.reg_base_addr;
+ len += sprintf(page + len, "Context for ISP device \n");
+ len += sprintf(page + len, "********************************************* \n");
+ while (print_len < reg_buf_len) {
+ len += sprintf(page + len, "offset 0x%x : 0x%x, 0x%x, 0x%x, 0x%x \n",
+ print_len,
+ reg_ptr[print_cnt],
+ reg_ptr[print_cnt+1],
+ reg_ptr[print_cnt+2],
+ reg_ptr[print_cnt+3]);
+ print_cnt += 4;
+ print_len += 16;
+ }
+ len += sprintf(page + len, "********************************************* \n");
+ len += sprintf(page + len, "The end of ISP device \n");
+#endif
+ return len;
+}
+
+/**********************************************************
+*the io controller of isp
+*unsigned int cmd:
+*unsigned long param:
+***********************************************************/
+static long _isp_kernel_ioctl( struct file *fl, unsigned int cmd, unsigned long param)
+{
+ long ret = 0;
+
+ if(ISP_IO_IRQ==cmd)
+ {
+ } else {
+
+ switch (cmd)
+ {
+ case ISP_IO_READ: {
+ }
+ break;
+
+ case ISP_IO_WRITE: {
+ }
+ break;
+
+ case ISP_IO_RST: {
+ ISP_PRINT(" isp_k:ioctl restet start \n");
+ }
+ break;
+
+ case ISP_IO_SETCLK:
+ ISP_PRINT(" isp_k:ioctl set clock start \n");
+ break;
+
+ case ISP_IO_STOP: {
+ }
+ break;
+
+ case ISP_IO_INT: {
+ }
+ break;
+
+ case ISP_IO_DCAM_INT: {
+ }
+ break;
+
+ case ISP_IO_LNC_PARAM: {
+ }
+ break;
+
+ case ISP_IO_LNC: {
+ }
+ break;
+
+ case ISP_IO_ALLOC: {
+ }
+ break;
+
+ default:
+ ISP_PRINT("isp_k:_ioctl cmd is unsupported, cmd = %x\n", (int32_t)cmd);
+ return -EFAULT;
+ }
+
+ }
+
+ //ISP_PRINT("isp_k:_ioctl finished\n");
+ ISP_IOCTL_EXIT:
+ return ret;
+}
+
+static int _isp_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ ISP_PRINT ("isp_k:probe start\n");
+
+ ret = misc_register(&isp_dev);
+ if (ret) {
+ ISP_PRINT ( "isp_k:probe cannot register miscdev on minor=%d (%d)\n",(int32_t)ISP_MINOR, (int32_t)ret);
+ return ret;
+ }
+/*
+ isp_proc_file = create_proc_read_entry("driver/sprd_isp" ,
+ 0444,
+ NULL,
+ _isp_kernel_proc_read,
+ NULL);
+ if (unlikely(NULL == isp_proc_file)) {
+ ISP_PRINT("isp_k:probe Can't create an entry for isp in /proc \n");
+ ret = ENOMEM;
+ return ret;
+ }
+*/
+ isp_dev.this_device->of_node = pdev->dev.of_node;
+ ISP_PRINT (" isp_k:probe end\n");
+ return 0;
+}
+
+static int _isp_remove(struct platform_device * dev)
+{
+ ISP_PRINT ("isp_k: remove start \n");
+
+ misc_deregister(&isp_dev);
+
+ if (isp_proc_file) {
+ remove_proc_entry("driver/sprd_isp", NULL);
+ }
+
+ ISP_PRINT ("isp_k: remove end !\n");
+
+ return 0;
+}
+
+static int32_t __init isp_kernel_init(void)
+{
+ int32_t ret = 0;
+ uint32_t addr = 0;
+ ISP_PRINT ("isp_k: init start \n");
+ if (platform_driver_register(&isp_driver) != 0) {
+ ISP_PRINT ("isp_kernel_init: platform device register error \n");
+ return -1;
+ }
+
+ ISP_PRINT ("isp_k: init end\n");
+
+ return ret;
+}
+
+static void isp_kernel_exit(void)
+{
+ ISP_PRINT ("isp_k: exit start \n");
+
+ platform_driver_unregister(&isp_driver);
+
+ ISP_PRINT ("isp_k: exit end \n");
+}
+
+module_init(isp_kernel_init);
+module_exit(isp_kernel_exit);
+
+MODULE_DESCRIPTION("Isp Driver");
+MODULE_LICENSE("GPL");