summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/isp')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch153
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch1226
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch453
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch124
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch1083
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch45
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch26
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch24
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch29
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch4625
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch209
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch696
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch1875
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch3413
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch2741
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch2384
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch4018
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch2249
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch2915
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch730
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch44
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch50
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch61
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch33
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch35
25 files changed, 29241 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch
new file mode 100644
index 0000000000..902f87943d
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/base/0001-omap3-Add-base-address-definitions-and-resources-fo.patch
@@ -0,0 +1,153 @@
1From 742cc1e62f0d04333c51630f3020da000aeb6de1 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Mon, 2 Mar 2009 19:36:26 +0200
4Subject: [PATCH] omap3: Add base address definitions and resources for OMAP 3 ISP
5
6This replaces earlier patch from Sergio Aguirre titled "[REVIEW PATCH 03/14]
7OMAP34XX: CAM: Resources fixes".
8
9Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
10---
11 arch/arm/mach-omap2/devices.c | 66 ++++++++++++++++++++++++---
12 arch/arm/plat-omap/include/mach/omap34xx.h | 28 +++++++++++-
13 2 files changed, 85 insertions(+), 9 deletions(-)
14
15diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
16index dad4528..2568b0c 100644
17--- a/arch/arm/mach-omap2/devices.c
18+++ b/arch/arm/mach-omap2/devices.c
19@@ -56,10 +56,60 @@ static inline void omap_init_camera(void)
20
21 #elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
22
23-static struct resource cam_resources[] = {
24+static struct resource omap3isp_resources[] = {
25+ {
26+ .start = OMAP3430_ISP_BASE,
27+ .end = OMAP3430_ISP_END,
28+ .flags = IORESOURCE_MEM,
29+ },
30+ {
31+ .start = OMAP3430_ISP_CBUFF_BASE,
32+ .end = OMAP3430_ISP_CBUFF_END,
33+ .flags = IORESOURCE_MEM,
34+ },
35+ {
36+ .start = OMAP3430_ISP_CCP2_BASE,
37+ .end = OMAP3430_ISP_CCP2_END,
38+ .flags = IORESOURCE_MEM,
39+ },
40 {
41- .start = OMAP34XX_CAMERA_BASE,
42- .end = OMAP34XX_CAMERA_BASE + 0x1B70,
43+ .start = OMAP3430_ISP_CCDC_BASE,
44+ .end = OMAP3430_ISP_CCDC_END,
45+ .flags = IORESOURCE_MEM,
46+ },
47+ {
48+ .start = OMAP3430_ISP_HIST_BASE,
49+ .end = OMAP3430_ISP_HIST_END,
50+ .flags = IORESOURCE_MEM,
51+ },
52+ {
53+ .start = OMAP3430_ISP_H3A_BASE,
54+ .end = OMAP3430_ISP_H3A_END,
55+ .flags = IORESOURCE_MEM,
56+ },
57+ {
58+ .start = OMAP3430_ISP_PREV_BASE,
59+ .end = OMAP3430_ISP_PREV_END,
60+ .flags = IORESOURCE_MEM,
61+ },
62+ {
63+ .start = OMAP3430_ISP_RESZ_BASE,
64+ .end = OMAP3430_ISP_RESZ_END,
65+ .flags = IORESOURCE_MEM,
66+ },
67+ {
68+ .start = OMAP3430_ISP_SBL_BASE,
69+ .end = OMAP3430_ISP_SBL_END,
70+ .flags = IORESOURCE_MEM,
71+ },
72+ {
73+ .start = OMAP3430_ISP_CSI2A_BASE,
74+ .end = OMAP3430_ISP_CSI2A_END,
75+ .flags = IORESOURCE_MEM,
76+ },
77+ {
78+ .start = OMAP3430_ISP_CSI2PHY_BASE,
79+ .end = OMAP3430_ISP_CSI2PHY_END,
80 .flags = IORESOURCE_MEM,
81 },
82 {
83@@ -68,16 +118,16 @@ static struct resource cam_resources[] = {
84 }
85 };
86
87-static struct platform_device omap_cam_device = {
88- .name = "omap34xxcam",
89+static struct platform_device omap3isp_device = {
90+ .name = "omap3isp",
91 .id = -1,
92- .num_resources = ARRAY_SIZE(cam_resources),
93- .resource = cam_resources,
94+ .num_resources = ARRAY_SIZE(omap3isp_resources),
95+ .resource = omap3isp_resources,
96 };
97
98 static inline void omap_init_camera(void)
99 {
100- platform_device_register(&omap_cam_device);
101+ platform_device_register(&omap3isp_device);
102 }
103 #else
104 static inline void omap_init_camera(void)
105diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h
106index 27a1e45..3bfbdf7 100644
107--- a/arch/arm/plat-omap/include/mach/omap34xx.h
108+++ b/arch/arm/plat-omap/include/mach/omap34xx.h
109@@ -49,6 +49,33 @@
110 #define OMAP343X_CTRL_BASE OMAP343X_SCM_BASE
111
112 #define OMAP34XX_IC_BASE 0x48200000
113+
114+#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000)
115+#define OMAP3430_ISP_CBUFF_BASE (OMAP3430_ISP_BASE + 0x0100)
116+#define OMAP3430_ISP_CCP2_BASE (OMAP3430_ISP_BASE + 0x0400)
117+#define OMAP3430_ISP_CCDC_BASE (OMAP3430_ISP_BASE + 0x0600)
118+#define OMAP3430_ISP_HIST_BASE (OMAP3430_ISP_BASE + 0x0A00)
119+#define OMAP3430_ISP_H3A_BASE (OMAP3430_ISP_BASE + 0x0C00)
120+#define OMAP3430_ISP_PREV_BASE (OMAP3430_ISP_BASE + 0x0E00)
121+#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000)
122+#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200)
123+#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400)
124+#define OMAP3430_ISP_CSI2A_BASE (OMAP3430_ISP_BASE + 0x1800)
125+#define OMAP3430_ISP_CSI2PHY_BASE (OMAP3430_ISP_BASE + 0x1970)
126+
127+#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F)
128+#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077)
129+#define OMAP3430_ISP_CCP2_END (OMAP3430_ISP_CCP2_BASE + 0x1EF)
130+#define OMAP3430_ISP_CCDC_END (OMAP3430_ISP_CCDC_BASE + 0x0A7)
131+#define OMAP3430_ISP_HIST_END (OMAP3430_ISP_HIST_BASE + 0x047)
132+#define OMAP3430_ISP_H3A_END (OMAP3430_ISP_H3A_BASE + 0x05F)
133+#define OMAP3430_ISP_PREV_END (OMAP3430_ISP_PREV_BASE + 0x09F)
134+#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB)
135+#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB)
136+#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F)
137+#define OMAP3430_ISP_CSI2A_END (OMAP3430_ISP_CSI2A_BASE + 0x16F)
138+#define OMAP3430_ISP_CSI2PHY_END (OMAP3430_ISP_CSI2PHY_BASE + 0x007)
139+
140 #define OMAP34XX_IVA_INTC_BASE 0x40000000
141 #define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000)
142 #define OMAP34XX_HSUSB_HOST_BASE (L4_34XX_BASE + 0x64000)
143@@ -56,7 +83,6 @@
144 #define OMAP34XX_SR1_BASE 0x480C9000
145 #define OMAP34XX_SR2_BASE 0x480CB000
146
147-#define OMAP34XX_CAMERA_BASE (L4_34XX_BASE + 0xBC000)
148 #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000)
149
150
151--
1521.5.6.5
153
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch
new file mode 100644
index 0000000000..c2c9bc2b62
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0001-omap-iommu-tlb-and-pagetable-primitives.patch
@@ -0,0 +1,1226 @@
1From a62a047ed02162573e4bece18ecf8bdd66ccd06b Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Mon, 26 Jan 2009 15:13:40 +0200
4Subject: [PATCH] omap iommu: tlb and pagetable primitives
5
6This patch provides:
7
8- iotlb_*() : iommu tlb operations
9- iopgtable_*() : iommu pagetable(twl) operations
10- iommu_*() : the other generic operations
11
12and the entry points to register and acquire iommu object.
13
14Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
15---
16 arch/arm/plat-omap/include/mach/iommu.h | 157 +++++
17 arch/arm/plat-omap/iommu.c | 953 +++++++++++++++++++++++++++++++
18 arch/arm/plat-omap/iopgtable.h | 72 +++
19 3 files changed, 1182 insertions(+), 0 deletions(-)
20 create mode 100644 arch/arm/plat-omap/include/mach/iommu.h
21 create mode 100644 arch/arm/plat-omap/iommu.c
22 create mode 100644 arch/arm/plat-omap/iopgtable.h
23
24diff --git a/arch/arm/plat-omap/include/mach/iommu.h b/arch/arm/plat-omap/include/mach/iommu.h
25new file mode 100644
26index 0000000..ef04d7a
27--- /dev/null
28+++ b/arch/arm/plat-omap/include/mach/iommu.h
29@@ -0,0 +1,157 @@
30+/*
31+ * omap iommu: main structures
32+ *
33+ * Copyright (C) 2008-2009 Nokia Corporation
34+ *
35+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
36+ *
37+ * This program is free software; you can redistribute it and/or modify
38+ * it under the terms of the GNU General Public License version 2 as
39+ * published by the Free Software Foundation.
40+ */
41+
42+#ifndef __MACH_IOMMU_H
43+#define __MACH_IOMMU_H
44+
45+struct iotlb_entry {
46+ u32 da;
47+ u32 pa;
48+ u32 pgsz, prsvd, valid;
49+ union {
50+ u16 ap;
51+ struct {
52+ u32 endian, elsz, mixed;
53+ };
54+ };
55+};
56+
57+struct iommu {
58+ const char *name;
59+ struct module *owner;
60+ struct clk *clk;
61+ void __iomem *regbase;
62+ struct device *dev;
63+
64+ unsigned int refcount;
65+ struct mutex iommu_lock; /* global for this whole object */
66+
67+ /*
68+ * We don't change iopgd for a situation like pgd for a task,
69+ * but share it globally for each iommu.
70+ */
71+ u32 *iopgd;
72+ spinlock_t page_table_lock; /* protect iopgd */
73+
74+ int nr_tlb_entries;
75+
76+ struct list_head mmap;
77+ struct mutex mmap_lock; /* protect mmap */
78+
79+ int (*isr)(struct iommu *obj);
80+
81+ void *ctx; /* iommu context: registres saved area */
82+};
83+
84+struct cr_regs {
85+ union {
86+ struct {
87+ u16 cam_l;
88+ u16 cam_h;
89+ };
90+ u32 cam;
91+ };
92+ union {
93+ struct {
94+ u16 ram_l;
95+ u16 ram_h;
96+ };
97+ u32 ram;
98+ };
99+};
100+
101+struct iotlb_lock {
102+ short base;
103+ short vict;
104+};
105+
106+/* architecture specific functions */
107+struct iommu_functions {
108+ unsigned long version;
109+
110+ int (*enable)(struct iommu *obj);
111+ void (*disable)(struct iommu *obj);
112+ u32 (*fault_isr)(struct iommu *obj, u32 *ra);
113+
114+ void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr);
115+ void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr);
116+
117+ struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e);
118+ int (*cr_valid)(struct cr_regs *cr);
119+ u32 (*cr_to_virt)(struct cr_regs *cr);
120+ void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e);
121+ ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf);
122+
123+ u32 (*get_pte_attr)(struct iotlb_entry *e);
124+
125+ void (*save_ctx)(struct iommu *obj);
126+ void (*restore_ctx)(struct iommu *obj);
127+ ssize_t (*dump_ctx)(struct iommu *obj, char *buf);
128+};
129+
130+struct iommu_platform_data {
131+ const char *name;
132+ const char *clk_name;
133+ const int nr_tlb_entries;
134+};
135+
136+#include <mach/iommu2.h>
137+
138+/*
139+ * utilities for super page(16MB, 1MB, 64KB and 4KB)
140+ */
141+
142+#define iopgsz_max(bytes) \
143+ (((bytes) >= SZ_16M) ? SZ_16M : \
144+ ((bytes) >= SZ_1M) ? SZ_1M : \
145+ ((bytes) >= SZ_64K) ? SZ_64K : \
146+ ((bytes) >= SZ_4K) ? SZ_4K : 0)
147+
148+#define bytes_to_iopgsz(bytes) \
149+ (((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M : \
150+ ((bytes) == SZ_1M) ? MMU_CAM_PGSZ_1M : \
151+ ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K : \
152+ ((bytes) == SZ_4K) ? MMU_CAM_PGSZ_4K : -1)
153+
154+#define iopgsz_to_bytes(iopgsz) \
155+ (((iopgsz) == MMU_CAM_PGSZ_16M) ? SZ_16M : \
156+ ((iopgsz) == MMU_CAM_PGSZ_1M) ? SZ_1M : \
157+ ((iopgsz) == MMU_CAM_PGSZ_64K) ? SZ_64K : \
158+ ((iopgsz) == MMU_CAM_PGSZ_4K) ? SZ_4K : 0)
159+
160+#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0)
161+
162+/*
163+ * global functions
164+ */
165+extern u32 iommu_arch_version(void);
166+
167+extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e);
168+extern void flush_iotlb_page(struct iommu *obj, u32 da);
169+extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
170+extern void flush_iotlb_all(struct iommu *obj);
171+
172+ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf);
173+
174+extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
175+extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
176+
177+extern struct iommu *iommu_get(const char *name);
178+extern void iommu_put(struct iommu *obj);
179+
180+extern void iommu_save_ctx(struct iommu *obj);
181+extern void iommu_restore_ctx(struct iommu *obj);
182+
183+extern int install_iommu_arch(const struct iommu_functions *ops);
184+extern void uninstall_iommu_arch(const struct iommu_functions *ops);
185+
186+#endif /* __MACH_IOMMU_H */
187diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
188new file mode 100644
189index 0000000..e638883
190--- /dev/null
191+++ b/arch/arm/plat-omap/iommu.c
192@@ -0,0 +1,953 @@
193+/*
194+ * omap iommu: tlb and pagetable primitives
195+ *
196+ * Copyright (C) 2008-2009 Nokia Corporation
197+ *
198+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
199+ * Paul Mundt and Toshihiro Kobayashi
200+ *
201+ * This program is free software; you can redistribute it and/or modify
202+ * it under the terms of the GNU General Public License version 2 as
203+ * published by the Free Software Foundation.
204+ */
205+
206+#include <linux/err.h>
207+#include <linux/module.h>
208+#include <linux/interrupt.h>
209+#include <linux/ioport.h>
210+#include <linux/clk.h>
211+#include <linux/platform_device.h>
212+
213+#include <asm/io.h>
214+#include <asm/cacheflush.h>
215+
216+#include <mach/clock.h>
217+#include <mach/iommu.h>
218+
219+#include "iopgtable.h"
220+
221+/* accommodate the difference between omap1 and omap2/3 */
222+static const struct iommu_functions *arch_iommu;
223+
224+static struct platform_driver omap_iommu_driver;
225+static struct kmem_cache *iopte_cachep;
226+
227+/**
228+ * install_iommu_arch() - Install archtecure specific iommu functions
229+ * @ops: a pointer to architecture specific iommu functions
230+ *
231+ * There are several kind of iommu algorithm(tlb, pagetable) among
232+ * omap series. This interface installs such an iommu algorighm.
233+ **/
234+int install_iommu_arch(const struct iommu_functions *ops)
235+{
236+ if (arch_iommu)
237+ return -EBUSY;
238+
239+ arch_iommu = ops;
240+ return 0;
241+}
242+EXPORT_SYMBOL_GPL(install_iommu_arch);
243+
244+/**
245+ * uninstall_iommu_arch() - Uninstall archtecure specific iommu functions
246+ * @ops: a pointer to architecture specific iommu functions
247+ *
248+ * This interface uninstalls the iommu algorighm installed previously.
249+ **/
250+void uninstall_iommu_arch(const struct iommu_functions *ops)
251+{
252+ if (arch_iommu != ops)
253+ pr_err("%s: not your arch\n", __func__);
254+
255+ arch_iommu = NULL;
256+}
257+EXPORT_SYMBOL_GPL(uninstall_iommu_arch);
258+
259+/**
260+ * iommu_save_ctx() - Save registers for pm off-mode support
261+ * @obj: target iommu
262+ **/
263+void iommu_save_ctx(struct iommu *obj)
264+{
265+ arch_iommu->save_ctx(obj);
266+}
267+EXPORT_SYMBOL_GPL(iommu_save_ctx);
268+
269+/**
270+ * iommu_restore_ctx() - Restore registers for pm off-mode support
271+ * @obj: target iommu
272+ **/
273+void iommu_restore_ctx(struct iommu *obj)
274+{
275+ arch_iommu->restore_ctx(obj);
276+}
277+EXPORT_SYMBOL_GPL(iommu_restore_ctx);
278+
279+/**
280+ * iommu_arch_version() - Return running iommu arch version
281+ **/
282+u32 iommu_arch_version(void)
283+{
284+ return arch_iommu->version;
285+}
286+EXPORT_SYMBOL_GPL(iommu_arch_version);
287+
288+static int iommu_enable(struct iommu *obj)
289+{
290+ int err;
291+
292+ if (!obj)
293+ return -EINVAL;
294+
295+ clk_enable(obj->clk);
296+
297+ err = arch_iommu->enable(obj);
298+
299+ clk_disable(obj->clk);
300+ return err;
301+}
302+
303+static void iommu_disable(struct iommu *obj)
304+{
305+ if (!obj)
306+ return;
307+
308+ clk_enable(obj->clk);
309+
310+ arch_iommu->disable(obj);
311+
312+ clk_disable(obj->clk);
313+}
314+
315+#ifdef DEBUG
316+static ssize_t iommu_dump_ctx(struct iommu *obj, char *buf)
317+{
318+ if (!obj || !buf)
319+ return -EINVAL;
320+
321+ return arch_iommu->dump_ctx(obj, buf);
322+}
323+#endif
324+
325+/*
326+ * TLB operations
327+ */
328+static inline void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
329+{
330+ BUG_ON(!cr || !e);
331+
332+ arch_iommu->cr_to_e(cr, e);
333+}
334+
335+static inline int iotlb_cr_valid(struct cr_regs *cr)
336+{
337+ if (!cr)
338+ return -EINVAL;
339+
340+ return arch_iommu->cr_valid(cr);
341+}
342+
343+static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj,
344+ struct iotlb_entry *e)
345+{
346+ if (!e)
347+ return NULL;
348+
349+ return arch_iommu->alloc_cr(obj, e);
350+}
351+
352+static inline u32 iotlb_cr_to_virt(struct cr_regs *cr)
353+{
354+ return arch_iommu->cr_to_virt(cr);
355+}
356+
357+static u32 get_iopte_attr(struct iotlb_entry *e)
358+{
359+ return arch_iommu->get_pte_attr(e);
360+}
361+
362+static u32 iommu_report_fault(struct iommu *obj, u32 *da)
363+{
364+ return arch_iommu->fault_isr(obj, da);
365+}
366+
367+static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
368+{
369+ u32 val;
370+
371+ val = iommu_read_reg(obj, MMU_LOCK);
372+
373+ l->base = MMU_LOCK_BASE(val);
374+ l->vict = MMU_LOCK_VICT(val);
375+
376+ BUG_ON(l->base != 0); /* Currently no preservation is used */
377+}
378+
379+static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
380+{
381+ u32 val;
382+
383+ BUG_ON(l->base != 0); /* Currently no preservation is used */
384+
385+ val = (l->base << MMU_LOCK_BASE_SHIFT);
386+ val |= (l->vict << MMU_LOCK_VICT_SHIFT);
387+
388+ iommu_write_reg(obj, val, MMU_LOCK);
389+}
390+
391+static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr)
392+{
393+ arch_iommu->tlb_read_cr(obj, cr);
394+}
395+
396+static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr)
397+{
398+ arch_iommu->tlb_load_cr(obj, cr);
399+
400+ iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
401+ iommu_write_reg(obj, 1, MMU_LD_TLB);
402+}
403+
404+/**
405+ * iotlb_dump_cr() - Dump an iommu tlb entry into buf
406+ * @obj: target iommu
407+ * @cr: contents of cam and ram register
408+ * @buf: output buffer
409+ **/
410+ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
411+{
412+ BUG_ON(!cr || !buf);
413+
414+ return arch_iommu->dump_cr(obj, cr, buf);
415+}
416+EXPORT_SYMBOL_GPL(iotlb_dump_cr);
417+
418+/**
419+ * load_iotlb_entry() - Set an iommu tlb entry
420+ * @obj: target iommu
421+ * @e: an iommu tlb entry info
422+ **/
423+int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
424+{
425+ int i;
426+ int err = 0;
427+ struct iotlb_lock l;
428+ struct cr_regs *cr;
429+
430+ if (!obj || !obj->nr_tlb_entries || !e)
431+ return -EINVAL;
432+
433+ clk_enable(obj->clk);
434+
435+ for (i = 0; i < obj->nr_tlb_entries; i++) {
436+ struct cr_regs tmp;
437+
438+ iotlb_lock_get(obj, &l);
439+ l.vict = i;
440+ iotlb_lock_set(obj, &l);
441+ iotlb_read_cr(obj, &tmp);
442+ if (!iotlb_cr_valid(&tmp))
443+ break;
444+ }
445+
446+ if (i == obj->nr_tlb_entries) {
447+ dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
448+ err = -EBUSY;
449+ goto out;
450+ }
451+
452+ cr = iotlb_alloc_cr(obj, e);
453+ if (IS_ERR(cr)) {
454+ clk_disable(obj->clk);
455+ return PTR_ERR(cr);
456+ }
457+
458+ iotlb_load_cr(obj, cr);
459+ kfree(cr);
460+
461+ /* increment victim for next tlb load */
462+ if (++l.vict == obj->nr_tlb_entries)
463+ l.vict = 0;
464+ iotlb_lock_set(obj, &l);
465+out:
466+ clk_disable(obj->clk);
467+ return err;
468+}
469+EXPORT_SYMBOL_GPL(load_iotlb_entry);
470+
471+/**
472+ * flush_iotlb_page() - Clear an iommu tlb entry
473+ * @obj: target iommu
474+ * @da: iommu device virtual address
475+ *
476+ * Clear an iommu tlb entry which includes 'da' address.
477+ **/
478+void flush_iotlb_page(struct iommu *obj, u32 da)
479+{
480+ struct iotlb_lock l;
481+ int i;
482+
483+ clk_enable(obj->clk);
484+
485+ for (i = 0; i < obj->nr_tlb_entries; i++) {
486+ struct cr_regs cr;
487+ u32 start;
488+ size_t bytes;
489+
490+ iotlb_lock_get(obj, &l);
491+ l.vict = i;
492+ iotlb_lock_set(obj, &l);
493+ iotlb_read_cr(obj, &cr);
494+ if (!iotlb_cr_valid(&cr))
495+ continue;
496+
497+ start = iotlb_cr_to_virt(&cr);
498+ bytes = iopgsz_to_bytes(cr.cam & 3);
499+
500+ if ((start <= da) && (da < start + bytes)) {
501+ dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
502+ __func__, start, da, bytes);
503+
504+ iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
505+ }
506+ }
507+ clk_disable(obj->clk);
508+
509+ if (i == obj->nr_tlb_entries)
510+ dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da);
511+}
512+EXPORT_SYMBOL_GPL(flush_iotlb_page);
513+
514+/**
515+ * flush_iotlb_range() - Clear an iommu tlb entries
516+ * @obj: target iommu
517+ * @start: iommu device virtual address(start)
518+ * @end: iommu device virtual address(end)
519+ *
520+ * Clear an iommu tlb entry which includes 'da' address.
521+ **/
522+void flush_iotlb_range(struct iommu *obj, u32 start, u32 end)
523+{
524+ u32 da = start;
525+
526+ while (da < end) {
527+ flush_iotlb_page(obj, da);
528+ /* FIXME: Optimize for multiple page size */
529+ da += IOPTE_SIZE;
530+ }
531+}
532+EXPORT_SYMBOL_GPL(flush_iotlb_range);
533+
534+/**
535+ * flush_iotlb_all() - Clear all iommu tlb entries
536+ * @obj: target iommu
537+ **/
538+void flush_iotlb_all(struct iommu *obj)
539+{
540+ struct iotlb_lock l;
541+
542+ clk_enable(obj->clk);
543+
544+ l.base = 0;
545+ l.vict = 0;
546+ iotlb_lock_set(obj, &l);
547+
548+ iommu_write_reg(obj, 1, MMU_GFLUSH);
549+
550+ clk_disable(obj->clk);
551+}
552+EXPORT_SYMBOL_GPL(flush_iotlb_all);
553+
554+/*
555+ * H/W pagetable operations
556+ */
557+static void flush_iopgd_range(u32 *first, u32 *last)
558+{
559+ /* FIXME: L2 cache should be taken care of if it exists */
560+ do {
561+ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pgd"
562+ : : "r" (first));
563+ first += L1_CACHE_BYTES / sizeof(*first);
564+ } while (first <= last);
565+}
566+
567+static void flush_iopte_range(u32 *first, u32 *last)
568+{
569+ /* FIXME: L2 cache should be taken care of if it exists */
570+ do {
571+ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pte"
572+ : : "r" (first));
573+ first += L1_CACHE_BYTES / sizeof(*first);
574+ } while (first <= last);
575+}
576+
577+static void iopte_free(u32 *iopte)
578+{
579+ /* Note: freed iopte's must be clean ready for re-use */
580+ kmem_cache_free(iopte_cachep, iopte);
581+}
582+
583+static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da)
584+{
585+ u32 *iopte;
586+
587+ /* a table has already existed */
588+ if (*iopgd)
589+ goto pte_ready;
590+
591+ /*
592+ * do the allocation outside the page table lock
593+ */
594+ spin_unlock(&obj->page_table_lock);
595+ iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL);
596+ spin_lock(&obj->page_table_lock);
597+
598+ if (!*iopgd) {
599+ if (!iopte)
600+ return ERR_PTR(-ENOMEM);
601+
602+ *iopgd = virt_to_phys(iopte) | IOPGD_TABLE;
603+ flush_iopgd_range(iopgd, iopgd);
604+
605+ dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte);
606+ } else {
607+ /* We raced, free the reduniovant table */
608+ iopte_free(iopte);
609+ }
610+
611+pte_ready:
612+ iopte = iopte_offset(iopgd, da);
613+
614+ dev_vdbg(obj->dev,
615+ "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
616+ __func__, da, iopgd, *iopgd, iopte, *iopte);
617+
618+ return iopte;
619+}
620+
621+static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
622+{
623+ u32 *iopgd = iopgd_offset(obj, da);
624+
625+ *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
626+ flush_iopgd_range(iopgd, iopgd);
627+ return 0;
628+}
629+
630+static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
631+{
632+ u32 *iopgd = iopgd_offset(obj, da);
633+ int i;
634+
635+ for (i = 0; i < 16; i++)
636+ *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
637+ flush_iopgd_range(iopgd, iopgd + 15);
638+ return 0;
639+}
640+
641+static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot)
642+{
643+ u32 *iopgd = iopgd_offset(obj, da);
644+ u32 *iopte = iopte_alloc(obj, iopgd, da);
645+
646+ if (IS_ERR(iopte))
647+ return PTR_ERR(iopte);
648+
649+ *iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL;
650+ flush_iopte_range(iopte, iopte);
651+
652+ dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n",
653+ __func__, da, pa, iopte, *iopte);
654+
655+ return 0;
656+}
657+
658+static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
659+{
660+ u32 *iopgd = iopgd_offset(obj, da);
661+ u32 *iopte = iopte_alloc(obj, iopgd, da);
662+ int i;
663+
664+ if (IS_ERR(iopte))
665+ return PTR_ERR(iopte);
666+
667+ for (i = 0; i < 16; i++)
668+ *(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE;
669+ flush_iopte_range(iopte, iopte + 15);
670+ return 0;
671+}
672+
673+static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e)
674+{
675+ int (*fn)(struct iommu *, u32, u32, u32);
676+ u32 prot;
677+ int err;
678+
679+ if (!obj || !e)
680+ return -EINVAL;
681+
682+ switch (e->pgsz) {
683+ case MMU_CAM_PGSZ_16M:
684+ fn = iopgd_alloc_super;
685+ break;
686+ case MMU_CAM_PGSZ_1M:
687+ fn = iopgd_alloc_section;
688+ break;
689+ case MMU_CAM_PGSZ_64K:
690+ fn = iopte_alloc_large;
691+ break;
692+ case MMU_CAM_PGSZ_4K:
693+ fn = iopte_alloc_page;
694+ break;
695+ default:
696+ fn = NULL;
697+ BUG();
698+ break;
699+ }
700+
701+ prot = get_iopte_attr(e);
702+
703+ spin_lock(&obj->page_table_lock);
704+ err = fn(obj, e->da, e->pa, prot);
705+ spin_unlock(&obj->page_table_lock);
706+
707+ return err;
708+}
709+
710+#ifdef DEBUG
711+static void dump_tlb_entries(struct iommu *obj)
712+{
713+ int i;
714+ struct iotlb_lock l;
715+
716+ clk_enable(obj->clk);
717+
718+ pr_info("%8s %8s\n", "cam:", "ram:");
719+ pr_info("-----------------------------------------\n");
720+
721+ for (i = 0; i < obj->nr_tlb_entries; i++) {
722+ struct cr_regs cr;
723+ static char buf[4096];
724+
725+ iotlb_lock_get(obj, &l);
726+ l.vict = i;
727+ iotlb_lock_set(obj, &l);
728+ iotlb_read_cr(obj, &cr);
729+ if (!iotlb_cr_valid(&cr))
730+ continue;
731+
732+ memset(buf, 0, 4096);
733+ iotlb_dump_cr(obj, &cr, buf);
734+ pr_err("%s", buf);
735+ }
736+
737+ clk_disable(obj->clk);
738+}
739+#else
740+static inline void dump_tlb_entries(struct iommu *obj) {}
741+#endif
742+
743+/**
744+ * iopgtable_store_entry() - Make an iommu pte entry
745+ * @obj: target iommu
746+ * @e: an iommu tlb entry info
747+ **/
748+int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e)
749+{
750+ int err;
751+
752+ flush_iotlb_page(obj, e->da);
753+ err = iopgtable_store_entry_core(obj, e);
754+#ifdef USE_IOTLB
755+ if (!err)
756+ load_iotlb_entry(obj, e);
757+#endif
758+ return err;
759+}
760+EXPORT_SYMBOL_GPL(iopgtable_store_entry);
761+
762+/**
763+ * iopgtable_lookup_entry() - Lookup an iommu pte entry
764+ * @obj: target iommu
765+ * @da: iommu device virtual address
766+ * @ppgd: iommu pgd entry pointer to be returned
767+ * @ppte: iommu pte entry pointer to be returned
768+ **/
769+void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte)
770+{
771+ u32 *iopgd, *iopte = NULL;
772+
773+ iopgd = iopgd_offset(obj, da);
774+ if (!*iopgd)
775+ goto out;
776+
777+ if (*iopgd & IOPGD_TABLE)
778+ iopte = iopte_offset(iopgd, da);
779+out:
780+ *ppgd = iopgd;
781+ *ppte = iopte;
782+}
783+EXPORT_SYMBOL_GPL(iopgtable_lookup_entry);
784+
785+static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da)
786+{
787+ size_t bytes;
788+ u32 *iopgd = iopgd_offset(obj, da);
789+ int nent = 1;
790+
791+ if (!*iopgd)
792+ return 0;
793+
794+ if (*iopgd & IOPGD_TABLE) {
795+ int i;
796+ u32 *iopte = iopte_offset(iopgd, da);
797+
798+ bytes = IOPTE_SIZE;
799+ if (*iopte & IOPTE_LARGE) {
800+ nent *= 16;
801+ /* rewind to the 1st entry */
802+ iopte = (u32 *)((u32)iopte & IOLARGE_MASK);
803+ }
804+ bytes *= nent;
805+ memset(iopte, 0, nent * sizeof(*iopte));
806+ flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte));
807+
808+ /*
809+ * do table walk to check if this table is necessary or not
810+ */
811+ iopte = iopte_offset(iopgd, 0);
812+ for (i = 0; i < PTRS_PER_IOPTE; i++)
813+ if (iopte[i])
814+ goto out;
815+
816+ iopte_free(iopte);
817+ nent = 1; /* for the next L1 entry */
818+ } else {
819+ bytes = IOPGD_SIZE;
820+ if (*iopgd & IOPGD_SUPER) {
821+ nent *= 16;
822+ /* rewind to the 1st entry */
823+ iopgd = (u32 *)((u32)iopgd & IOSUPER_MASK);
824+ }
825+ bytes *= nent;
826+ }
827+ memset(iopgd, 0, nent * sizeof(*iopgd));
828+ flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd));
829+out:
830+ return bytes;
831+}
832+
833+/**
834+ * iopgtable_clear_entry() - Remove an iommu pte entry
835+ * @obj: target iommu
836+ * @da: iommu device virtual address
837+ **/
838+size_t iopgtable_clear_entry(struct iommu *obj, u32 da)
839+{
840+ size_t bytes;
841+
842+ spin_lock(&obj->page_table_lock);
843+
844+ bytes = iopgtable_clear_entry_core(obj, da);
845+ flush_iotlb_page(obj, da);
846+
847+ spin_unlock(&obj->page_table_lock);
848+
849+ return bytes;
850+}
851+EXPORT_SYMBOL_GPL(iopgtable_clear_entry);
852+
853+static void iopgtable_clear_entry_all(struct iommu *obj)
854+{
855+ int i;
856+
857+ spin_lock(&obj->page_table_lock);
858+
859+ for (i = 0; i < PTRS_PER_IOPGD; i++) {
860+ u32 da;
861+ u32 *iopgd;
862+
863+ da = i << IOPGD_SHIFT;
864+ iopgd = iopgd_offset(obj, da);
865+
866+ if (!*iopgd)
867+ continue;
868+
869+ if (*iopgd & IOPGD_TABLE)
870+ iopte_free(iopte_offset(iopgd, 0));
871+
872+ *iopgd = 0;
873+ flush_iopgd_range(iopgd, iopgd);
874+ }
875+
876+ flush_iotlb_all(obj);
877+
878+ spin_unlock(&obj->page_table_lock);
879+}
880+
881+/*
882+ * Device IOMMU generic operations
883+ */
884+static irqreturn_t iommu_fault_handler(int irq, void *data)
885+{
886+ u32 stat, da;
887+ u32 *iopgd, *iopte;
888+ int err = -EIO;
889+ struct iommu *obj = data;
890+
891+ /* Dynamic loading TLB or PTE */
892+ if (obj->isr)
893+ err = obj->isr(obj);
894+
895+ if (!err)
896+ return IRQ_HANDLED;
897+
898+ stat = iommu_report_fault(obj, &da);
899+ if (!stat)
900+ return IRQ_HANDLED;
901+
902+ iopgd = iopgd_offset(obj, da);
903+
904+ if (!(*iopgd & IOPGD_TABLE)) {
905+ dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
906+ da, iopgd, *iopgd);
907+ return IRQ_NONE;
908+ }
909+
910+ iopte = iopte_offset(iopgd, da);
911+
912+ dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
913+ __func__, da, iopgd, *iopgd, iopte, *iopte);
914+
915+ dump_tlb_entries(obj);
916+
917+ return IRQ_NONE;
918+}
919+
920+static int device_match_by_alias(struct device *dev, void *data)
921+{
922+ struct iommu *obj = to_iommu(dev);
923+ const char *name = data;
924+
925+ pr_debug("%s: %s %s\n", __func__, obj->name, name);
926+
927+ return strcmp(obj->name, name) == 0;
928+}
929+
930+/**
931+ * iommu_put() - Get iommu handler
932+ * @name: target iommu name
933+ **/
934+struct iommu *iommu_get(const char *name)
935+{
936+ int err = -ENOMEM;
937+ struct device *dev;
938+ struct iommu *obj;
939+
940+ dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
941+ device_match_by_alias);
942+ if (!dev)
943+ return ERR_PTR(-ENODEV);
944+
945+ obj = to_iommu(dev);
946+
947+ mutex_lock(&obj->iommu_lock);
948+
949+ if (obj->refcount++ == 0) {
950+ err = iommu_enable(obj);
951+ if (err)
952+ goto err_enable;
953+ flush_iotlb_all(obj);
954+ }
955+
956+ if (!try_module_get(obj->owner))
957+ goto err_module;
958+
959+ mutex_unlock(&obj->iommu_lock);
960+
961+ dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
962+ return obj;
963+
964+err_module:
965+ if (obj->refcount == 1)
966+ iommu_disable(obj);
967+err_enable:
968+ mutex_unlock(&obj->iommu_lock);
969+ return ERR_PTR(err);
970+}
971+EXPORT_SYMBOL_GPL(iommu_get);
972+
973+/**
974+ * iommu_put() - Put back iommu handler
975+ * @obj: target iommu
976+ **/
977+void iommu_put(struct iommu *obj)
978+{
979+ if (!obj && IS_ERR(obj))
980+ return;
981+
982+ mutex_lock(&obj->iommu_lock);
983+
984+ if (--obj->refcount == 0)
985+ iommu_disable(obj);
986+
987+ module_put(obj->owner);
988+
989+ mutex_unlock(&obj->iommu_lock);
990+
991+ dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
992+}
993+EXPORT_SYMBOL_GPL(iommu_put);
994+
995+/*
996+ * OMAP Device MMU(IOMMU) detection
997+ */
998+static int __devinit omap_iommu_probe(struct platform_device *pdev)
999+{
1000+ int err = -ENODEV;
1001+ void *p;
1002+ int irq;
1003+ struct iommu *obj;
1004+ struct resource *res;
1005+ struct iommu_platform_data *pdata = pdev->dev.platform_data;
1006+
1007+ if (pdev->num_resources != 2)
1008+ return -EINVAL;
1009+
1010+ obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
1011+ if (!obj)
1012+ return -ENOMEM;
1013+
1014+ obj->clk = clk_get(&pdev->dev, pdata->clk_name);
1015+ if (IS_ERR(obj->clk))
1016+ goto err_clk;
1017+
1018+ obj->nr_tlb_entries = pdata->nr_tlb_entries;
1019+ obj->name = pdata->name;
1020+ obj->dev = &pdev->dev;
1021+ obj->ctx = (void *)obj + sizeof(*obj);
1022+
1023+ mutex_init(&obj->iommu_lock);
1024+ mutex_init(&obj->mmap_lock);
1025+ spin_lock_init(&obj->page_table_lock);
1026+ INIT_LIST_HEAD(&obj->mmap);
1027+
1028+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1029+ if (!res) {
1030+ err = -ENODEV;
1031+ goto err_mem;
1032+ }
1033+ obj->regbase = ioremap(res->start, resource_size(res));
1034+ if (!obj->regbase) {
1035+ err = -ENOMEM;
1036+ goto err_mem;
1037+ }
1038+
1039+ res = request_mem_region(res->start, resource_size(res),
1040+ dev_name(&pdev->dev));
1041+ if (!res) {
1042+ err = -EIO;
1043+ goto err_mem;
1044+ }
1045+
1046+ irq = platform_get_irq(pdev, 0);
1047+ if (irq < 0) {
1048+ err = -ENODEV;
1049+ goto err_irq;
1050+ }
1051+ err = request_irq(irq, iommu_fault_handler, IRQF_SHARED,
1052+ dev_name(&pdev->dev), obj);
1053+ if (err < 0)
1054+ goto err_irq;
1055+ platform_set_drvdata(pdev, obj);
1056+
1057+ p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE));
1058+ if (!p) {
1059+ err = -ENOMEM;
1060+ goto err_pgd;
1061+ }
1062+ memset(p, 0, IOPGD_TABLE_SIZE);
1063+ clean_dcache_area(p, IOPGD_TABLE_SIZE);
1064+ obj->iopgd = p;
1065+
1066+ BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE));
1067+
1068+ dev_info(&pdev->dev, "%s registered\n", obj->name);
1069+ return 0;
1070+
1071+err_pgd:
1072+ free_irq(irq, obj);
1073+err_irq:
1074+ release_mem_region(res->start, resource_size(res));
1075+ iounmap(obj->regbase);
1076+err_mem:
1077+ clk_put(obj->clk);
1078+err_clk:
1079+ kfree(obj);
1080+ return err;
1081+}
1082+
1083+static int __devexit omap_iommu_remove(struct platform_device *pdev)
1084+{
1085+ int irq;
1086+ struct resource *res;
1087+ struct iommu *obj = platform_get_drvdata(pdev);
1088+
1089+ platform_set_drvdata(pdev, NULL);
1090+
1091+ iopgtable_clear_entry_all(obj);
1092+ free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE));
1093+
1094+ irq = platform_get_irq(pdev, 0);
1095+ free_irq(irq, obj);
1096+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1097+ release_mem_region(res->start, resource_size(res));
1098+ iounmap(obj->regbase);
1099+
1100+ clk_put(obj->clk);
1101+ dev_info(&pdev->dev, "%s removed\n", obj->name);
1102+ kfree(obj);
1103+ return 0;
1104+}
1105+
1106+static struct platform_driver omap_iommu_driver = {
1107+ .probe = omap_iommu_probe,
1108+ .remove = __devexit_p(omap_iommu_remove),
1109+ .driver = {
1110+ .name = "omap-iommu",
1111+ },
1112+};
1113+
1114+static void iopte_cachep_ctor(void *iopte)
1115+{
1116+ clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
1117+}
1118+
1119+static int __init omap_iommu_init(void)
1120+{
1121+ struct kmem_cache *p;
1122+ const unsigned long flags = SLAB_HWCACHE_ALIGN;
1123+
1124+ p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, 0, flags,
1125+ iopte_cachep_ctor);
1126+ if (!p)
1127+ return -ENOMEM;
1128+ iopte_cachep = p;
1129+
1130+ return platform_driver_register(&omap_iommu_driver);
1131+}
1132+module_init(omap_iommu_init);
1133+
1134+static void __exit omap_iommu_exit(void)
1135+{
1136+ kmem_cache_destroy(iopte_cachep);
1137+
1138+ platform_driver_unregister(&omap_iommu_driver);
1139+}
1140+module_exit(omap_iommu_exit);
1141+
1142+MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives");
1143+MODULE_ALIAS("platform:omap-iommu");
1144+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
1145+MODULE_LICENSE("GPL v2");
1146diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h
1147new file mode 100644
1148index 0000000..37dac43
1149--- /dev/null
1150+++ b/arch/arm/plat-omap/iopgtable.h
1151@@ -0,0 +1,72 @@
1152+/*
1153+ * omap iommu: pagetable definitions
1154+ *
1155+ * Copyright (C) 2008-2009 Nokia Corporation
1156+ *
1157+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
1158+ *
1159+ * This program is free software; you can redistribute it and/or modify
1160+ * it under the terms of the GNU General Public License version 2 as
1161+ * published by the Free Software Foundation.
1162+ */
1163+
1164+#ifndef __PLAT_OMAP_IOMMU_H
1165+#define __PLAT_OMAP_IOMMU_H
1166+
1167+#define IOPGD_SHIFT 20
1168+#define IOPGD_SIZE (1 << IOPGD_SHIFT)
1169+#define IOPGD_MASK (~(IOPGD_SIZE - 1))
1170+#define IOSECTION_MASK IOPGD_MASK
1171+#define PTRS_PER_IOPGD (1 << (32 - IOPGD_SHIFT))
1172+#define IOPGD_TABLE_SIZE (PTRS_PER_IOPGD * sizeof(u32))
1173+
1174+#define IOSUPER_SIZE (IOPGD_SIZE << 4)
1175+#define IOSUPER_MASK (~(IOSUPER_SIZE - 1))
1176+
1177+#define IOPTE_SHIFT 12
1178+#define IOPTE_SIZE (1 << IOPTE_SHIFT)
1179+#define IOPTE_MASK (~(IOPTE_SIZE - 1))
1180+#define IOPAGE_MASK IOPTE_MASK
1181+#define PTRS_PER_IOPTE (1 << (IOPGD_SHIFT - IOPTE_SHIFT))
1182+#define IOPTE_TABLE_SIZE (PTRS_PER_IOPTE * sizeof(u32))
1183+
1184+#define IOLARGE_SIZE (IOPTE_SIZE << 4)
1185+#define IOLARGE_MASK (~(IOLARGE_SIZE - 1))
1186+
1187+#define IOPGD_TABLE (1 << 0)
1188+#define IOPGD_SECTION (2 << 0)
1189+#define IOPGD_SUPER (1 << 18 | 2 << 0)
1190+
1191+#define IOPTE_SMALL (2 << 0)
1192+#define IOPTE_LARGE (1 << 0)
1193+
1194+#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1))
1195+#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da))
1196+
1197+#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1))
1198+#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd)))
1199+
1200+#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
1201+#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da))
1202+
1203+static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
1204+ u32 flags)
1205+{
1206+ memset(e, 0, sizeof(*e));
1207+
1208+ e->da = da;
1209+ e->pa = pa;
1210+ e->valid = 1;
1211+ /* FIXME: add OMAP1 support */
1212+ e->pgsz = flags & MMU_CAM_PGSZ_MASK;
1213+ e->endian = flags & MMU_RAM_ENDIAN_MASK;
1214+ e->elsz = flags & MMU_RAM_ELSZ_MASK;
1215+ e->mixed = flags & MMU_RAM_MIXED_MASK;
1216+
1217+ return iopgsz_to_bytes(e->pgsz);
1218+}
1219+
1220+#define to_iommu(dev) \
1221+ (struct iommu *)platform_get_drvdata(to_platform_device(dev))
1222+
1223+#endif /* __PLAT_OMAP_IOMMU_H */
1224--
12251.5.6.5
1226
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch
new file mode 100644
index 0000000000..d5f78dd14e
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0002-omap-iommu-omap2-architecture-specific-functions.patch
@@ -0,0 +1,453 @@
1From c79d7959c45f40e47520aa6acd54c19094754787 Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Mon, 26 Jan 2009 15:13:45 +0200
4Subject: [PATCH] omap iommu: omap2 architecture specific functions
5
6The structure 'arch_mmu' accommodates the difference between omap1 and
7omap2/3.
8
9This patch provides omap2/3 specific functions
10
11Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
12---
13 arch/arm/mach-omap2/iommu2.c | 326 ++++++++++++++++++++++++++++++
14 arch/arm/plat-omap/include/mach/iommu2.h | 94 +++++++++
15 2 files changed, 420 insertions(+), 0 deletions(-)
16 create mode 100644 arch/arm/mach-omap2/iommu2.c
17 create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h
18
19diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
20new file mode 100644
21index 0000000..88a44f1
22--- /dev/null
23+++ b/arch/arm/mach-omap2/iommu2.c
24@@ -0,0 +1,326 @@
25+/*
26+ * omap iommu: omap2/3 architecture specific functions
27+ *
28+ * Copyright (C) 2008-2009 Nokia Corporation
29+ *
30+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>,
31+ * Paul Mundt and Toshihiro Kobayashi
32+ *
33+ * This program is free software; you can redistribute it and/or modify
34+ * it under the terms of the GNU General Public License version 2 as
35+ * published by the Free Software Foundation.
36+ */
37+
38+#include <linux/err.h>
39+#include <linux/device.h>
40+#include <linux/jiffies.h>
41+#include <linux/module.h>
42+#include <linux/stringify.h>
43+
44+#include <asm/io.h>
45+
46+#include <mach/iommu.h>
47+#include <mach/iommu2.h>
48+
49+/*
50+ * omap2 architecture specific register bit definitions
51+ */
52+#define IOMMU_ARCH_VERSION 0x00000011
53+
54+/* SYSCONF */
55+#define MMU_SYS_IDLE_SHIFT 3
56+#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT)
57+#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT)
58+#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT)
59+#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT)
60+
61+#define MMU_SYS_SOFTRESET (1 << 1)
62+#define MMU_SYS_AUTOIDLE 1
63+
64+/* SYSSTATUS */
65+#define MMU_SYS_RESETDONE 1
66+
67+/* IRQSTATUS & IRQENABLE */
68+#define MMU_IRQ_MULTIHITFAULT (1 << 4)
69+#define MMU_IRQ_TABLEWALKFAULT (1 << 3)
70+#define MMU_IRQ_EMUMISS (1 << 2)
71+#define MMU_IRQ_TRANSLATIONFAULT (1 << 1)
72+#define MMU_IRQ_TLBMISS (1 << 0)
73+#define MMU_IRQ_MASK \
74+ (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \
75+ MMU_IRQ_TRANSLATIONFAULT)
76+
77+/* MMU_CNTL */
78+#define MMU_CNTL_SHIFT 1
79+#define MMU_CNTL_MASK (7 << MMU_CNTL_SHIFT)
80+#define MMU_CNTL_EML_TLB (1 << 3)
81+#define MMU_CNTL_TWL_EN (1 << 2)
82+#define MMU_CNTL_MMU_EN (1 << 1)
83+
84+#define get_cam_va_mask(pgsz) \
85+ (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 : \
86+ ((pgsz) == MMU_CAM_PGSZ_1M) ? 0xfff00000 : \
87+ ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \
88+ ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0)
89+
90+static int omap2_iommu_enable(struct iommu *obj)
91+{
92+ u32 l, pa;
93+ unsigned long timeout;
94+
95+ if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K))
96+ return -EINVAL;
97+
98+ pa = virt_to_phys(obj->iopgd);
99+ if (!IS_ALIGNED(pa, SZ_16K))
100+ return -EINVAL;
101+
102+ iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG);
103+
104+ timeout = jiffies + msecs_to_jiffies(20);
105+ do {
106+ l = iommu_read_reg(obj, MMU_SYSSTATUS);
107+ if (l & MMU_SYS_RESETDONE)
108+ break;
109+ } while (time_after(jiffies, timeout));
110+
111+ if (!(l & MMU_SYS_RESETDONE)) {
112+ dev_err(obj->dev, "can't take mmu out of reset\n");
113+ return -ENODEV;
114+ }
115+
116+ l = iommu_read_reg(obj, MMU_REVISION);
117+ dev_info(obj->dev, "%s: version %d.%d\n", obj->name,
118+ (l >> 4) & 0xf, l & 0xf);
119+
120+ l = iommu_read_reg(obj, MMU_SYSCONFIG);
121+ l &= ~MMU_SYS_IDLE_MASK;
122+ l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE);
123+ iommu_write_reg(obj, l, MMU_SYSCONFIG);
124+
125+ iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE);
126+ iommu_write_reg(obj, pa, MMU_TTB);
127+
128+ l = iommu_read_reg(obj, MMU_CNTL);
129+ l &= ~MMU_CNTL_MASK;
130+ l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN);
131+ iommu_write_reg(obj, l, MMU_CNTL);
132+
133+ return 0;
134+}
135+
136+static void omap2_iommu_disable(struct iommu *obj)
137+{
138+ u32 l = iommu_read_reg(obj, MMU_CNTL);
139+
140+ l &= ~MMU_CNTL_MASK;
141+ iommu_write_reg(obj, l, MMU_CNTL);
142+ iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG);
143+
144+ dev_dbg(obj->dev, "%s is shutting down\n", obj->name);
145+}
146+
147+static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
148+{
149+ int i;
150+ u32 stat, da;
151+ const char *err_msg[] = {
152+ "tlb miss",
153+ "translation fault",
154+ "emulation miss",
155+ "table walk fault",
156+ "multi hit fault",
157+ };
158+
159+ stat = iommu_read_reg(obj, MMU_IRQSTATUS);
160+ stat &= MMU_IRQ_MASK;
161+ if (!stat)
162+ return 0;
163+
164+ da = iommu_read_reg(obj, MMU_FAULT_AD);
165+ *ra = da;
166+
167+ dev_err(obj->dev, "%s:\tda:%08x ", __func__, da);
168+
169+ for (i = 0; i < ARRAY_SIZE(err_msg); i++) {
170+ if (stat & (1 << i))
171+ printk("%s ", err_msg[i]);
172+ }
173+ printk("\n");
174+
175+ iommu_write_reg(obj, stat, MMU_IRQSTATUS);
176+ return stat;
177+}
178+
179+static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
180+{
181+ cr->cam = iommu_read_reg(obj, MMU_READ_CAM);
182+ cr->ram = iommu_read_reg(obj, MMU_READ_RAM);
183+}
184+
185+static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr)
186+{
187+ iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM);
188+ iommu_write_reg(obj, cr->ram, MMU_RAM);
189+}
190+
191+static u32 omap2_cr_to_virt(struct cr_regs *cr)
192+{
193+ u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK;
194+ u32 mask = get_cam_va_mask(cr->cam & page_size);
195+
196+ return cr->cam & mask;
197+}
198+
199+static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
200+{
201+ struct cr_regs *cr;
202+
203+ if (e->da & ~(get_cam_va_mask(e->pgsz))) {
204+ dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__,
205+ e->da);
206+ return ERR_PTR(-EINVAL);
207+ }
208+
209+ cr = kmalloc(sizeof(*cr), GFP_KERNEL);
210+ if (!cr)
211+ return ERR_PTR(-ENOMEM);
212+
213+ cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz;
214+ cr->ram = e->pa | e->endian | e->elsz | e->mixed;
215+
216+ return cr;
217+}
218+
219+static inline int omap2_cr_valid(struct cr_regs *cr)
220+{
221+ return cr->cam & MMU_CAM_V;
222+}
223+
224+static u32 omap2_get_pte_attr(struct iotlb_entry *e)
225+{
226+ u32 attr;
227+
228+ attr = e->mixed << 5;
229+ attr |= e->endian;
230+ attr |= e->elsz >> 3;
231+ attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6);
232+
233+ return attr;
234+}
235+
236+static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
237+{
238+ char *p = buf;
239+
240+ /* FIXME: Need more detail analysis of cam/ram */
241+ p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram);
242+
243+ return p - buf;
244+}
245+
246+#define pr_reg(name) \
247+ p += sprintf(p, "%20s: %08x\n", \
248+ __stringify(name), iommu_read_reg(obj, MMU_##name));
249+
250+static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf)
251+{
252+ char *p = buf;
253+
254+ pr_reg(REVISION);
255+ pr_reg(SYSCONFIG);
256+ pr_reg(SYSSTATUS);
257+ pr_reg(IRQSTATUS);
258+ pr_reg(IRQENABLE);
259+ pr_reg(WALKING_ST);
260+ pr_reg(CNTL);
261+ pr_reg(FAULT_AD);
262+ pr_reg(TTB);
263+ pr_reg(LOCK);
264+ pr_reg(LD_TLB);
265+ pr_reg(CAM);
266+ pr_reg(RAM);
267+ pr_reg(GFLUSH);
268+ pr_reg(FLUSH_ENTRY);
269+ pr_reg(READ_CAM);
270+ pr_reg(READ_RAM);
271+ pr_reg(EMU_FAULT_AD);
272+
273+ return p - buf;
274+}
275+
276+static void omap2_iommu_save_ctx(struct iommu *obj)
277+{
278+ int i;
279+ u32 *p = obj->ctx;
280+
281+ for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
282+ p[i] = iommu_read_reg(obj, i * sizeof(u32));
283+ dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
284+ }
285+
286+ BUG_ON(p[0] != IOMMU_ARCH_VERSION);
287+}
288+
289+static void omap2_iommu_restore_ctx(struct iommu *obj)
290+{
291+ int i;
292+ u32 *p = obj->ctx;
293+
294+ for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
295+ iommu_write_reg(obj, p[i], i * sizeof(u32));
296+ dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
297+ }
298+
299+ BUG_ON(p[0] != IOMMU_ARCH_VERSION);
300+}
301+
302+static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
303+{
304+ e->da = cr->cam & MMU_CAM_VATAG_MASK;
305+ e->pa = cr->ram & MMU_RAM_PADDR_MASK;
306+ e->valid = cr->cam & MMU_CAM_V;
307+ e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK;
308+ e->endian = cr->ram & MMU_RAM_ENDIAN_MASK;
309+ e->elsz = cr->ram & MMU_RAM_ELSZ_MASK;
310+ e->mixed = cr->ram & MMU_RAM_MIXED;
311+}
312+
313+static const struct iommu_functions omap2_iommu_ops = {
314+ .version = IOMMU_ARCH_VERSION,
315+
316+ .enable = omap2_iommu_enable,
317+ .disable = omap2_iommu_disable,
318+ .fault_isr = omap2_iommu_fault_isr,
319+
320+ .tlb_read_cr = omap2_tlb_read_cr,
321+ .tlb_load_cr = omap2_tlb_load_cr,
322+
323+ .cr_to_e = omap2_cr_to_e,
324+ .cr_to_virt = omap2_cr_to_virt,
325+ .alloc_cr = omap2_alloc_cr,
326+ .cr_valid = omap2_cr_valid,
327+ .dump_cr = omap2_dump_cr,
328+
329+ .get_pte_attr = omap2_get_pte_attr,
330+
331+ .save_ctx = omap2_iommu_save_ctx,
332+ .restore_ctx = omap2_iommu_restore_ctx,
333+ .dump_ctx = omap2_iommu_dump_ctx,
334+};
335+
336+static int __init omap2_iommu_init(void)
337+{
338+ return install_iommu_arch(&omap2_iommu_ops);
339+}
340+module_init(omap2_iommu_init);
341+
342+static void __exit omap2_iommu_exit(void)
343+{
344+ uninstall_iommu_arch(&omap2_iommu_ops);
345+}
346+module_exit(omap2_iommu_exit);
347+
348+MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi");
349+MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions");
350+MODULE_LICENSE("GPL v2");
351diff --git a/arch/arm/plat-omap/include/mach/iommu2.h b/arch/arm/plat-omap/include/mach/iommu2.h
352new file mode 100644
353index 0000000..d746047
354--- /dev/null
355+++ b/arch/arm/plat-omap/include/mach/iommu2.h
356@@ -0,0 +1,94 @@
357+/*
358+ * omap iommu: omap2 architecture specific definitions
359+ *
360+ * Copyright (C) 2008-2009 Nokia Corporation
361+ *
362+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
363+ *
364+ * This program is free software; you can redistribute it and/or modify
365+ * it under the terms of the GNU General Public License version 2 as
366+ * published by the Free Software Foundation.
367+ */
368+
369+#ifndef __MACH_IOMMU2_H
370+#define __MACH_IOMMU2_H
371+
372+/*
373+ * MMU Register offsets
374+ */
375+#define MMU_REVISION 0x00
376+#define MMU_SYSCONFIG 0x10
377+#define MMU_SYSSTATUS 0x14
378+#define MMU_IRQSTATUS 0x18
379+#define MMU_IRQENABLE 0x1c
380+#define MMU_WALKING_ST 0x40
381+#define MMU_CNTL 0x44
382+#define MMU_FAULT_AD 0x48
383+#define MMU_TTB 0x4c
384+#define MMU_LOCK 0x50
385+#define MMU_LD_TLB 0x54
386+#define MMU_CAM 0x58
387+#define MMU_RAM 0x5c
388+#define MMU_GFLUSH 0x60
389+#define MMU_FLUSH_ENTRY 0x64
390+#define MMU_READ_CAM 0x68
391+#define MMU_READ_RAM 0x6c
392+#define MMU_EMU_FAULT_AD 0x70
393+
394+#define MMU_REG_SIZE 256
395+
396+/*
397+ * MMU Register bit definitions
398+ */
399+#define MMU_LOCK_BASE_SHIFT 10
400+#define MMU_LOCK_BASE_MASK (0x1f << MMU_LOCK_BASE_SHIFT)
401+#define MMU_LOCK_BASE(x) \
402+ ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT)
403+
404+#define MMU_LOCK_VICT_SHIFT 4
405+#define MMU_LOCK_VICT_MASK (0x1f << MMU_LOCK_VICT_SHIFT)
406+#define MMU_LOCK_VICT(x) \
407+ ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT)
408+
409+#define MMU_CAM_VATAG_SHIFT 12
410+#define MMU_CAM_VATAG_MASK \
411+ ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT)
412+#define MMU_CAM_P (1 << 3)
413+#define MMU_CAM_V (1 << 2)
414+#define MMU_CAM_PGSZ_MASK 3
415+#define MMU_CAM_PGSZ_1M (0 << 0)
416+#define MMU_CAM_PGSZ_64K (1 << 0)
417+#define MMU_CAM_PGSZ_4K (2 << 0)
418+#define MMU_CAM_PGSZ_16M (3 << 0)
419+
420+#define MMU_RAM_PADDR_SHIFT 12
421+#define MMU_RAM_PADDR_MASK \
422+ ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT)
423+#define MMU_RAM_ENDIAN_SHIFT 9
424+#define MMU_RAM_ENDIAN_MASK (1 << MMU_RAM_ENDIAN_SHIFT)
425+#define MMU_RAM_ENDIAN_BIG (1 << MMU_RAM_ENDIAN_SHIFT)
426+#define MMU_RAM_ENDIAN_LITTLE (0 << MMU_RAM_ENDIAN_SHIFT)
427+#define MMU_RAM_ELSZ_SHIFT 7
428+#define MMU_RAM_ELSZ_MASK (3 << MMU_RAM_ELSZ_SHIFT)
429+#define MMU_RAM_ELSZ_8 (0 << MMU_RAM_ELSZ_SHIFT)
430+#define MMU_RAM_ELSZ_16 (1 << MMU_RAM_ELSZ_SHIFT)
431+#define MMU_RAM_ELSZ_32 (2 << MMU_RAM_ELSZ_SHIFT)
432+#define MMU_RAM_ELSZ_NONE (3 << MMU_RAM_ELSZ_SHIFT)
433+#define MMU_RAM_MIXED_SHIFT 6
434+#define MMU_RAM_MIXED_MASK (1 << MMU_RAM_MIXED_SHIFT)
435+#define MMU_RAM_MIXED MMU_RAM_MIXED_MASK
436+
437+/*
438+ * register accessors
439+ */
440+static inline u32 iommu_read_reg(struct iommu *obj, size_t offs)
441+{
442+ return __raw_readl(obj->regbase + offs);
443+}
444+
445+static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs)
446+{
447+ __raw_writel(val, obj->regbase + offs);
448+}
449+
450+#endif /* __MACH_IOMMU2_H */
451--
4521.5.6.5
453
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch
new file mode 100644
index 0000000000..2954c47872
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0003-omap-iommu-omap3-iommu-device-registration.patch
@@ -0,0 +1,124 @@
1From 6a84082597dd322713c5d5951530e3eecb878ad4 Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Wed, 28 Jan 2009 21:32:04 +0200
4Subject: [PATCH] omap iommu: omap3 iommu device registration
5
6Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7---
8 arch/arm/mach-omap2/omap3-iommu.c | 104 +++++++++++++++++++++++++++++++++++++
9 1 files changed, 104 insertions(+), 0 deletions(-)
10 create mode 100644 arch/arm/mach-omap2/omap3-iommu.c
11
12diff --git a/arch/arm/mach-omap2/omap3-iommu.c b/arch/arm/mach-omap2/omap3-iommu.c
13new file mode 100644
14index 0000000..97481cc
15--- /dev/null
16+++ b/arch/arm/mach-omap2/omap3-iommu.c
17@@ -0,0 +1,104 @@
18+/*
19+ * omap iommu: omap3 device registration
20+ *
21+ * Copyright (C) 2008-2009 Nokia Corporation
22+ *
23+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
24+ *
25+ * This program is free software; you can redistribute it and/or modify
26+ * it under the terms of the GNU General Public License version 2 as
27+ * published by the Free Software Foundation.
28+ */
29+
30+#include <linux/platform_device.h>
31+#include <linux/io.h>
32+
33+#include <mach/iommu.h>
34+
35+#define OMAP3_MMU1_BASE 0x480bd400
36+#define OMAP3_MMU2_BASE 0x5d000000
37+#define OMAP3_MMU1_IRQ 24
38+#define OMAP3_MMU2_IRQ 28
39+
40+static struct resource omap3_iommu_res[] = {
41+ { /* Camera ISP MMU */
42+ .start = OMAP3_MMU1_BASE,
43+ .end = OMAP3_MMU1_BASE + MMU_REG_SIZE - 1,
44+ .flags = IORESOURCE_MEM,
45+ },
46+ {
47+ .start = OMAP3_MMU1_IRQ,
48+ .flags = IORESOURCE_IRQ,
49+ },
50+ { /* IVA2.2 MMU */
51+ .start = OMAP3_MMU2_BASE,
52+ .end = OMAP3_MMU2_BASE + MMU_REG_SIZE - 1,
53+ .flags = IORESOURCE_MEM,
54+ },
55+ {
56+ .start = OMAP3_MMU2_IRQ,
57+ .flags = IORESOURCE_IRQ,
58+ },
59+};
60+#define NR_IOMMU_RES (ARRAY_SIZE(omap3_iommu_res) / 2)
61+
62+static const struct iommu_platform_data omap3_iommu_pdata[] __initconst = {
63+ {
64+ .name = "isp",
65+ .nr_tlb_entries = 8,
66+ .clk_name = "cam_ick",
67+ },
68+ {
69+ .name = "iva2",
70+ .nr_tlb_entries = 32,
71+ .clk_name = "iva2_ck",
72+ },
73+};
74+#define NR_IOMMU_DEVICES ARRAY_SIZE(omap3_iommu_pdata)
75+
76+static struct platform_device *omap3_iommu_pdev[NR_IOMMU_DEVICES];
77+
78+static int __init omap3_iommu_init(void)
79+{
80+ int i, err;
81+
82+ for (i = 0; i < NR_IOMMU_DEVICES; i++) {
83+ struct platform_device *pdev;
84+
85+ pdev = platform_device_alloc("omap-iommu", i + 1);
86+ if (!pdev)
87+ goto err_out;
88+ err = platform_device_add_resources(pdev,
89+ &omap3_iommu_res[2 * i], NR_IOMMU_RES);
90+ if (err)
91+ goto err_out;
92+ err = platform_device_add_data(pdev, &omap3_iommu_pdata[i],
93+ sizeof(omap3_iommu_pdata[0]));
94+ if (err)
95+ goto err_out;
96+ err = platform_device_add(pdev);
97+ if (err)
98+ goto err_out;
99+ omap3_iommu_pdev[i] = pdev;
100+ }
101+ return 0;
102+
103+err_out:
104+ while (i--)
105+ platform_device_put(omap3_iommu_pdev[i]);
106+ return err;
107+}
108+module_init(omap3_iommu_init);
109+
110+static void __exit omap3_iommu_exit(void)
111+{
112+ int i;
113+
114+ for (i = 0; i < NR_IOMMU_DEVICES; i++)
115+ platform_device_unregister(omap3_iommu_pdev[i]);
116+}
117+module_exit(omap3_iommu_exit);
118+
119+MODULE_AUTHOR("Hiroshi DOYU");
120+MODULE_DESCRIPTION("omap iommu: omap3 device registration");
121+MODULE_LICENSE("GPL v2");
122--
1231.5.6.5
124
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch
new file mode 100644
index 0000000000..945778b943
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0004-omap-iommu-simple-virtual-address-space-management.patch
@@ -0,0 +1,1083 @@
1From 07365182b998af3dc2b79e822b8e21a3f50262c4 Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Wed, 28 Jan 2009 21:32:08 +0200
4Subject: [PATCH] omap iommu: simple virtual address space management
5
6This patch provides a device drivers, which has a omap iommu, with
7address mapping APIs between device virtual address(iommu), physical
8address and MPU virtual address.
9
10There are 4 possible patterns for iommu virtual address(iova/da) mapping.
11
12 |iova/ mapping iommu_ page
13 | da pa va (d)-(p)-(v) function type
14 ---------------------------------------------------------------------------
15 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s
16 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s
17 3 | c d c 1 - n - 1 _vmap() / _vunmap() s
18 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n*
19
20 'iova': device iommu virtual address
21 'da': alias of 'iova'
22 'pa': physical address
23 'va': mpu virtual address
24
25 'c': contiguous memory area
26 'd': dicontiguous memory area
27 'a': anonymous memory allocation
28 '()': optional feature
29
30 'n': a normal page(4KB) size is used.
31 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
32
33 '*': not yet, but feasible.
34
35Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
36---
37 arch/arm/include/asm/io.h | 6 +
38 arch/arm/mm/ioremap.c | 11 +
39 arch/arm/plat-omap/include/mach/iovmm.h | 94 ++++
40 arch/arm/plat-omap/iovmm.c | 891 +++++++++++++++++++++++++++++++
41 4 files changed, 1002 insertions(+), 0 deletions(-)
42 create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h
43 create mode 100644 arch/arm/plat-omap/iovmm.c
44
45diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
46index d2a59cf..cbdadfe 100644
47--- a/arch/arm/include/asm/io.h
48+++ b/arch/arm/include/asm/io.h
49@@ -75,6 +75,12 @@ extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int);
50 extern void __iounmap(volatile void __iomem *addr);
51
52 /*
53+ * external interface to remap single page with appropriate type
54+ */
55+extern int ioremap_page(unsigned long virt, unsigned long phys,
56+ unsigned int mtype);
57+
58+/*
59 * Bad read/write accesses...
60 */
61 extern void __readwrite_bug(const char *fn);
62diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
63index 9f88dd3..8441351 100644
64--- a/arch/arm/mm/ioremap.c
65+++ b/arch/arm/mm/ioremap.c
66@@ -110,6 +110,17 @@ static int remap_area_pages(unsigned long start, unsigned long pfn,
67 return err;
68 }
69
70+int ioremap_page(unsigned long virt, unsigned long phys, unsigned int mtype)
71+{
72+ const struct mem_type *type;
73+
74+ type = get_mem_type(mtype);
75+ if (!type)
76+ return -EINVAL;
77+
78+ return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, type);
79+}
80+EXPORT_SYMBOL(ioremap_page);
81
82 void __check_kvm_seq(struct mm_struct *mm)
83 {
84diff --git a/arch/arm/plat-omap/include/mach/iovmm.h b/arch/arm/plat-omap/include/mach/iovmm.h
85new file mode 100644
86index 0000000..bdc7ce5
87--- /dev/null
88+++ b/arch/arm/plat-omap/include/mach/iovmm.h
89@@ -0,0 +1,94 @@
90+/*
91+ * omap iommu: simple virtual address space management
92+ *
93+ * Copyright (C) 2008-2009 Nokia Corporation
94+ *
95+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
96+ *
97+ * This program is free software; you can redistribute it and/or modify
98+ * it under the terms of the GNU General Public License version 2 as
99+ * published by the Free Software Foundation.
100+ */
101+
102+#ifndef __IOMMU_MMAP_H
103+#define __IOMMU_MMAP_H
104+
105+struct iovm_struct {
106+ struct iommu *iommu; /* iommu object which this belongs to */
107+ u32 da_start; /* area definition */
108+ u32 da_end;
109+ u32 flags; /* IOVMF_: see below */
110+ struct list_head list; /* linked in ascending order */
111+ const struct sg_table *sgt; /* keep 'page' <-> 'da' mapping */
112+ void *va; /* mpu side mapped address */
113+};
114+
115+/*
116+ * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma)
117+ *
118+ * lower 16 bit is used for h/w and upper 16 bit is for s/w.
119+ */
120+#define IOVMF_SW_SHIFT 16
121+#define IOVMF_HW_SIZE (1 << IOVMF_SW_SHIFT)
122+#define IOVMF_HW_MASK (IOVMF_HW_SIZE - 1)
123+#define IOVMF_SW_MASK (~IOVMF_HW_MASK)UL
124+
125+/*
126+ * iovma: h/w flags derived from cam and ram attribute
127+ */
128+#define IOVMF_CAM_MASK (~((1 << 10) - 1))
129+#define IOVMF_RAM_MASK (~IOVMF_CAM_MASK)
130+
131+#define IOVMF_PGSZ_MASK (3 << 0)
132+#define IOVMF_PGSZ_1M MMU_CAM_PGSZ_1M
133+#define IOVMF_PGSZ_64K MMU_CAM_PGSZ_64K
134+#define IOVMF_PGSZ_4K MMU_CAM_PGSZ_4K
135+#define IOVMF_PGSZ_16M MMU_CAM_PGSZ_16M
136+
137+#define IOVMF_ENDIAN_MASK (1 << 9)
138+#define IOVMF_ENDIAN_BIG MMU_RAM_ENDIAN_BIG
139+#define IOVMF_ENDIAN_LITTLE MMU_RAM_ENDIAN_LITTLE
140+
141+#define IOVMF_ELSZ_MASK (3 << 7)
142+#define IOVMF_ELSZ_8 MMU_RAM_ELSZ_8
143+#define IOVMF_ELSZ_16 MMU_RAM_ELSZ_16
144+#define IOVMF_ELSZ_32 MMU_RAM_ELSZ_32
145+#define IOVMF_ELSZ_NONE MMU_RAM_ELSZ_NONE
146+
147+#define IOVMF_MIXED_MASK (1 << 6)
148+#define IOVMF_MIXED MMU_RAM_MIXED
149+
150+/*
151+ * iovma: s/w flags, used for mapping and umapping internally.
152+ */
153+#define IOVMF_MMIO (1 << IOVMF_SW_SHIFT)
154+#define IOVMF_ALLOC (2 << IOVMF_SW_SHIFT)
155+#define IOVMF_ALLOC_MASK (3 << IOVMF_SW_SHIFT)
156+
157+/* "superpages" is supported just with physically linear pages */
158+#define IOVMF_DISCONT (1 << (2 + IOVMF_SW_SHIFT))
159+#define IOVMF_LINEAR (2 << (2 + IOVMF_SW_SHIFT))
160+#define IOVMF_LINEAR_MASK (3 << (2 + IOVMF_SW_SHIFT))
161+
162+#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT))
163+#define IOVMF_DA_ANON (2 << (4 + IOVMF_SW_SHIFT))
164+#define IOVMF_DA_MASK (3 << (4 + IOVMF_SW_SHIFT))
165+
166+
167+extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
168+extern u32 iommu_vmap(struct iommu *obj, u32 da,
169+ const struct sg_table *sgt, u32 flags);
170+extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da);
171+extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes,
172+ u32 flags);
173+extern void iommu_vfree(struct iommu *obj, const u32 da);
174+extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
175+ u32 flags);
176+extern void iommu_kunmap(struct iommu *obj, u32 da);
177+extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes,
178+ u32 flags);
179+extern void iommu_kfree(struct iommu *obj, u32 da);
180+
181+extern void *da_to_va(struct iommu *obj, u32 da);
182+
183+#endif /* __IOMMU_MMAP_H */
184diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
185new file mode 100644
186index 0000000..6726d10
187--- /dev/null
188+++ b/arch/arm/plat-omap/iovmm.c
189@@ -0,0 +1,891 @@
190+/*
191+ * omap iommu: simple virtual address space management
192+ *
193+ * Copyright (C) 2008-2009 Nokia Corporation
194+ *
195+ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
196+ *
197+ * This program is free software; you can redistribute it and/or modify
198+ * it under the terms of the GNU General Public License version 2 as
199+ * published by the Free Software Foundation.
200+ */
201+
202+#include <linux/err.h>
203+#include <linux/vmalloc.h>
204+#include <linux/device.h>
205+#include <linux/scatterlist.h>
206+
207+#include <asm/io.h>
208+#include <asm/cacheflush.h>
209+
210+#include <mach/iommu.h>
211+#include <mach/iovmm.h>
212+
213+#include "iopgtable.h"
214+
215+/*
216+ * A device driver needs to create address mappings between:
217+ *
218+ * - iommu/device address
219+ * - physical address
220+ * - mpu virtual address
221+ *
222+ * There are 4 possible patterns for them:
223+ *
224+ * |iova/ mapping iommu_ page
225+ * | da pa va (d)-(p)-(v) function type
226+ * ---------------------------------------------------------------------------
227+ * 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s
228+ * 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s
229+ * 3 | c d c 1 - n - 1 _vmap() / _vunmap() s
230+ * 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n*
231+ *
232+ *
233+ * 'iova': device iommu virtual address
234+ * 'da': alias of 'iova'
235+ * 'pa': physical address
236+ * 'va': mpu virtual address
237+ *
238+ * 'c': contiguous memory area
239+ * 'd': dicontiguous memory area
240+ * 'a': anonymous memory allocation
241+ * '()': optional feature
242+ *
243+ * 'n': a normal page(4KB) size is used.
244+ * 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used.
245+ *
246+ * '*': not yet, but feasible.
247+ */
248+
249+static struct kmem_cache *iovm_area_cachep;
250+
251+/* return total bytes of sg buffers */
252+static size_t sgtable_len(const struct sg_table *sgt)
253+{
254+ unsigned int i, total = 0;
255+ struct scatterlist *sg;
256+
257+ if (!sgt)
258+ return 0;
259+
260+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
261+ size_t bytes;
262+
263+ bytes = sg_dma_len(sg);
264+
265+ if (!iopgsz_ok(bytes)) {
266+ pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
267+ __func__, i, bytes);
268+ return 0;
269+ }
270+
271+ total += bytes;
272+ }
273+
274+ return total;
275+}
276+#define sgtable_ok(x) (!!sgtable_len(x))
277+
278+/*
279+ * calculate the optimal number sg elements from total bytes based on
280+ * iommu superpages
281+ */
282+static unsigned int sgtable_nents(size_t bytes)
283+{
284+ int i;
285+ unsigned int nr_entries;
286+ const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, };
287+
288+ if (!IS_ALIGNED(bytes, PAGE_SIZE)) {
289+ pr_err("%s: wrong size %08x\n", __func__, bytes);
290+ return 0;
291+ }
292+
293+ nr_entries = 0;
294+ for (i = 0; i < ARRAY_SIZE(pagesize); i++) {
295+ if (bytes >= pagesize[i]) {
296+ nr_entries += (bytes / pagesize[i]);
297+ bytes %= pagesize[i];
298+ }
299+ }
300+ BUG_ON(bytes);
301+
302+ return nr_entries;
303+}
304+
305+/* allocate and initialize sg_table header(a kind of 'superblock') */
306+static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags)
307+{
308+ unsigned int nr_entries;
309+ int err;
310+ struct sg_table *sgt;
311+
312+ if (!bytes)
313+ return ERR_PTR(-EINVAL);
314+
315+ if (!IS_ALIGNED(bytes, PAGE_SIZE))
316+ return ERR_PTR(-EINVAL);
317+
318+ /* FIXME: IOVMF_DA_FIXED should support 'superpages' */
319+ if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) {
320+ nr_entries = sgtable_nents(bytes);
321+ if (!nr_entries)
322+ return ERR_PTR(-EINVAL);
323+ } else
324+ nr_entries = bytes / PAGE_SIZE;
325+
326+ sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
327+ if (!sgt)
328+ return ERR_PTR(-ENOMEM);
329+
330+ err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
331+ if (err)
332+ return ERR_PTR(err);
333+
334+ pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries);
335+
336+ return sgt;
337+}
338+
339+/* free sg_table header(a kind of superblock) */
340+static void sgtable_free(struct sg_table *sgt)
341+{
342+ if (!sgt)
343+ return;
344+
345+ sg_free_table(sgt);
346+ kfree(sgt);
347+
348+ pr_debug("%s: sgt:%p\n", __func__, sgt);
349+}
350+
351+/* map 'sglist' to a contiguous mpu virtual area and return 'va' */
352+static void *vmap_sg(const struct sg_table *sgt)
353+{
354+ u32 va;
355+ size_t total;
356+ unsigned int i;
357+ struct scatterlist *sg;
358+ struct vm_struct *new;
359+
360+ total = sgtable_len(sgt);
361+ if (!total)
362+ return ERR_PTR(-EINVAL);
363+
364+ new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END);
365+ if (!new)
366+ return ERR_PTR(-ENOMEM);
367+ va = (u32)new->addr;
368+
369+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
370+ size_t bytes;
371+ u32 pa;
372+ int err;
373+
374+ pa = sg_phys(sg);
375+ bytes = sg_dma_len(sg);
376+
377+ BUG_ON(bytes != PAGE_SIZE);
378+
379+ err = ioremap_page(va, pa, MT_DEVICE);
380+ if (err)
381+ goto err_out;
382+
383+ va += bytes;
384+ }
385+
386+ flush_cache_vmap(new->addr, total);
387+ return new->addr;
388+
389+err_out:
390+ WARN_ON(1); /* FIXME: cleanup some mpu mappings */
391+ vunmap(new->addr);
392+ return ERR_PTR(-EAGAIN);
393+}
394+
395+static inline void vunmap_sg(const void *va)
396+{
397+ vunmap(va);
398+}
399+
400+static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da)
401+{
402+ struct iovm_struct *tmp;
403+
404+ list_for_each_entry(tmp, &obj->mmap, list) {
405+ if ((da >= tmp->da_start) && (da < tmp->da_end)) {
406+ size_t len;
407+
408+ len = tmp->da_end - tmp->da_start;
409+
410+ dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n",
411+ __func__, tmp->da_start, da, tmp->da_end, len,
412+ tmp->flags);
413+
414+ return tmp;
415+ }
416+ }
417+
418+ return NULL;
419+}
420+
421+/**
422+ * find_iovm_area - find iovma which includes @da
423+ * @da: iommu device virtual address
424+ *
425+ * Find the existing iovma starting at @da
426+ */
427+struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da)
428+{
429+ struct iovm_struct *area;
430+
431+ mutex_lock(&obj->mmap_lock);
432+ area = __find_iovm_area(obj, da);
433+ mutex_unlock(&obj->mmap_lock);
434+
435+ return area;
436+}
437+EXPORT_SYMBOL_GPL(find_iovm_area);
438+
439+/*
440+ * This finds the hole(area) which fits the requested address and len
441+ * in iovmas mmap, and returns the new allocated iovma.
442+ */
443+static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
444+ size_t bytes, u32 flags)
445+{
446+ struct iovm_struct *new, *tmp;
447+ u32 start, prev_end, alignement;
448+
449+ if (!obj || !bytes)
450+ return ERR_PTR(-EINVAL);
451+
452+ start = da;
453+ alignement = PAGE_SIZE;
454+
455+ if (flags & IOVMF_DA_ANON) {
456+ /*
457+ * Reserve the first page for NULL
458+ */
459+ start = PAGE_SIZE;
460+ if (flags & IOVMF_LINEAR)
461+ alignement = iopgsz_max(bytes);
462+ start = roundup(start, alignement);
463+ }
464+
465+ tmp = NULL;
466+ if (list_empty(&obj->mmap))
467+ goto found;
468+
469+ prev_end = 0;
470+ list_for_each_entry(tmp, &obj->mmap, list) {
471+
472+ if ((prev_end <= start) && (start + bytes < tmp->da_start))
473+ goto found;
474+
475+ if (flags & IOVMF_DA_ANON)
476+ start = roundup(tmp->da_end, alignement);
477+
478+ prev_end = tmp->da_end;
479+ }
480+
481+ if ((start >= prev_end) && (ULONG_MAX - start >= bytes))
482+ goto found;
483+
484+ dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",
485+ __func__, da, bytes, flags);
486+
487+ return ERR_PTR(-EINVAL);
488+
489+found:
490+ new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL);
491+ if (!new)
492+ return ERR_PTR(-ENOMEM);
493+
494+ new->iommu = obj;
495+ new->da_start = start;
496+ new->da_end = start + bytes;
497+ new->flags = flags;
498+
499+ /*
500+ * keep ascending order of iovmas
501+ */
502+ if (tmp)
503+ list_add_tail(&new->list, &tmp->list);
504+ else
505+ list_add(&new->list, &obj->mmap);
506+
507+ dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n",
508+ __func__, new->da_start, start, new->da_end, bytes, flags);
509+
510+ return new;
511+}
512+
513+static void free_iovm_area(struct iommu *obj, struct iovm_struct *area)
514+{
515+ size_t bytes;
516+
517+ BUG_ON(!obj || !area);
518+
519+ bytes = area->da_end - area->da_start;
520+
521+ dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n",
522+ __func__, area->da_start, area->da_end, bytes, area->flags);
523+
524+ list_del(&area->list);
525+ kmem_cache_free(iovm_area_cachep, area);
526+}
527+
528+/**
529+ * da_to_va - convert (d) to (v)
530+ * @obj: objective iommu
531+ * @da: iommu device virtual address
532+ * @va: mpu virtual address
533+ *
534+ * Returns mpu virtual addr which corresponds to a given device virtual addr
535+ */
536+void *da_to_va(struct iommu *obj, u32 da)
537+{
538+ void *va = NULL;
539+ struct iovm_struct *area;
540+
541+ mutex_lock(&obj->mmap_lock);
542+
543+ area = __find_iovm_area(obj, da);
544+ if (!area) {
545+ dev_warn(obj->dev, "%s: no da area(%08x)\n", __func__, da);
546+ goto out;
547+ }
548+ va = area->va;
549+ mutex_unlock(&obj->mmap_lock);
550+out:
551+ return va;
552+}
553+EXPORT_SYMBOL_GPL(da_to_va);
554+
555+static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va)
556+{
557+ unsigned int i;
558+ struct scatterlist *sg;
559+ void *va = _va;
560+ void *va_end;
561+
562+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
563+ struct page *pg;
564+ const size_t bytes = PAGE_SIZE;
565+
566+ /*
567+ * iommu 'superpage' isn't supported with 'iommu_vmalloc()'
568+ */
569+ pg = vmalloc_to_page(va);
570+ BUG_ON(!pg);
571+ sg_set_page(sg, pg, bytes, 0);
572+
573+ va += bytes;
574+ }
575+
576+ va_end = _va + PAGE_SIZE * i;
577+ flush_cache_vmap(_va, va_end);
578+}
579+
580+static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
581+{
582+ /*
583+ * Actually this is not necessary at all, just exists for
584+ * consistency of the code readibility.
585+ */
586+ BUG_ON(!sgt);
587+}
588+
589+static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len)
590+{
591+ unsigned int i;
592+ struct scatterlist *sg;
593+ void *va;
594+
595+ va = phys_to_virt(pa);
596+
597+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
598+ size_t bytes;
599+
600+ bytes = iopgsz_max(len);
601+
602+ BUG_ON(!iopgsz_ok(bytes));
603+
604+ sg_set_buf(sg, phys_to_virt(pa), bytes);
605+ /*
606+ * 'pa' is cotinuous(linear).
607+ */
608+ pa += bytes;
609+ len -= bytes;
610+ }
611+ BUG_ON(len);
612+
613+ clean_dcache_area(va, len);
614+}
615+
616+static inline void sgtable_drain_kmalloc(struct sg_table *sgt)
617+{
618+ /*
619+ * Actually this is not necessary at all, just exists for
620+ * consistency of the code readibility
621+ */
622+ BUG_ON(!sgt);
623+}
624+
625+/* create 'da' <-> 'pa' mapping from 'sgt' */
626+static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
627+ const struct sg_table *sgt, u32 flags)
628+{
629+ int err;
630+ unsigned int i, j;
631+ struct scatterlist *sg;
632+ u32 da = new->da_start;
633+
634+ if (!obj || !new || !sgt)
635+ return -EINVAL;
636+
637+ BUG_ON(!sgtable_ok(sgt));
638+
639+ for_each_sg(sgt->sgl, sg, sgt->nents, i) {
640+ u32 pa;
641+ int pgsz;
642+ size_t bytes;
643+ struct iotlb_entry e;
644+
645+ pa = sg_phys(sg);
646+ bytes = sg_dma_len(sg);
647+
648+ flags &= ~IOVMF_PGSZ_MASK;
649+ pgsz = bytes_to_iopgsz(bytes);
650+ if (pgsz < 0)
651+ goto err_out;
652+ flags |= pgsz;
653+
654+ pr_debug("%s: [%d] %08x %08x(%x)\n", __func__,
655+ i, da, pa, bytes);
656+
657+ iotlb_init_entry(&e, da, pa, flags);
658+ err = iopgtable_store_entry(obj, &e);
659+ if (err)
660+ goto err_out;
661+
662+ da += bytes;
663+ }
664+ return 0;
665+
666+err_out:
667+ da = new->da_start;
668+
669+ for_each_sg(sgt->sgl, sg, i, j) {
670+ size_t bytes;
671+
672+ bytes = iopgtable_clear_entry(obj, da);
673+
674+ BUG_ON(!iopgsz_ok(bytes));
675+
676+ da += bytes;
677+ }
678+ return err;
679+}
680+
681+/* release 'da' <-> 'pa' mapping */
682+static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area)
683+{
684+ u32 start;
685+ size_t total = area->da_end - area->da_start;
686+
687+ BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE));
688+
689+ start = area->da_start;
690+ while (total > 0) {
691+ size_t bytes;
692+
693+ bytes = iopgtable_clear_entry(obj, start);
694+ if (bytes == 0)
695+ bytes = PAGE_SIZE;
696+ else
697+ dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n",
698+ __func__, start, bytes, area->flags);
699+
700+ BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE));
701+
702+ total -= bytes;
703+ start += bytes;
704+ }
705+ BUG_ON(total);
706+}
707+
708+/* template function for all unmapping */
709+static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
710+ void (*fn)(const void *), u32 flags)
711+{
712+ struct sg_table *sgt = NULL;
713+ struct iovm_struct *area;
714+
715+ BUG_ON(in_interrupt());
716+
717+ if (!IS_ALIGNED(da, PAGE_SIZE)) {
718+ dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
719+ return NULL;
720+ }
721+
722+ mutex_lock(&obj->mmap_lock);
723+
724+ area = __find_iovm_area(obj, da);
725+ if (!area) {
726+ dev_err(obj->dev, "%s: no da area(%08x)\n", __func__, da);
727+ goto out;
728+ }
729+
730+ if ((area->flags & flags) != flags) {
731+ dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__,
732+ area->flags);
733+ goto out;
734+ }
735+ sgt = (struct sg_table *)area->sgt;
736+
737+ unmap_iovm_area(obj, area);
738+
739+ fn(area->va);
740+
741+ dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__,
742+ area->da_start, da, area->da_end,
743+ area->da_end - area->da_start, area->flags);
744+
745+ free_iovm_area(obj, area);
746+out:
747+ mutex_unlock(&obj->mmap_lock);
748+
749+ return sgt;
750+}
751+
752+static u32 map_iommu_region(struct iommu *obj, u32 da,
753+ const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
754+{
755+ int err = -ENOMEM;
756+ struct iovm_struct *new;
757+
758+ mutex_lock(&obj->mmap_lock);
759+
760+ new = alloc_iovm_area(obj, da, bytes, flags);
761+ if (IS_ERR(new)) {
762+ err = PTR_ERR(new);
763+ goto err_alloc_iovma;
764+ }
765+ new->va = va;
766+ new->sgt = sgt;
767+
768+ if (map_iovm_area(obj, new, sgt, new->flags))
769+ goto err_map;
770+
771+ mutex_unlock(&obj->mmap_lock);
772+
773+ dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n",
774+ __func__, new->da_start, bytes, new->flags, va);
775+
776+ return new->da_start;
777+
778+err_map:
779+ free_iovm_area(obj, new);
780+err_alloc_iovma:
781+ mutex_unlock(&obj->mmap_lock);
782+ return err;
783+}
784+
785+static inline u32 __iommu_vmap(struct iommu *obj, u32 da,
786+ const struct sg_table *sgt, void *va, size_t bytes, u32 flags)
787+{
788+ return map_iommu_region(obj, da, sgt, va, bytes, flags);
789+}
790+
791+/**
792+ * iommu_vmap - (d)-(p)-(v) address mapper
793+ * @obj: objective iommu
794+ * @sgt: address of scatter gather table
795+ * @flags: iovma and page property
796+ *
797+ * Creates 1-n-1 mapping with given @sgt and returns @da.
798+ * All @sgt element must be io page size aligned.
799+ */
800+u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
801+ u32 flags)
802+{
803+ size_t bytes;
804+ void *va;
805+
806+ if (!obj || !obj->dev || !sgt)
807+ return -EINVAL;
808+
809+ bytes = sgtable_len(sgt);
810+ if (!bytes)
811+ return -EINVAL;
812+ bytes = PAGE_ALIGN(bytes);
813+
814+ va = vmap_sg(sgt);
815+ if (IS_ERR(va))
816+ return PTR_ERR(va);
817+
818+ flags &= IOVMF_HW_MASK;
819+ flags |= IOVMF_DISCONT;
820+ flags |= IOVMF_MMIO;
821+ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
822+
823+ da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
824+ if (IS_ERR_VALUE(da))
825+ vunmap_sg(va);
826+
827+ return da;
828+}
829+EXPORT_SYMBOL_GPL(iommu_vmap);
830+
831+/**
832+ * iommu_vunmap - release virtual mapping obtained by 'iommu_vmap()'
833+ * @obj: objective iommu
834+ * @da: iommu device virtual address
835+ *
836+ * Free the iommu virtually contiguous memory area starting at
837+ * @da, which was returned by 'iommu_vmap()'.
838+ */
839+struct sg_table *iommu_vunmap(struct iommu *obj, u32 da)
840+{
841+ struct sg_table *sgt;
842+ /*
843+ * 'sgt' is allocated before 'iommu_vmalloc()' is called.
844+ * Just returns 'sgt' to the caller to free
845+ */
846+ sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO);
847+ if (!sgt)
848+ dev_err(obj->dev, "%s: No sgt\n", __func__);
849+ return sgt;
850+}
851+EXPORT_SYMBOL_GPL(iommu_vunmap);
852+
853+/**
854+ * iommu_vmalloc - (d)-(p)-(v) address allocator and mapper
855+ * @obj: objective iommu
856+ * @da: contiguous iommu virtual memory
857+ * @bytes: allocation size
858+ * @flags: iovma and page property
859+ *
860+ * Allocate @bytes linearly and creates 1-n-1 mapping and returns
861+ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
862+ */
863+u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
864+{
865+ void *va;
866+ struct sg_table *sgt;
867+
868+ if (!obj || !obj->dev || !bytes)
869+ return -EINVAL;
870+
871+ bytes = PAGE_ALIGN(bytes);
872+
873+ va = vmalloc(bytes);
874+ if (!va)
875+ return -ENOMEM;
876+
877+ sgt = sgtable_alloc(bytes, flags);
878+ if (IS_ERR(sgt)) {
879+ da = PTR_ERR(sgt);
880+ goto err_sgt_alloc;
881+ }
882+ sgtable_fill_vmalloc(sgt, va);
883+
884+ flags &= IOVMF_HW_MASK;
885+ flags |= IOVMF_DISCONT;
886+ flags |= IOVMF_ALLOC;
887+ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
888+
889+ da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
890+ if (IS_ERR_VALUE(da))
891+ goto err_iommu_vmap;
892+
893+ return da;
894+
895+err_iommu_vmap:
896+ sgtable_drain_vmalloc(sgt);
897+ sgtable_free(sgt);
898+err_sgt_alloc:
899+ vfree(va);
900+ return da;
901+}
902+EXPORT_SYMBOL_GPL(iommu_vmalloc);
903+
904+/**
905+ * iommu_vfree - release memory allocated by 'iommu_vmalloc()'
906+ * @obj: objective iommu
907+ * @da: iommu device virtual address
908+ *
909+ * Frees the iommu virtually continuous memory area starting at
910+ * @da, as obtained from 'iommu_vmalloc()'.
911+ */
912+void iommu_vfree(struct iommu *obj, const u32 da)
913+{
914+ struct sg_table *sgt;
915+
916+ sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC);
917+ if (!sgt)
918+ dev_err(obj->dev, "%s: No sgt\n", __func__);
919+ sgtable_free(sgt);
920+}
921+EXPORT_SYMBOL_GPL(iommu_vfree);
922+
923+static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
924+ size_t bytes, u32 flags)
925+{
926+ struct sg_table *sgt;
927+
928+ sgt = sgtable_alloc(bytes, flags);
929+ if (IS_ERR(sgt))
930+ return PTR_ERR(sgt);
931+
932+ sgtable_fill_kmalloc(sgt, pa, bytes);
933+
934+ da = map_iommu_region(obj, da, sgt, va, bytes, flags);
935+ if (IS_ERR_VALUE(da)) {
936+ sgtable_drain_kmalloc(sgt);
937+ sgtable_free(sgt);
938+ }
939+
940+ return da;
941+}
942+
943+/**
944+ * iommu_kmap - (d)-(p)-(v) address mapper
945+ * @obj: objective iommu
946+ * @da: contiguous iommu virtual memory
947+ * @pa: contiguous physical memory
948+ * @flags: iovma and page property
949+ *
950+ * Creates 1-1-1 mapping and returns @da again, which can be
951+ * adjusted if 'IOVMF_DA_ANON' is set.
952+ */
953+u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
954+ u32 flags)
955+{
956+ void *va;
957+
958+ if (!obj || !obj->dev || !bytes)
959+ return -EINVAL;
960+
961+ bytes = PAGE_ALIGN(bytes);
962+
963+ va = ioremap(pa, bytes);
964+ if (!va)
965+ return -ENOMEM;
966+
967+ flags &= IOVMF_HW_MASK;
968+ flags |= IOVMF_LINEAR;
969+ flags |= IOVMF_MMIO;
970+ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
971+
972+ da = __iommu_kmap(obj, da, pa, va, bytes, flags);
973+ if (IS_ERR_VALUE(da))
974+ iounmap(va);
975+
976+ return da;
977+}
978+EXPORT_SYMBOL_GPL(iommu_kmap);
979+
980+/**
981+ * iommu_kunmap - release virtual mapping obtained by 'iommu_kmap()'
982+ * @obj: objective iommu
983+ * @da: iommu device virtual address
984+ *
985+ * Frees the iommu virtually contiguous memory area starting at
986+ * @da, which was passed to and was returned by'iommu_kmap()'.
987+ */
988+void iommu_kunmap(struct iommu *obj, u32 da)
989+{
990+ struct sg_table *sgt;
991+
992+ sgt = unmap_vm_area(obj, da, __iounmap, IOVMF_LINEAR | IOVMF_MMIO);
993+ if (!sgt)
994+ dev_err(obj->dev, "%s: No sgt\n", __func__);
995+ sgtable_free(sgt);
996+}
997+EXPORT_SYMBOL_GPL(iommu_kunmap);
998+
999+/**
1000+ * iommu_kmalloc - (d)-(p)-(v) address allocator and mapper
1001+ * @obj: objective iommu
1002+ * @da: contiguous iommu virtual memory
1003+ * @bytes: bytes for allocation
1004+ * @flags: iovma and page property
1005+ *
1006+ * Allocate @bytes linearly and creates 1-1-1 mapping and returns
1007+ * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
1008+ */
1009+u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
1010+{
1011+ void *va;
1012+ u32 pa;
1013+
1014+ if (!obj || !obj->dev || !bytes)
1015+ return -EINVAL;
1016+
1017+ bytes = PAGE_ALIGN(bytes);
1018+
1019+ va = kmalloc(bytes, GFP_KERNEL | GFP_DMA);
1020+ if (!va)
1021+ return -ENOMEM;
1022+ pa = virt_to_phys(va);
1023+
1024+ flags &= IOVMF_HW_MASK;
1025+ flags |= IOVMF_LINEAR;
1026+ flags |= IOVMF_ALLOC;
1027+ flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
1028+
1029+ da = __iommu_kmap(obj, da, pa, va, bytes, flags);
1030+ if (IS_ERR_VALUE(da))
1031+ kfree(va);
1032+
1033+ return da;
1034+}
1035+EXPORT_SYMBOL_GPL(iommu_kmalloc);
1036+
1037+/**
1038+ * iommu_kfree - release virtual mapping obtained by 'iommu_kmalloc()'
1039+ * @obj: objective iommu
1040+ * @da: iommu device virtual address
1041+ *
1042+ * Frees the iommu virtually contiguous memory area starting at
1043+ * @da, which was passed to and was returned by'iommu_kmalloc()'.
1044+ */
1045+void iommu_kfree(struct iommu *obj, u32 da)
1046+{
1047+ struct sg_table *sgt;
1048+
1049+ sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC);
1050+ if (!sgt)
1051+ dev_err(obj->dev, "%s: No sgt\n", __func__);
1052+ sgtable_free(sgt);
1053+}
1054+EXPORT_SYMBOL_GPL(iommu_kfree);
1055+
1056+
1057+static int __init iovmm_init(void)
1058+{
1059+ const unsigned long flags = SLAB_HWCACHE_ALIGN;
1060+ struct kmem_cache *p;
1061+
1062+ p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0,
1063+ flags, NULL);
1064+ if (!p)
1065+ return -ENOMEM;
1066+ iovm_area_cachep = p;
1067+
1068+ return 0;
1069+}
1070+module_init(iovmm_init);
1071+
1072+static void __exit iovmm_exit(void)
1073+{
1074+ kmem_cache_destroy(iovm_area_cachep);
1075+}
1076+module_exit(iovmm_exit);
1077+
1078+MODULE_DESCRIPTION("omap iommu: simple virtual address space management");
1079+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
1080+MODULE_LICENSE("GPL v2");
1081--
10821.5.6.5
1083
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000000..c0f9e4d9ac
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0005-omap-iommu-entries-for-Kconfig-and-Makefile.patch
@@ -0,0 +1,45 @@
1From 7de046a6a8446358001c38ad1d0b2b829ca0c98c Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Wed, 28 Jan 2009 21:32:08 +0200
4Subject: [PATCH] omap iommu: entries for Kconfig and Makefile
5
6Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7---
8 arch/arm/plat-omap/Kconfig | 8 ++++++++
9 arch/arm/plat-omap/Makefile | 1 +
10 2 files changed, 9 insertions(+), 0 deletions(-)
11
12diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
13index b16ae76..2090bb5 100644
14--- a/arch/arm/plat-omap/Kconfig
15+++ b/arch/arm/plat-omap/Kconfig
16@@ -176,6 +176,14 @@ config OMAP_MBOX_FWK
17 Say Y here if you want to use OMAP Mailbox framework support for
18 DSP, IVA1.0 and IVA2 in OMAP1/2/3.
19
20+config OMAP_IOMMU
21+ tristate "IOMMU support"
22+ depends on ARCH_OMAP
23+ default n
24+ help
25+ Say Y here if you want to use OMAP IOMMU support for IVA2 and
26+ Camera in OMAP3.
27+
28 choice
29 prompt "System timer"
30 default OMAP_MPU_TIMER
31diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
32index 3ebc09e..aa8f6df 100644
33--- a/arch/arm/plat-omap/Makefile
34+++ b/arch/arm/plat-omap/Makefile
35@@ -13,6 +13,7 @@ obj- :=
36 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
37
38 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
39+obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
40
41 obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
42 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
43--
441.5.6.5
45
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch
new file mode 100644
index 0000000000..54a7abfe85
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0006-omap-iommu-Don-t-try-BUG_ON-in_interrupt.patch
@@ -0,0 +1,26 @@
1From b03f695e25bbdaa95a2cc87e15ee8592e7ca128d Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Feb 2009 18:01:29 +0200
4Subject: [PATCH] omap iommu: Don't try BUG_ON(in_interrupt())
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 arch/arm/plat-omap/iovmm.c | 2 --
9 1 files changed, 0 insertions(+), 2 deletions(-)
10
11diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
12index 6726d10..bdfbb09 100644
13--- a/arch/arm/plat-omap/iovmm.c
14+++ b/arch/arm/plat-omap/iovmm.c
15@@ -523,8 +523,6 @@ static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da,
16 struct sg_table *sgt = NULL;
17 struct iovm_struct *area;
18
19- BUG_ON(in_interrupt());
20-
21 if (!IS_ALIGNED(da, PAGE_SIZE)) {
22 dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da);
23 return NULL;
24--
251.5.6.5
26
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch
new file mode 100644
index 0000000000..d8ad0eb0b7
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0007-omap-iommu-We-support-chained-scatterlists-probabl.patch
@@ -0,0 +1,24 @@
1From 24f984f784cae1a4515fe1be8db1ac24cdf51e84 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Feb 2009 18:37:41 +0200
4Subject: [PATCH] omap iommu: We support chained scatterlists, probably. :)
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 arch/arm/include/asm/scatterlist.h | 2 ++
9 1 files changed, 2 insertions(+), 0 deletions(-)
10
11diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h
12index ca0a37d..393f8b8 100644
13--- a/arch/arm/include/asm/scatterlist.h
14+++ b/arch/arm/include/asm/scatterlist.h
15@@ -24,4 +24,6 @@ struct scatterlist {
16 #define sg_dma_address(sg) ((sg)->dma_address)
17 #define sg_dma_len(sg) ((sg)->length)
18
19+#define ARCH_HAS_SG_CHAIN
20+
21 #endif /* _ASMARM_SCATTERLIST_H */
22--
231.5.6.5
24
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000000..298e797c37
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/iommu/0008-omap2-iommu-entries-for-Kconfig-and-Makefile.patch
@@ -0,0 +1,29 @@
1From 3c65ff4a684d3e0f4d9c59e731975408452c3743 Mon Sep 17 00:00:00 2001
2From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3Date: Wed, 28 Jan 2009 21:32:09 +0200
4Subject: [PATCH] omap2 iommu: entries for Kconfig and Makefile
5
6Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7---
8 arch/arm/mach-omap2/Makefile | 5 +++++
9 1 files changed, 5 insertions(+), 0 deletions(-)
10
11diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
12index b44bb78..33b5aa8 100644
13--- a/arch/arm/mach-omap2/Makefile
14+++ b/arch/arm/mach-omap2/Makefile
15@@ -38,6 +38,11 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
16 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
17 mailbox_mach-objs := mailbox.o
18
19+iommu-y += iommu2.o
20+iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o
21+
22+obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)
23+
24 # Specific board support
25 obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
26 obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o board-h4-mmc.o
27--
281.5.6.5
29
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch
new file mode 100644
index 0000000000..e6e07d8afc
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0001-omap3isp-Add-ISP-main-driver-and-register-definitio.patch
@@ -0,0 +1,4625 @@
1From 77c99cd863b906c803c3dec08753c19bf9b67882 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add ISP main driver and register definitions
5
6TODO:
7
8- Release resoures in isp_probe() if something fails.
9
10- Implement a sensible generic interface so that the ISP can offer a
11 v4l2_subdev (like the v4l2-int-device slaves) interface towards the
12 camera driver.
13
14- Handle CSI1 and CSI2 error cases (currently unhandled?).
15
16- Fix H3A / HIST interrupt enabling / disabling.
17
18- Clean up the private ioctls.
19
20- Handle SBL overflows somehow.
21
22Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
23---
24 drivers/media/video/Makefile | 2 +
25 drivers/media/video/isp/Makefile | 12 +
26 drivers/media/video/isp/isp.c | 2547 ++++++++++++++++++++++++++++++++++++++
27 drivers/media/video/isp/isp.h | 318 +++++
28 drivers/media/video/isp/ispreg.h | 1674 +++++++++++++++++++++++++
29 5 files changed, 4553 insertions(+), 0 deletions(-)
30 create mode 100644 drivers/media/video/isp/Makefile
31 create mode 100644 drivers/media/video/isp/isp.c
32 create mode 100644 drivers/media/video/isp/isp.h
33 create mode 100644 drivers/media/video/isp/ispreg.h
34
35diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
36index 72f6d03..e654270 100644
37--- a/drivers/media/video/Makefile
38+++ b/drivers/media/video/Makefile
39@@ -106,6 +106,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
40 obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
41 obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
42
43+obj-y += isp/
44+
45 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
46
47 obj-$(CONFIG_USB_DABUSB) += dabusb.o
48diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
49new file mode 100644
50index 0000000..f14d617
51--- /dev/null
52+++ b/drivers/media/video/isp/Makefile
53@@ -0,0 +1,12 @@
54+# Makefile for OMAP3 ISP driver
55+
56+ifdef CONFIG_ARCH_OMAP3410
57+isp-mod-objs += \
58+ isp.o ispccdc.o
59+else
60+isp-mod-objs += \
61+ isp.o ispccdc.o ispmmu.o \
62+ isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
63+endif
64+
65+obj-$(CONFIG_VIDEO_OMAP3) += isp-mod.o
66diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
67new file mode 100644
68index 0000000..54c839b
69--- /dev/null
70+++ b/drivers/media/video/isp/isp.c
71@@ -0,0 +1,2547 @@
72+/*
73+ * isp.c
74+ *
75+ * Driver Library for ISP Control module in TI's OMAP3 Camera ISP
76+ * ISP interface and IRQ related APIs are defined here.
77+ *
78+ * Copyright (C) 2009 Texas Instruments.
79+ * Copyright (C) 2009 Nokia.
80+ *
81+ * Contributors:
82+ * Sameer Venkatraman <sameerv@ti.com>
83+ * Mohit Jalori <mjalori@ti.com>
84+ * Sergio Aguirre <saaguirre@ti.com>
85+ * Sakari Ailus <sakari.ailus@nokia.com>
86+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
87+ * Toni Leinonen <toni.leinonen@nokia.com>
88+ *
89+ * This package is free software; you can redistribute it and/or modify
90+ * it under the terms of the GNU General Public License version 2 as
91+ * published by the Free Software Foundation.
92+ *
93+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
94+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
95+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96+ */
97+
98+#include <asm/cacheflush.h>
99+
100+#include <linux/delay.h>
101+#include <linux/interrupt.h>
102+#include <linux/clk.h>
103+#include <linux/dma-mapping.h>
104+#include <linux/vmalloc.h>
105+#include <linux/platform_device.h>
106+
107+#include "isp.h"
108+#include "ispmmu.h"
109+#include "ispreg.h"
110+#include "ispccdc.h"
111+#include "isph3a.h"
112+#include "isphist.h"
113+#include "isp_af.h"
114+#include "isppreview.h"
115+#include "ispresizer.h"
116+#include "ispcsi2.h"
117+
118+static struct isp_device *omap3isp;
119+
120+static int isp_try_size(struct v4l2_pix_format *pix_input,
121+ struct v4l2_pix_format *pix_output);
122+
123+static void isp_save_ctx(void);
124+
125+static void isp_restore_ctx(void);
126+
127+static void isp_buf_init(void);
128+
129+/* List of image formats supported via OMAP ISP */
130+const static struct v4l2_fmtdesc isp_formats[] = {
131+ {
132+ .description = "UYVY, packed",
133+ .pixelformat = V4L2_PIX_FMT_UYVY,
134+ },
135+ {
136+ .description = "YUYV (YUV 4:2:2), packed",
137+ .pixelformat = V4L2_PIX_FMT_YUYV,
138+ },
139+ {
140+ .description = "Bayer10 (GrR/BGb)",
141+ .pixelformat = V4L2_PIX_FMT_SGRBG10,
142+ },
143+};
144+
145+/* ISP Crop capabilities */
146+static struct v4l2_rect ispcroprect;
147+static struct v4l2_rect cur_rect;
148+
149+/**
150+ * struct vcontrol - Video control structure.
151+ * @qc: V4L2 Query control structure.
152+ * @current_value: Current value of the control.
153+ */
154+static struct vcontrol {
155+ struct v4l2_queryctrl qc;
156+ int current_value;
157+} video_control[] = {
158+ {
159+ {
160+ .id = V4L2_CID_BRIGHTNESS,
161+ .type = V4L2_CTRL_TYPE_INTEGER,
162+ .name = "Brightness",
163+ .minimum = ISPPRV_BRIGHT_LOW,
164+ .maximum = ISPPRV_BRIGHT_HIGH,
165+ .step = ISPPRV_BRIGHT_STEP,
166+ .default_value = ISPPRV_BRIGHT_DEF,
167+ },
168+ .current_value = ISPPRV_BRIGHT_DEF,
169+ },
170+ {
171+ {
172+ .id = V4L2_CID_CONTRAST,
173+ .type = V4L2_CTRL_TYPE_INTEGER,
174+ .name = "Contrast",
175+ .minimum = ISPPRV_CONTRAST_LOW,
176+ .maximum = ISPPRV_CONTRAST_HIGH,
177+ .step = ISPPRV_CONTRAST_STEP,
178+ .default_value = ISPPRV_CONTRAST_DEF,
179+ },
180+ .current_value = ISPPRV_CONTRAST_DEF,
181+ },
182+ {
183+ {
184+ .id = V4L2_CID_COLORFX,
185+ .type = V4L2_CTRL_TYPE_MENU,
186+ .name = "Color Effects",
187+ .minimum = V4L2_COLORFX_NONE,
188+ .maximum = V4L2_COLORFX_SEPIA,
189+ .step = 1,
190+ .default_value = V4L2_COLORFX_NONE,
191+ },
192+ .current_value = V4L2_COLORFX_NONE,
193+ }
194+};
195+
196+static struct v4l2_querymenu video_menu[] = {
197+ {
198+ .id = V4L2_CID_COLORFX,
199+ .index = 0,
200+ .name = "None",
201+ },
202+ {
203+ .id = V4L2_CID_COLORFX,
204+ .index = 1,
205+ .name = "B&W",
206+ },
207+ {
208+ .id = V4L2_CID_COLORFX,
209+ .index = 2,
210+ .name = "Sepia",
211+ },
212+};
213+
214+struct isp_buf {
215+ dma_addr_t isp_addr;
216+ void (*complete)(struct videobuf_buffer *vb, void *priv);
217+ struct videobuf_buffer *vb;
218+ void *priv;
219+ u32 vb_state;
220+};
221+
222+#define ISP_BUFS_IS_FULL(bufs) \
223+ (((bufs)->queue + 1) % NUM_BUFS == (bufs)->done)
224+#define ISP_BUFS_IS_EMPTY(bufs) ((bufs)->queue == (bufs)->done)
225+#define ISP_BUFS_IS_LAST(bufs) \
226+ ((bufs)->queue == ((bufs)->done + 1) % NUM_BUFS)
227+#define ISP_BUFS_QUEUED(bufs) \
228+ ((((bufs)->done - (bufs)->queue + NUM_BUFS)) % NUM_BUFS)
229+#define ISP_BUF_DONE(bufs) ((bufs)->buf + (bufs)->done)
230+#define ISP_BUF_NEXT_DONE(bufs) \
231+ ((bufs)->buf + ((bufs)->done + 1) % NUM_BUFS)
232+#define ISP_BUF_QUEUE(bufs) ((bufs)->buf + (bufs)->queue)
233+#define ISP_BUF_MARK_DONE(bufs) \
234+ (bufs)->done = ((bufs)->done + 1) % NUM_BUFS;
235+#define ISP_BUF_MARK_QUEUED(bufs) \
236+ (bufs)->queue = ((bufs)->queue + 1) % NUM_BUFS;
237+
238+struct isp_bufs {
239+ dma_addr_t isp_addr_capture[VIDEO_MAX_FRAME];
240+ spinlock_t lock; /* For handling current buffer */
241+ /* queue full: (ispsg.queue + 1) % NUM_BUFS == ispsg.done
242+ queue empty: ispsg.queue == ispsg.done */
243+ struct isp_buf buf[NUM_BUFS];
244+ /* Next slot to queue a buffer. */
245+ int queue;
246+ /* Buffer that is being processed. */
247+ int done;
248+ /* Wait for this many hs_vs before anything else. */
249+ int wait_hs_vs;
250+};
251+
252+/**
253+ * struct ispirq - Structure for containing callbacks to be called in ISP ISR.
254+ * @isp_callbk: Array which stores callback functions, indexed by the type of
255+ * callback (8 possible types).
256+ * @isp_callbk_arg1: Pointer to array containing pointers to the first argument
257+ * to be passed to the requested callback function.
258+ * @isp_callbk_arg2: Pointer to array containing pointers to the second
259+ * argument to be passed to the requested callback function.
260+ *
261+ * This structure is used to contain all the callback functions related for
262+ * each callback type (CBK_CCDC_VD0, CBK_CCDC_VD1, CBK_PREV_DONE,
263+ * CBK_RESZ_DONE, CBK_MMU_ERR, CBK_H3A_AWB_DONE, CBK_HIST_DONE, CBK_HS_VS,
264+ * CBK_LSC_ISR).
265+ */
266+struct isp_irq {
267+ isp_callback_t isp_callbk[CBK_END];
268+ isp_vbq_callback_ptr isp_callbk_arg1[CBK_END];
269+ void *isp_callbk_arg2[CBK_END];
270+};
271+
272+/**
273+ * struct ispmodule - Structure for storing ISP sub-module information.
274+ * @isp_pipeline: Bit mask for submodules enabled within the ISP.
275+ * @applyCrop: Flag to do a crop operation when video buffer queue ISR is done
276+ * @pix: Structure containing the format and layout of the output image.
277+ * @ccdc_input_width: ISP CCDC module input image width.
278+ * @ccdc_input_height: ISP CCDC module input image height.
279+ * @ccdc_output_width: ISP CCDC module output image width.
280+ * @ccdc_output_height: ISP CCDC module output image height.
281+ * @preview_input_width: ISP Preview module input image width.
282+ * @preview_input_height: ISP Preview module input image height.
283+ * @preview_output_width: ISP Preview module output image width.
284+ * @preview_output_height: ISP Preview module output image height.
285+ * @resizer_input_width: ISP Resizer module input image width.
286+ * @resizer_input_height: ISP Resizer module input image height.
287+ * @resizer_output_width: ISP Resizer module output image width.
288+ * @resizer_output_height: ISP Resizer module output image height.
289+ */
290+struct isp_module {
291+ unsigned int isp_pipeline;
292+ int applyCrop;
293+ struct v4l2_pix_format pix;
294+ unsigned int ccdc_input_width;
295+ unsigned int ccdc_input_height;
296+ unsigned int ccdc_output_width;
297+ unsigned int ccdc_output_height;
298+ unsigned int preview_input_width;
299+ unsigned int preview_input_height;
300+ unsigned int preview_output_width;
301+ unsigned int preview_output_height;
302+ unsigned int resizer_input_width;
303+ unsigned int resizer_input_height;
304+ unsigned int resizer_output_width;
305+ unsigned int resizer_output_height;
306+};
307+
308+#define RAW_CAPTURE(isp) \
309+ (!((isp)->module.isp_pipeline & OMAP_ISP_PREVIEW))
310+
311+/**
312+ * struct isp - Structure for storing ISP Control module information
313+ * @lock: Spinlock to sync between isr and processes.
314+ * @isp_mutex: Semaphore used to get access to the ISP.
315+ * @ref_count: Reference counter.
316+ * @cam_ick: Pointer to ISP Interface clock.
317+ * @cam_fck: Pointer to ISP Functional clock.
318+ *
319+ * This structure is used to store the OMAP ISP Control Information.
320+ */
321+static struct isp {
322+ spinlock_t lock; /* For handling registered ISP callbacks */
323+ struct mutex isp_mutex; /* For handling ref_count field */
324+ int ref_count;
325+ struct clk *cam_ick;
326+ struct clk *cam_mclk;
327+ struct clk *csi2_fck;
328+ struct isp_interface_config *config;
329+ dma_addr_t tmp_buf;
330+ size_t tmp_buf_size;
331+ unsigned long tmp_buf_offset;
332+ struct isp_bufs bufs;
333+ struct isp_irq irq;
334+ struct isp_module module;
335+} isp_obj;
336+
337+/* Structure for saving/restoring ISP module registers */
338+static struct isp_reg isp_reg_list[] = {
339+ {OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
340+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_GRESET_LENGTH, 0},
341+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_REPLAY, 0},
342+ {OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
343+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
344+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_FRAME, 0},
345+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_DELAY, 0},
346+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_DELAY, 0},
347+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_DELAY, 0},
348+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_PSTRB_LENGTH, 0},
349+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_STRB_LENGTH, 0},
350+ {OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_SHUT_LENGTH, 0},
351+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_SYSCONFIG, 0},
352+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF_IRQENABLE, 0},
353+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_CTRL, 0},
354+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_CTRL, 0},
355+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_START, 0},
356+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_START, 0},
357+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_END, 0},
358+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_END, 0},
359+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_WINDOWSIZE, 0},
360+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_WINDOWSIZE, 0},
361+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF0_THRESHOLD, 0},
362+ {OMAP3_ISP_IOMEM_CBUFF, ISP_CBUFF1_THRESHOLD, 0},
363+ {0, ISP_TOK_TERM, 0}
364+};
365+
366+u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset)
367+{
368+ return __raw_readl(omap3isp->mmio_base[isp_mmio_range] + reg_offset);
369+}
370+EXPORT_SYMBOL(isp_reg_readl);
371+
372+void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
373+ u32 reg_offset)
374+{
375+ __raw_writel(reg_value,
376+ omap3isp->mmio_base[isp_mmio_range] + reg_offset);
377+}
378+EXPORT_SYMBOL(isp_reg_writel);
379+
380+/*
381+ *
382+ * V4L2 Handling
383+ *
384+ */
385+
386+/**
387+ * find_vctrl - Returns the index of the ctrl array of the requested ctrl ID.
388+ * @id: Requested control ID.
389+ *
390+ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
391+ * domain.
392+ **/
393+static int find_vctrl(int id)
394+{
395+ int i;
396+
397+ if (id < V4L2_CID_BASE)
398+ return -EDOM;
399+
400+ for (i = (ARRAY_SIZE(video_control) - 1); i >= 0; i--)
401+ if (video_control[i].qc.id == id)
402+ break;
403+
404+ if (i < 0)
405+ i = -EINVAL;
406+
407+ return i;
408+}
409+
410+static int find_next_vctrl(int id)
411+{
412+ int i;
413+ u32 best = (u32)-1;
414+
415+ for (i = 0; i < ARRAY_SIZE(video_control); i++) {
416+ if (video_control[i].qc.id > id &&
417+ (best == (u32)-1 ||
418+ video_control[i].qc.id <
419+ video_control[best].qc.id)) {
420+ best = i;
421+ }
422+ }
423+
424+ if (best == (u32)-1)
425+ return -EINVAL;
426+
427+ return best;
428+}
429+
430+/**
431+ * find_vmenu - Returns index of the menu array of the requested ctrl option.
432+ * @id: Requested control ID.
433+ * @index: Requested menu option index.
434+ *
435+ * Returns 0 if successful, -EINVAL if not found, or -EDOM if its out of
436+ * domain.
437+ **/
438+static int find_vmenu(int id, int index)
439+{
440+ int i;
441+
442+ if (id < V4L2_CID_BASE)
443+ return -EDOM;
444+
445+ for (i = (ARRAY_SIZE(video_menu) - 1); i >= 0; i--) {
446+ if (video_menu[i].id != id || video_menu[i].index != index)
447+ continue;
448+ return i;
449+ }
450+
451+ return -EINVAL;
452+}
453+
454+/**
455+ * isp_release_resources - Free ISP submodules
456+ **/
457+static void isp_release_resources(void)
458+{
459+ if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
460+ ispccdc_free();
461+
462+ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW)
463+ isppreview_free();
464+
465+ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER)
466+ ispresizer_free();
467+ return;
468+}
469+
470+static int isp_wait(int (*busy)(void), int wait_for_busy, int max_wait)
471+{
472+ int wait = 0;
473+
474+ if (max_wait == 0)
475+ max_wait = 10000; /* 10 ms */
476+
477+ while ((wait_for_busy && !busy())
478+ || (!wait_for_busy && busy())) {
479+ rmb();
480+ udelay(1);
481+ wait++;
482+ if (wait > max_wait) {
483+ printk(KERN_ALERT "%s: wait is too much\n", __func__);
484+ return -EBUSY;
485+ }
486+ }
487+ DPRINTK_ISPCTRL(KERN_ALERT "%s: wait %d\n", __func__, wait);
488+
489+ return 0;
490+}
491+
492+static int ispccdc_sbl_wait_idle(int max_wait)
493+{
494+ return isp_wait(ispccdc_sbl_busy, 0, max_wait);
495+}
496+
497+static void isp_enable_interrupts(int is_raw)
498+{
499+ isp_reg_writel(-1, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
500+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
501+ IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
502+ IRQ0ENABLE_HS_VS_IRQ |
503+ IRQ0ENABLE_CCDC_VD0_IRQ |
504+ IRQ0ENABLE_CCDC_VD1_IRQ);
505+
506+ if (is_raw)
507+ return;
508+
509+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
510+ IRQ0ENABLE_PRV_DONE_IRQ |
511+ IRQ0ENABLE_RSZ_DONE_IRQ);
512+
513+ return;
514+}
515+
516+static void isp_disable_interrupts(void)
517+{
518+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
519+ ~(IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ |
520+ IRQ0ENABLE_HS_VS_IRQ |
521+ IRQ0ENABLE_CCDC_VD0_IRQ |
522+ IRQ0ENABLE_CCDC_VD1_IRQ |
523+ IRQ0ENABLE_PRV_DONE_IRQ |
524+ IRQ0ENABLE_RSZ_DONE_IRQ));
525+}
526+
527+/**
528+ * isp_set_callback - Sets the callback for the ISP module done events.
529+ * @type: Type of the event for which callback is requested.
530+ * @callback: Method to be called as callback in the ISR context.
531+ * @arg1: First argument to be passed when callback is called in ISR.
532+ * @arg2: Second argument to be passed when callback is called in ISR.
533+ *
534+ * This function sets a callback function for a done event in the ISP
535+ * module, and enables the corresponding interrupt.
536+ **/
537+int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
538+ isp_vbq_callback_ptr arg1,
539+ void *arg2)
540+{
541+ unsigned long irqflags = 0;
542+
543+ if (callback == NULL) {
544+ DPRINTK_ISPCTRL("ISP_ERR : Null Callback\n");
545+ return -EINVAL;
546+ }
547+
548+ spin_lock_irqsave(&isp_obj.lock, irqflags);
549+ isp_obj.irq.isp_callbk[type] = callback;
550+ isp_obj.irq.isp_callbk_arg1[type] = arg1;
551+ isp_obj.irq.isp_callbk_arg2[type] = arg2;
552+ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
553+
554+ switch (type) {
555+ case CBK_H3A_AWB_DONE:
556+ isp_reg_writel(IRQ0ENABLE_H3A_AWB_DONE_IRQ,
557+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
558+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
559+ IRQ0ENABLE_H3A_AWB_DONE_IRQ);
560+ break;
561+ case CBK_H3A_AF_DONE:
562+ isp_reg_writel(IRQ0ENABLE_H3A_AF_DONE_IRQ,
563+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
564+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
565+ IRQ0ENABLE_H3A_AF_DONE_IRQ);
566+ break;
567+ case CBK_HIST_DONE:
568+ isp_reg_writel(IRQ0ENABLE_HIST_DONE_IRQ,
569+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
570+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
571+ IRQ0ENABLE_HIST_DONE_IRQ);
572+ break;
573+ case CBK_PREV_DONE:
574+ isp_reg_writel(IRQ0ENABLE_PRV_DONE_IRQ,
575+ OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
576+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
577+ IRQ0ENABLE_PRV_DONE_IRQ);
578+ break;
579+ default:
580+ break;
581+ }
582+
583+ return 0;
584+}
585+EXPORT_SYMBOL(isp_set_callback);
586+
587+/**
588+ * isp_unset_callback - Clears the callback for the ISP module done events.
589+ * @type: Type of the event for which callback to be cleared.
590+ *
591+ * This function clears a callback function for a done event in the ISP
592+ * module, and disables the corresponding interrupt.
593+ **/
594+int isp_unset_callback(enum isp_callback_type type)
595+{
596+ unsigned long irqflags = 0;
597+
598+ spin_lock_irqsave(&isp_obj.lock, irqflags);
599+ isp_obj.irq.isp_callbk[type] = NULL;
600+ isp_obj.irq.isp_callbk_arg1[type] = NULL;
601+ isp_obj.irq.isp_callbk_arg2[type] = NULL;
602+ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
603+
604+ switch (type) {
605+ case CBK_H3A_AWB_DONE:
606+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
607+ ~IRQ0ENABLE_H3A_AWB_DONE_IRQ);
608+ break;
609+ case CBK_H3A_AF_DONE:
610+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
611+ ~IRQ0ENABLE_H3A_AF_DONE_IRQ);
612+ break;
613+ case CBK_HIST_DONE:
614+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
615+ ~IRQ0ENABLE_HIST_DONE_IRQ);
616+ break;
617+ case CBK_CSIA:
618+ isp_csi2_irq_set(0);
619+ break;
620+ case CBK_CSIB:
621+ isp_reg_writel(IRQ0ENABLE_CSIB_IRQ, OMAP3_ISP_IOMEM_MAIN,
622+ ISP_IRQ0STATUS);
623+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
624+ IRQ0ENABLE_CSIB_IRQ);
625+ break;
626+ case CBK_PREV_DONE:
627+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
628+ ~IRQ0ENABLE_PRV_DONE_IRQ);
629+ break;
630+ default:
631+ break;
632+ }
633+
634+ return 0;
635+}
636+EXPORT_SYMBOL(isp_unset_callback);
637+
638+/**
639+ * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
640+ * @xclk: Desired frequency of the clock in Hz.
641+ * @xclksel: XCLK to configure (0 = A, 1 = B).
642+ *
643+ * Configures the specified MCLK divisor in the ISP timing control register
644+ * (TCTRL_CTRL) to generate the desired xclk clock value.
645+ *
646+ * Divisor = CM_CAM_MCLK_HZ / xclk
647+ *
648+ * Returns the final frequency that is actually being generated
649+ **/
650+u32 isp_set_xclk(u32 xclk, u8 xclksel)
651+{
652+ u32 divisor;
653+ u32 currentxclk;
654+
655+ if (xclk >= CM_CAM_MCLK_HZ) {
656+ divisor = ISPTCTRL_CTRL_DIV_BYPASS;
657+ currentxclk = CM_CAM_MCLK_HZ;
658+ } else if (xclk >= 2) {
659+ divisor = CM_CAM_MCLK_HZ / xclk;
660+ if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
661+ divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
662+ currentxclk = CM_CAM_MCLK_HZ / divisor;
663+ } else {
664+ divisor = xclk;
665+ currentxclk = 0;
666+ }
667+
668+ switch (xclksel) {
669+ case 0:
670+ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
671+ ~ISPTCTRL_CTRL_DIVA_MASK,
672+ divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
673+ DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclka set to %d Hz\n",
674+ currentxclk);
675+ break;
676+ case 1:
677+ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
678+ ~ISPTCTRL_CTRL_DIVB_MASK,
679+ divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
680+ DPRINTK_ISPCTRL("isp_set_xclk(): cam_xclkb set to %d Hz\n",
681+ currentxclk);
682+ break;
683+ default:
684+ DPRINTK_ISPCTRL("ISP_ERR: isp_set_xclk(): Invalid requested "
685+ "xclk. Must be 0 (A) or 1 (B)."
686+ "\n");
687+ return -EINVAL;
688+ }
689+
690+ return currentxclk;
691+}
692+EXPORT_SYMBOL(isp_set_xclk);
693+
694+/**
695+ * isp_power_settings - Sysconfig settings, for Power Management.
696+ * @isp_sysconfig: Structure containing the power settings for ISP to configure
697+ *
698+ * Sets the power settings for the ISP, and SBL bus.
699+ **/
700+static void isp_power_settings(int idle)
701+{
702+ if (idle) {
703+ isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
704+ (ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY <<
705+ ISP_SYSCONFIG_MIDLEMODE_SHIFT),
706+ OMAP3_ISP_IOMEM_MAIN,
707+ ISP_SYSCONFIG);
708+ if (omap_rev() == OMAP3430_REV_ES1_0) {
709+ isp_reg_writel(ISPCSI1_AUTOIDLE |
710+ (ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
711+ ISPCSI1_MIDLEMODE_SHIFT),
712+ OMAP3_ISP_IOMEM_CSI2A,
713+ ISP_CSIA_SYSCONFIG);
714+ isp_reg_writel(ISPCSI1_AUTOIDLE |
715+ (ISPCSI1_MIDLEMODE_SMARTSTANDBY <<
716+ ISPCSI1_MIDLEMODE_SHIFT),
717+ OMAP3_ISP_IOMEM_CCP2,
718+ ISP_CSIB_SYSCONFIG);
719+ }
720+ isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
721+ ISP_CTRL);
722+
723+ } else {
724+ isp_reg_writel(ISP_SYSCONFIG_AUTOIDLE |
725+ (ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY <<
726+ ISP_SYSCONFIG_MIDLEMODE_SHIFT),
727+ OMAP3_ISP_IOMEM_MAIN,
728+ ISP_SYSCONFIG);
729+ if (omap_rev() == OMAP3430_REV_ES1_0) {
730+ isp_reg_writel(ISPCSI1_AUTOIDLE |
731+ (ISPCSI1_MIDLEMODE_FORCESTANDBY <<
732+ ISPCSI1_MIDLEMODE_SHIFT),
733+ OMAP3_ISP_IOMEM_CSI2A,
734+ ISP_CSIA_SYSCONFIG);
735+
736+ isp_reg_writel(ISPCSI1_AUTOIDLE |
737+ (ISPCSI1_MIDLEMODE_FORCESTANDBY <<
738+ ISPCSI1_MIDLEMODE_SHIFT),
739+ OMAP3_ISP_IOMEM_CCP2,
740+ ISP_CSIB_SYSCONFIG);
741+ }
742+
743+ isp_reg_writel(ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
744+ ISP_CTRL);
745+ }
746+}
747+
748+#define BIT_SET(var, shift, mask, val) \
749+ do { \
750+ var = (var & ~(mask << shift)) \
751+ | (val << shift); \
752+ } while (0)
753+
754+static int isp_init_csi(struct isp_interface_config *config)
755+{
756+ u32 i = 0, val, reg;
757+ int format;
758+
759+ switch (config->u.csi.format) {
760+ case V4L2_PIX_FMT_SGRBG10:
761+ format = 0x16; /* RAW10+VP */
762+ break;
763+ case V4L2_PIX_FMT_SGRBG10DPCM8:
764+ format = 0x12; /* RAW8+DPCM10+VP */
765+ break;
766+ default:
767+ printk(KERN_ERR "isp_init_csi: bad csi format\n");
768+ return -EINVAL;
769+ }
770+
771+ /* Reset the CSI and wait for reset to complete */
772+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSCONFIG) |
773+ BIT(1),
774+ OMAP3_ISP_IOMEM_CCP2,
775+ ISPCSI1_SYSCONFIG);
776+ while (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
777+ BIT(0))) {
778+ udelay(10);
779+ if (i++ > 10)
780+ break;
781+ }
782+ if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_SYSSTATUS) &
783+ BIT(0))) {
784+ printk(KERN_WARNING
785+ "omap3_isp: timeout waiting for csi reset\n");
786+ }
787+
788+ /* ISPCSI1_CTRL */
789+ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
790+ val &= ~BIT(11); /* Enable VP only off ->
791+ extract embedded data to interconnect */
792+ BIT_SET(val, 8, 0x3, config->u.csi.vpclk); /* Video port clock */
793+/* val |= BIT(3); */ /* Wait for FEC before disabling interface */
794+ val |= BIT(2); /* I/O cell output is parallel
795+ (no effect, but errata says should be enabled
796+ for class 1/2) */
797+ val |= BIT(12); /* VP clock polarity to falling edge
798+ (needed or bad picture!) */
799+
800+ /* Data/strobe physical layer */
801+ BIT_SET(val, 1, 1, config->u.csi.signalling);
802+ BIT_SET(val, 10, 1, config->u.csi.strobe_clock_inv);
803+ val |= BIT(4); /* Magic bit to enable CSI1 and strobe mode */
804+ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
805+
806+ /* ISPCSI1_LCx_CTRL logical channel #0 */
807+ reg = ISPCSI1_LCx_CTRL(0); /* reg = ISPCSI1_CTRL1; */
808+ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
809+ /* Format = RAW10+VP or RAW8+DPCM10+VP*/
810+ BIT_SET(val, 3, 0x1f, format);
811+ /* Enable setting of frame regions of interest */
812+ BIT_SET(val, 1, 1, 1);
813+ BIT_SET(val, 2, 1, config->u.csi.crc);
814+ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
815+
816+ /* ISPCSI1_DAT_START for logical channel #0 */
817+ reg = ISPCSI1_LCx_DAT_START(0); /* reg = ISPCSI1_DAT_START; */
818+ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
819+ BIT_SET(val, 16, 0xfff, config->u.csi.data_start);
820+ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
821+
822+ /* ISPCSI1_DAT_SIZE for logical channel #0 */
823+ reg = ISPCSI1_LCx_DAT_SIZE(0); /* reg = ISPCSI1_DAT_SIZE; */
824+ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, reg);
825+ BIT_SET(val, 16, 0xfff, config->u.csi.data_size);
826+ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, reg);
827+
828+ /* Clear status bits for logical channel #0 */
829+ isp_reg_writel(0xFFF & ~BIT(6), OMAP3_ISP_IOMEM_CCP2,
830+ ISPCSI1_LC01_IRQSTATUS);
831+
832+ /* Enable CSI1 */
833+ val = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
834+ val |= BIT(0) | BIT(4);
835+ isp_reg_writel(val, OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL);
836+
837+ if (!(isp_reg_readl(OMAP3_ISP_IOMEM_CCP2, ISPCSI1_CTRL) & BIT(4))) {
838+ printk(KERN_WARNING "OMAP3 CSI1 bus not available\n");
839+ if (config->u.csi.signalling) /* Strobe mode requires CSI1 */
840+ return -EIO;
841+ }
842+
843+ return 0;
844+}
845+
846+/**
847+ * isp_configure_interface - Configures ISP Control I/F related parameters.
848+ * @config: Pointer to structure containing the desired configuration for the
849+ * ISP.
850+ *
851+ * Configures ISP control register (ISP_CTRL) with the values specified inside
852+ * the config structure. Controls:
853+ * - Selection of parallel or serial input to the preview hardware.
854+ * - Data lane shifter.
855+ * - Pixel clock polarity.
856+ * - 8 to 16-bit bridge at the input of CCDC module.
857+ * - HS or VS synchronization signal detection
858+ **/
859+int isp_configure_interface(struct isp_interface_config *config)
860+{
861+ u32 ispctrl_val = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
862+ int r;
863+
864+ isp_obj.config = config;
865+
866+ ispctrl_val &= ISPCTRL_SHIFT_MASK;
867+ ispctrl_val |= config->dataline_shift << ISPCTRL_SHIFT_SHIFT;
868+ ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
869+
870+ ispctrl_val &= ISPCTRL_PAR_SER_CLK_SEL_MASK;
871+
872+ isp_buf_init();
873+
874+ switch (config->ccdc_par_ser) {
875+ case ISP_PARLL:
876+ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
877+ ispctrl_val |= config->u.par.par_clk_pol
878+ << ISPCTRL_PAR_CLK_POL_SHIFT;
879+ ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
880+ ispctrl_val |= config->u.par.par_bridge
881+ << ISPCTRL_PAR_BRIDGE_SHIFT;
882+ break;
883+ case ISP_CSIA:
884+ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
885+ ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_BENDIAN;
886+
887+ isp_csi2_ctx_config_format(0, config->u.csi.format);
888+ isp_csi2_ctx_update(0, false);
889+
890+ if (config->u.csi.crc)
891+ isp_csi2_ctrl_config_ecc_enable(true);
892+
893+ isp_csi2_ctrl_config_vp_out_ctrl(config->u.csi.vpclk);
894+ isp_csi2_ctrl_config_vp_only_enable(true);
895+ isp_csi2_ctrl_config_vp_clk_enable(true);
896+ isp_csi2_ctrl_update(false);
897+
898+ isp_csi2_irq_complexio1_set(1);
899+ isp_csi2_irq_status_set(1);
900+ isp_csi2_irq_set(1);
901+
902+ isp_csi2_enable(1);
903+ mdelay(3);
904+ break;
905+ case ISP_CSIB:
906+ ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
907+ r = isp_init_csi(config);
908+ if (r)
909+ return r;
910+ break;
911+ case ISP_NONE:
912+ return 0;
913+ default:
914+ return -EINVAL;
915+ }
916+
917+ ispctrl_val &= ~ISPCTRL_SYNC_DETECT_VSRISE;
918+ ispctrl_val |= config->hsvs_syncdetect;
919+
920+ isp_reg_writel(ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
921+
922+ /* Set sensor specific fields in CCDC and Previewer module.*/
923+ isppreview_set_skip(config->prev_sph, config->prev_slv);
924+ ispccdc_set_wenlog(config->wenlog);
925+
926+ return 0;
927+}
928+EXPORT_SYMBOL(isp_configure_interface);
929+
930+static int isp_buf_process(struct isp_bufs *bufs);
931+
932+/**
933+ * omap34xx_isp_isr - Interrupt Service Routine for Camera ISP module.
934+ * @irq: Not used currently.
935+ * @ispirq_disp: Pointer to the object that is passed while request_irq is
936+ * called. This is the isp_obj.irq object containing info on the
937+ * callback.
938+ *
939+ * Handles the corresponding callback if plugged in.
940+ *
941+ * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
942+ * IRQ wasn't handled.
943+ **/
944+static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
945+{
946+ struct isp *isp = _isp;
947+ struct isp_irq *irqdis = &isp->irq;
948+ struct isp_bufs *bufs = &isp->bufs;
949+ unsigned long flags;
950+ u32 irqstatus = 0;
951+ unsigned long irqflags = 0;
952+ int wait_hs_vs = 0;
953+
954+ irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
955+ isp_reg_writel(irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
956+
957+ spin_lock_irqsave(&bufs->lock, flags);
958+ wait_hs_vs = bufs->wait_hs_vs;
959+ if (irqstatus & HS_VS && bufs->wait_hs_vs)
960+ bufs->wait_hs_vs--;
961+ spin_unlock_irqrestore(&bufs->lock, flags);
962+
963+ spin_lock_irqsave(&isp_obj.lock, irqflags);
964+ /*
965+ * We need to wait for the first HS_VS interrupt from CCDC.
966+ * Otherwise our frame (and everything else) might be bad.
967+ */
968+ if (wait_hs_vs)
969+ goto out_ignore_buff;
970+
971+ if (irqstatus & CCDC_VD0) {
972+ if (RAW_CAPTURE(&isp_obj))
973+ isp_buf_process(bufs);
974+ if (!ispccdc_busy())
975+ ispccdc_config_shadow_registers();
976+ }
977+
978+ if (irqstatus & PREV_DONE) {
979+ if (irqdis->isp_callbk[CBK_PREV_DONE])
980+ irqdis->isp_callbk[CBK_PREV_DONE](
981+ PREV_DONE,
982+ irqdis->isp_callbk_arg1[CBK_PREV_DONE],
983+ irqdis->isp_callbk_arg2[CBK_PREV_DONE]);
984+ else if (!RAW_CAPTURE(&isp_obj) && !ispresizer_busy()) {
985+ if (isp_obj.module.applyCrop) {
986+ ispresizer_applycrop();
987+ if (!ispresizer_busy())
988+ isp_obj.module.applyCrop = 0;
989+ }
990+ if (!isppreview_busy()) {
991+ ispresizer_enable(1);
992+ if (isppreview_busy()) {
993+ /* FIXME: locking! */
994+ ISP_BUF_DONE(bufs)->vb_state =
995+ VIDEOBUF_ERROR;
996+ printk(KERN_ERR "%s: can't stop"
997+ " preview\n", __func__);
998+ }
999+ }
1000+ if (!isppreview_busy())
1001+ isppreview_config_shadow_registers();
1002+ if (!isppreview_busy())
1003+ isph3a_update_wb();
1004+ }
1005+ }
1006+
1007+ if (irqstatus & RESZ_DONE) {
1008+ if (!RAW_CAPTURE(&isp_obj)) {
1009+ if (!ispresizer_busy())
1010+ ispresizer_config_shadow_registers();
1011+ isp_buf_process(bufs);
1012+ }
1013+ }
1014+
1015+ if (irqstatus & H3A_AWB_DONE) {
1016+ if (irqdis->isp_callbk[CBK_H3A_AWB_DONE])
1017+ irqdis->isp_callbk[CBK_H3A_AWB_DONE](
1018+ H3A_AWB_DONE,
1019+ irqdis->isp_callbk_arg1[CBK_H3A_AWB_DONE],
1020+ irqdis->isp_callbk_arg2[CBK_H3A_AWB_DONE]);
1021+ }
1022+
1023+ if (irqstatus & HIST_DONE) {
1024+ if (irqdis->isp_callbk[CBK_HIST_DONE])
1025+ irqdis->isp_callbk[CBK_HIST_DONE](
1026+ HIST_DONE,
1027+ irqdis->isp_callbk_arg1[CBK_HIST_DONE],
1028+ irqdis->isp_callbk_arg2[CBK_HIST_DONE]);
1029+ }
1030+
1031+ if (irqstatus & H3A_AF_DONE) {
1032+ if (irqdis->isp_callbk[CBK_H3A_AF_DONE])
1033+ irqdis->isp_callbk[CBK_H3A_AF_DONE](
1034+ H3A_AF_DONE,
1035+ irqdis->isp_callbk_arg1[CBK_H3A_AF_DONE],
1036+ irqdis->isp_callbk_arg2[CBK_H3A_AF_DONE]);
1037+ }
1038+
1039+
1040+out_ignore_buff:
1041+ if (irqstatus & LSC_PRE_ERR) {
1042+ struct isp_buf *buf = ISP_BUF_DONE(bufs);
1043+ /* Mark buffer faulty. */
1044+ buf->vb_state = VIDEOBUF_ERROR;
1045+ ispccdc_lsc_error_handler();
1046+ printk(KERN_ERR "%s: lsc prefetch error\n", __func__);
1047+ }
1048+
1049+ if (irqstatus & CSIA) {
1050+ struct isp_buf *buf = ISP_BUF_DONE(bufs);
1051+ isp_csi2_isr();
1052+ buf->vb_state = VIDEOBUF_ERROR;
1053+ }
1054+
1055+ if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
1056+ u32 ispcsi1_irqstatus;
1057+
1058+ ispcsi1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CCP2,
1059+ ISPCSI1_LC01_IRQSTATUS);
1060+ DPRINTK_ISPCTRL("%x\n", ispcsi1_irqstatus);
1061+ }
1062+
1063+ if (irqdis->isp_callbk[CBK_CATCHALL]) {
1064+ irqdis->isp_callbk[CBK_CATCHALL](
1065+ irqstatus,
1066+ irqdis->isp_callbk_arg1[CBK_CATCHALL],
1067+ irqdis->isp_callbk_arg2[CBK_CATCHALL]);
1068+ }
1069+
1070+ spin_unlock_irqrestore(&isp_obj.lock, irqflags);
1071+
1072+#if 1
1073+ {
1074+ static const struct {
1075+ int num;
1076+ char *name;
1077+ } bits[] = {
1078+ { 31, "HS_VS_IRQ" },
1079+ { 30, "SEC_ERR_IRQ" },
1080+ { 29, "OCP_ERR_IRQ" },
1081+ { 28, "MMU_ERR_IRQ" },
1082+ { 27, "res27" },
1083+ { 26, "res26" },
1084+ { 25, "OVF_IRQ" },
1085+ { 24, "RSZ_DONE_IRQ" },
1086+ { 23, "res23" },
1087+ { 22, "res22" },
1088+ { 21, "CBUFF_IRQ" },
1089+ { 20, "PRV_DONE_IRQ" },
1090+ { 19, "CCDC_LSC_PREFETCH_ERROR" },
1091+ { 18, "CCDC_LSC_PREFETCH_COMPLETED" },
1092+ { 17, "CCDC_LSC_DONE" },
1093+ { 16, "HIST_DONE_IRQ" },
1094+ { 15, "res15" },
1095+ { 14, "res14" },
1096+ { 13, "H3A_AWB_DONE_IRQ" },
1097+ { 12, "H3A_AF_DONE_IRQ" },
1098+ { 11, "CCDC_ERR_IRQ" },
1099+ { 10, "CCDC_VD2_IRQ" },
1100+ { 9, "CCDC_VD1_IRQ" },
1101+ { 8, "CCDC_VD0_IRQ" },
1102+ { 7, "res7" },
1103+ { 6, "res6" },
1104+ { 5, "res5" },
1105+ { 4, "CSIB_IRQ" },
1106+ { 3, "CSIB_LCM_IRQ" },
1107+ { 2, "res2" },
1108+ { 1, "res1" },
1109+ { 0, "CSIA_IRQ" },
1110+ };
1111+ int i;
1112+ for (i = 0; i < ARRAY_SIZE(bits); i++) {
1113+ if ((1 << bits[i].num) & irqstatus)
1114+ DPRINTK_ISPCTRL("%s ", bits[i].name);
1115+ }
1116+ DPRINTK_ISPCTRL("\n");
1117+ }
1118+#endif
1119+
1120+ return IRQ_HANDLED;
1121+}
1122+
1123+/* Device name, needed for resource tracking layer */
1124+struct device_driver camera_drv = {
1125+ .name = "camera"
1126+};
1127+
1128+struct device camera_dev = {
1129+ .driver = &camera_drv,
1130+};
1131+
1132+/**
1133+ * isp_tmp_buf_free - To free allocated 10MB memory
1134+ *
1135+ **/
1136+static void isp_tmp_buf_free(void)
1137+{
1138+ if (isp_obj.tmp_buf) {
1139+ ispmmu_vfree(isp_obj.tmp_buf);
1140+ isp_obj.tmp_buf = 0;
1141+ isp_obj.tmp_buf_size = 0;
1142+ }
1143+}
1144+
1145+/**
1146+ * isp_tmp_buf_alloc - To allocate a 10MB memory
1147+ *
1148+ **/
1149+static u32 isp_tmp_buf_alloc(size_t size)
1150+{
1151+ isp_tmp_buf_free();
1152+
1153+ printk(KERN_INFO "%s: allocating %d bytes\n", __func__, size);
1154+
1155+ isp_obj.tmp_buf = ispmmu_vmalloc(size);
1156+ if (IS_ERR((void *)isp_obj.tmp_buf)) {
1157+ printk(KERN_ERR "ispmmu_vmap mapping failed ");
1158+ return -ENOMEM;
1159+ }
1160+ isp_obj.tmp_buf_size = size;
1161+
1162+ isppreview_set_outaddr(isp_obj.tmp_buf);
1163+ ispresizer_set_inaddr(isp_obj.tmp_buf);
1164+
1165+ return 0;
1166+}
1167+
1168+/**
1169+ * isp_start - Starts ISP submodule
1170+ *
1171+ * Start the needed isp components assuming these components
1172+ * are configured correctly.
1173+ **/
1174+void isp_start(void)
1175+{
1176+ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
1177+ && is_isppreview_enabled())
1178+ isppreview_enable(1);
1179+
1180+ return;
1181+}
1182+EXPORT_SYMBOL(isp_start);
1183+
1184+#define ISP_STATISTICS_BUSY \
1185+ ()
1186+#define ISP_STOP_TIMEOUT msecs_to_jiffies(1000)
1187+static int __isp_disable_modules(int suspend)
1188+{
1189+ unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
1190+ int reset = 0;
1191+
1192+ /*
1193+ * We need to stop all the modules after CCDC first or they'll
1194+ * never stop since they may not get a full frame from CCDC.
1195+ */
1196+ if (suspend) {
1197+ isp_af_suspend();
1198+ isph3a_aewb_suspend();
1199+ isp_hist_suspend();
1200+ isppreview_suspend();
1201+ ispresizer_suspend();
1202+ } else {
1203+ isp_af_enable(0);
1204+ isph3a_aewb_enable(0);
1205+ isp_hist_enable(0);
1206+ isppreview_enable(0);
1207+ ispresizer_enable(0);
1208+ }
1209+
1210+ timeout = jiffies + ISP_STOP_TIMEOUT;
1211+ while (isp_af_busy()
1212+ || isph3a_aewb_busy()
1213+ || isp_hist_busy()
1214+ || isppreview_busy()
1215+ || ispresizer_busy()) {
1216+ if (time_after(jiffies, timeout)) {
1217+ printk(KERN_ERR "%s: can't stop non-ccdc modules\n",
1218+ __func__);
1219+ reset = 1;
1220+ break;
1221+ }
1222+ msleep(1);
1223+ }
1224+
1225+ /* Let's stop CCDC now. */
1226+ if (suspend)
1227+ /* This function supends lsc too */
1228+ ispccdc_suspend();
1229+ else {
1230+ ispccdc_enable_lsc(0);
1231+ ispccdc_enable(0);
1232+ }
1233+
1234+ timeout = jiffies + ISP_STOP_TIMEOUT;
1235+ while (ispccdc_busy()) {
1236+ if (time_after(jiffies, timeout)) {
1237+ printk(KERN_ERR "%s: can't stop ccdc\n", __func__);
1238+ reset = 1;
1239+ break;
1240+ }
1241+ msleep(1);
1242+ }
1243+
1244+ return reset;
1245+}
1246+
1247+static int isp_stop_modules(void)
1248+{
1249+ return __isp_disable_modules(0);
1250+}
1251+
1252+static int isp_suspend_modules(void)
1253+{
1254+ return __isp_disable_modules(1);
1255+}
1256+
1257+static void isp_resume_modules(void)
1258+{
1259+ ispresizer_resume();
1260+ isppreview_resume();
1261+ isp_hist_resume();
1262+ isph3a_aewb_resume();
1263+ isp_af_resume();
1264+ ispccdc_resume();
1265+}
1266+
1267+static void isp_reset(void)
1268+{
1269+ unsigned long timeout = 0;
1270+
1271+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
1272+ | ISP_SYSCONFIG_SOFTRESET,
1273+ OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
1274+ while (!(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS) & 0x1)) {
1275+ if (timeout++ > 10000) {
1276+ printk(KERN_ALERT "%s: cannot reset ISP\n", __func__);
1277+ break;
1278+ }
1279+ udelay(1);
1280+ }
1281+}
1282+
1283+/**
1284+ * isp_stop - Stops isp submodules
1285+ **/
1286+void isp_stop()
1287+{
1288+ int reset;
1289+
1290+ isp_disable_interrupts();
1291+ reset = isp_stop_modules();
1292+ isp_buf_init();
1293+ if (!reset)
1294+ return;
1295+
1296+ isp_save_ctx();
1297+ isp_reset();
1298+ isp_restore_ctx();
1299+}
1300+EXPORT_SYMBOL(isp_stop);
1301+
1302+static void isp_set_buf(struct isp_buf *buf)
1303+{
1304+ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER
1305+ && is_ispresizer_enabled())
1306+ ispresizer_set_outaddr(buf->isp_addr);
1307+ else if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC)
1308+ ispccdc_set_outaddr(buf->isp_addr);
1309+
1310+}
1311+
1312+/**
1313+ * isp_calc_pipeline - Sets pipeline depending of input and output pixel format
1314+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
1315+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
1316+ **/
1317+static u32 isp_calc_pipeline(struct v4l2_pix_format *pix_input,
1318+ struct v4l2_pix_format *pix_output)
1319+{
1320+ isp_release_resources();
1321+ if ((pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
1322+ || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
1323+ && pix_output->pixelformat != V4L2_PIX_FMT_SGRBG10) {
1324+ isp_obj.module.isp_pipeline =
1325+ OMAP_ISP_CCDC | OMAP_ISP_PREVIEW | OMAP_ISP_RESIZER;
1326+ ispccdc_request();
1327+ isppreview_request();
1328+ ispresizer_request();
1329+ ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP);
1330+ isppreview_config_datapath(PRV_RAW_CCDC, PREVIEW_MEM);
1331+ ispresizer_config_datapath(RSZ_MEM_YUV);
1332+ } else {
1333+ isp_obj.module.isp_pipeline = OMAP_ISP_CCDC;
1334+ ispccdc_request();
1335+ if (pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10
1336+ || pix_input->pixelformat == V4L2_PIX_FMT_SGRBG10DPCM8)
1337+ ispccdc_config_datapath(CCDC_RAW, CCDC_OTHERS_VP_MEM);
1338+ else
1339+ ispccdc_config_datapath(CCDC_YUV_SYNC,
1340+ CCDC_OTHERS_MEM);
1341+ }
1342+ return 0;
1343+}
1344+
1345+/**
1346+ * isp_config_pipeline - Configures the image size and ycpos for ISP submodules
1347+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
1348+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
1349+ *
1350+ * The configuration of ycpos depends on the output pixel format for both the
1351+ * Preview and Resizer submodules.
1352+ **/
1353+static void isp_config_pipeline(struct v4l2_pix_format *pix_input,
1354+ struct v4l2_pix_format *pix_output)
1355+{
1356+ ispccdc_config_size(isp_obj.module.ccdc_input_width,
1357+ isp_obj.module.ccdc_input_height,
1358+ isp_obj.module.ccdc_output_width,
1359+ isp_obj.module.ccdc_output_height);
1360+
1361+ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
1362+ isppreview_config_size(isp_obj.module.preview_input_width,
1363+ isp_obj.module.preview_input_height,
1364+ isp_obj.module.preview_output_width,
1365+ isp_obj.module.preview_output_height);
1366+ }
1367+
1368+ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
1369+ ispresizer_config_size(isp_obj.module.resizer_input_width,
1370+ isp_obj.module.resizer_input_height,
1371+ isp_obj.module.resizer_output_width,
1372+ isp_obj.module.resizer_output_height);
1373+ }
1374+
1375+ if (pix_output->pixelformat == V4L2_PIX_FMT_UYVY) {
1376+ isppreview_config_ycpos(YCPOS_YCrYCb);
1377+ if (is_ispresizer_enabled())
1378+ ispresizer_config_ycpos(0);
1379+ } else {
1380+ isppreview_config_ycpos(YCPOS_CrYCbY);
1381+ if (is_ispresizer_enabled())
1382+ ispresizer_config_ycpos(1);
1383+ }
1384+
1385+ return;
1386+}
1387+
1388+static void isp_buf_init(void)
1389+{
1390+ struct isp_bufs *bufs = &isp_obj.bufs;
1391+ int sg;
1392+
1393+ bufs->queue = 0;
1394+ bufs->done = 0;
1395+ bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
1396+ for (sg = 0; sg < NUM_BUFS; sg++) {
1397+ bufs->buf[sg].complete = NULL;
1398+ bufs->buf[sg].vb = NULL;
1399+ bufs->buf[sg].priv = NULL;
1400+ }
1401+}
1402+
1403+/**
1404+ * isp_vbq_sync - Walks the pages table and flushes the cache for
1405+ * each page.
1406+ **/
1407+static int isp_vbq_sync(struct videobuf_buffer *vb, int when)
1408+{
1409+ flush_cache_all();
1410+
1411+ return 0;
1412+}
1413+
1414+static int isp_buf_process(struct isp_bufs *bufs)
1415+{
1416+ struct isp_buf *buf = NULL;
1417+ unsigned long flags;
1418+ int last;
1419+
1420+ spin_lock_irqsave(&bufs->lock, flags);
1421+
1422+ if (ISP_BUFS_IS_EMPTY(bufs))
1423+ goto out;
1424+
1425+ if (RAW_CAPTURE(&isp_obj) && ispccdc_sbl_wait_idle(1000)) {
1426+ printk(KERN_ERR "ccdc %d won't become idle!\n",
1427+ RAW_CAPTURE(&isp_obj));
1428+ goto out;
1429+ }
1430+
1431+ /* We had at least one buffer in queue. */
1432+ buf = ISP_BUF_DONE(bufs);
1433+ last = ISP_BUFS_IS_LAST(bufs);
1434+
1435+ if (!last) {
1436+ /* Set new buffer address. */
1437+ isp_set_buf(ISP_BUF_NEXT_DONE(bufs));
1438+ } else {
1439+ /* Tell ISP not to write any of our buffers. */
1440+ isp_disable_interrupts();
1441+ if (RAW_CAPTURE(&isp_obj))
1442+ ispccdc_enable(0);
1443+ else
1444+ ispresizer_enable(0);
1445+ /*
1446+ * We must wait for the HS_VS since before that the
1447+ * CCDC may trigger interrupts even if it's not
1448+ * receiving a frame.
1449+ */
1450+ bufs->wait_hs_vs = isp_obj.config->wait_hs_vs;
1451+ }
1452+ if ((RAW_CAPTURE(&isp_obj) && ispccdc_busy())
1453+ || (!RAW_CAPTURE(&isp_obj) && ispresizer_busy())) {
1454+ /*
1455+ * Next buffer available: for the transfer to succeed, the
1456+ * CCDC (RAW capture) or resizer (YUV capture) must be idle
1457+ * for the duration of transfer setup. Bad things happen
1458+ * otherwise!
1459+ *
1460+ * Next buffer not available: if we fail to stop the
1461+ * ISP the buffer is probably going to be bad.
1462+ */
1463+ /* Mark this buffer faulty. */
1464+ buf->vb_state = VIDEOBUF_ERROR;
1465+ /* Mark next faulty, too, in case we have one. */
1466+ if (!last) {
1467+ ISP_BUF_NEXT_DONE(bufs)->vb_state =
1468+ VIDEOBUF_ERROR;
1469+ printk(KERN_ALERT "OUCH!!!\n");
1470+ } else {
1471+ printk(KERN_ALERT "Ouch!\n");
1472+ }
1473+ }
1474+
1475+ /* Mark the current buffer as done. */
1476+ ISP_BUF_MARK_DONE(bufs);
1477+
1478+ DPRINTK_ISPCTRL(KERN_ALERT "%s: finish %d mmu %p\n", __func__,
1479+ (bufs->done - 1 + NUM_BUFS) % NUM_BUFS,
1480+ (bufs->buf+((bufs->done - 1 + NUM_BUFS)
1481+ % NUM_BUFS))->isp_addr);
1482+
1483+out:
1484+ spin_unlock_irqrestore(&bufs->lock, flags);
1485+
1486+ if (buf != NULL) {
1487+ /*
1488+ * We want to dequeue a buffer from the video buffer
1489+ * queue. Let's do it!
1490+ */
1491+ isp_vbq_sync(buf->vb, DMA_FROM_DEVICE);
1492+ buf->vb->state = buf->vb_state;
1493+ buf->complete(buf->vb, buf->priv);
1494+ }
1495+
1496+ return 0;
1497+}
1498+
1499+int isp_buf_queue(struct videobuf_buffer *vb,
1500+ void (*complete)(struct videobuf_buffer *vb, void *priv),
1501+ void *priv)
1502+{
1503+ unsigned long flags;
1504+ struct isp_buf *buf;
1505+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
1506+ const struct scatterlist *sglist = dma->sglist;
1507+ struct isp_bufs *bufs = &isp_obj.bufs;
1508+ int sglen = dma->sglen;
1509+
1510+ BUG_ON(sglen < 0 || !sglist);
1511+
1512+ isp_vbq_sync(vb, DMA_TO_DEVICE);
1513+
1514+ spin_lock_irqsave(&bufs->lock, flags);
1515+
1516+ BUG_ON(ISP_BUFS_IS_FULL(bufs));
1517+
1518+ buf = ISP_BUF_QUEUE(bufs);
1519+
1520+ buf->isp_addr = bufs->isp_addr_capture[vb->i];
1521+ buf->complete = complete;
1522+ buf->vb = vb;
1523+ buf->priv = priv;
1524+ buf->vb_state = VIDEOBUF_DONE;
1525+
1526+ if (ISP_BUFS_IS_EMPTY(bufs)) {
1527+ isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
1528+ isp_set_buf(buf);
1529+ ispccdc_enable(1);
1530+ isp_start();
1531+ }
1532+
1533+ ISP_BUF_MARK_QUEUED(bufs);
1534+
1535+ spin_unlock_irqrestore(&bufs->lock, flags);
1536+
1537+ DPRINTK_ISPCTRL(KERN_ALERT "%s: queue %d vb %d, mmu %p\n", __func__,
1538+ (bufs->queue - 1 + NUM_BUFS) % NUM_BUFS, vb->i,
1539+ buf->isp_addr);
1540+
1541+ return 0;
1542+}
1543+EXPORT_SYMBOL(isp_buf_queue);
1544+
1545+int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
1546+ unsigned int *size)
1547+{
1548+ int rval = 0;
1549+ size_t tmp_size = PAGE_ALIGN(isp_obj.module.preview_output_width
1550+ * isp_obj.module.preview_output_height
1551+ * ISP_BYTES_PER_PIXEL);
1552+
1553+ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW
1554+ && isp_obj.tmp_buf_size < tmp_size)
1555+ rval = isp_tmp_buf_alloc(tmp_size);
1556+
1557+ return rval;
1558+}
1559+EXPORT_SYMBOL(isp_vbq_setup);
1560+
1561+/**
1562+ * isp_vbq_prepare - Videobuffer queue prepare.
1563+ * @vbq: Pointer to videobuf_queue structure.
1564+ * @vb: Pointer to videobuf_buffer structure.
1565+ * @field: Requested Field order for the videobuffer.
1566+ *
1567+ * Returns 0 if successful, or -EIO if the ispmmu was unable to map a
1568+ * scatter-gather linked list data space.
1569+ **/
1570+int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
1571+ enum v4l2_field field)
1572+{
1573+ unsigned int isp_addr;
1574+ struct videobuf_dmabuf *vdma;
1575+ struct isp_bufs *bufs = &isp_obj.bufs;
1576+
1577+ int err = 0;
1578+
1579+ vdma = videobuf_to_dma(vb);
1580+
1581+ isp_addr = ispmmu_vmap(vdma->sglist, vdma->sglen);
1582+
1583+ if (IS_ERR_VALUE(isp_addr))
1584+ err = -EIO;
1585+ else
1586+ bufs->isp_addr_capture[vb->i] = isp_addr;
1587+
1588+ return err;
1589+}
1590+EXPORT_SYMBOL(isp_vbq_prepare);
1591+
1592+/**
1593+ * isp_vbq_release - Videobuffer queue release.
1594+ * @vbq: Pointer to videobuf_queue structure.
1595+ * @vb: Pointer to videobuf_buffer structure.
1596+ **/
1597+void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb)
1598+{
1599+ struct isp_bufs *bufs = &isp_obj.bufs;
1600+
1601+ ispmmu_vunmap(bufs->isp_addr_capture[vb->i]);
1602+ bufs->isp_addr_capture[vb->i] = (dma_addr_t)NULL;
1603+ return;
1604+}
1605+EXPORT_SYMBOL(isp_vbq_release);
1606+
1607+/**
1608+ * isp_queryctrl - Query V4L2 control from existing controls in ISP.
1609+ * @a: Pointer to v4l2_queryctrl structure. It only needs the id field filled.
1610+ *
1611+ * Returns 0 if successful, or -EINVAL if not found in ISP.
1612+ **/
1613+int isp_queryctrl(struct v4l2_queryctrl *a)
1614+{
1615+ int i;
1616+
1617+ if (a->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
1618+ a->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
1619+ i = find_next_vctrl(a->id);
1620+ } else {
1621+ i = find_vctrl(a->id);
1622+ }
1623+
1624+ if (i < 0)
1625+ return -EINVAL;
1626+
1627+ *a = video_control[i].qc;
1628+ return 0;
1629+}
1630+EXPORT_SYMBOL(isp_queryctrl);
1631+
1632+/**
1633+ * isp_queryctrl - Query V4L2 control from existing controls in ISP.
1634+ * @a: Pointer to v4l2_queryctrl structure. It only needs the id field filled.
1635+ *
1636+ * Returns 0 if successful, or -EINVAL if not found in ISP.
1637+ **/
1638+int isp_querymenu(struct v4l2_querymenu *a)
1639+{
1640+ int i;
1641+
1642+ i = find_vmenu(a->id, a->index);
1643+
1644+ if (i < 0)
1645+ return -EINVAL;
1646+
1647+ *a = video_menu[i];
1648+ return 0;
1649+}
1650+EXPORT_SYMBOL(isp_querymenu);
1651+
1652+/**
1653+ * isp_g_ctrl - Gets value of the desired V4L2 control.
1654+ * @a: V4L2 control to read actual value from.
1655+ *
1656+ * Return 0 if successful, or -EINVAL if chosen control is not found.
1657+ **/
1658+int isp_g_ctrl(struct v4l2_control *a)
1659+{
1660+ u8 current_value;
1661+ int rval = 0;
1662+
1663+ if (!isp_obj.ref_count)
1664+ return -EINVAL;
1665+
1666+ switch (a->id) {
1667+ case V4L2_CID_BRIGHTNESS:
1668+ isppreview_query_brightness(&current_value);
1669+ a->value = current_value / ISPPRV_BRIGHT_UNITS;
1670+ break;
1671+ case V4L2_CID_CONTRAST:
1672+ isppreview_query_contrast(&current_value);
1673+ a->value = current_value / ISPPRV_CONTRAST_UNITS;
1674+ break;
1675+ case V4L2_CID_COLORFX:
1676+ isppreview_get_color(&current_value);
1677+ a->value = current_value;
1678+ break;
1679+ default:
1680+ rval = -EINVAL;
1681+ break;
1682+ }
1683+
1684+ return rval;
1685+}
1686+EXPORT_SYMBOL(isp_g_ctrl);
1687+
1688+/**
1689+ * isp_s_ctrl - Sets value of the desired V4L2 control.
1690+ * @a: V4L2 control to read actual value from.
1691+ *
1692+ * Return 0 if successful, -EINVAL if chosen control is not found or value
1693+ * is out of bounds, -EFAULT if copy_from_user or copy_to_user operation fails
1694+ * from camera abstraction layer related controls or the transfered user space
1695+ * pointer via the value field is not set properly.
1696+ **/
1697+int isp_s_ctrl(struct v4l2_control *a)
1698+{
1699+ int rval = 0;
1700+ u8 new_value = a->value;
1701+
1702+ if (!isp_obj.ref_count)
1703+ return -EINVAL;
1704+
1705+ switch (a->id) {
1706+ case V4L2_CID_BRIGHTNESS:
1707+ if (new_value > ISPPRV_BRIGHT_HIGH)
1708+ rval = -EINVAL;
1709+ else
1710+ isppreview_update_brightness(&new_value);
1711+ break;
1712+ case V4L2_CID_CONTRAST:
1713+ if (new_value > ISPPRV_CONTRAST_HIGH)
1714+ rval = -EINVAL;
1715+ else
1716+ isppreview_update_contrast(&new_value);
1717+ break;
1718+ case V4L2_CID_COLORFX:
1719+ if (new_value > V4L2_COLORFX_SEPIA)
1720+ rval = -EINVAL;
1721+ else
1722+ isppreview_set_color(&new_value);
1723+ break;
1724+ default:
1725+ rval = -EINVAL;
1726+ break;
1727+ }
1728+
1729+ return rval;
1730+}
1731+EXPORT_SYMBOL(isp_s_ctrl);
1732+
1733+/**
1734+ * isp_handle_private - Handle all private ioctls for isp module.
1735+ * @cmd: ioctl cmd value
1736+ * @arg: ioctl arg value
1737+ *
1738+ * Return 0 if successful, -EINVAL if chosen cmd value is not handled or value
1739+ * is out of bounds, -EFAULT if ioctl arg value is not valid.
1740+ * Function simply routes the input ioctl cmd id to the appropriate handler in
1741+ * the isp module.
1742+ **/
1743+int isp_handle_private(int cmd, void *arg)
1744+{
1745+ int rval = 0;
1746+
1747+ if (!isp_obj.ref_count)
1748+ return -EINVAL;
1749+
1750+ switch (cmd) {
1751+ case VIDIOC_PRIVATE_ISP_CCDC_CFG:
1752+ rval = omap34xx_isp_ccdc_config(arg);
1753+ break;
1754+ case VIDIOC_PRIVATE_ISP_PRV_CFG:
1755+ rval = omap34xx_isp_preview_config(arg);
1756+ break;
1757+ case VIDIOC_PRIVATE_ISP_AEWB_CFG: {
1758+ struct isph3a_aewb_config *params;
1759+ params = (struct isph3a_aewb_config *)arg;
1760+ rval = isph3a_aewb_configure(params);
1761+ }
1762+ break;
1763+ case VIDIOC_PRIVATE_ISP_AEWB_REQ: {
1764+ struct isph3a_aewb_data *data;
1765+ data = (struct isph3a_aewb_data *)arg;
1766+ rval = isph3a_aewb_request_statistics(data);
1767+ }
1768+ break;
1769+ case VIDIOC_PRIVATE_ISP_HIST_CFG: {
1770+ struct isp_hist_config *params;
1771+ params = (struct isp_hist_config *)arg;
1772+ rval = isp_hist_configure(params);
1773+ }
1774+ break;
1775+ case VIDIOC_PRIVATE_ISP_HIST_REQ: {
1776+ struct isp_hist_data *data;
1777+ data = (struct isp_hist_data *)arg;
1778+ rval = isp_hist_request_statistics(data);
1779+ }
1780+ break;
1781+ case VIDIOC_PRIVATE_ISP_AF_CFG: {
1782+ struct af_configuration *params;
1783+ params = (struct af_configuration *)arg;
1784+ rval = isp_af_configure(params);
1785+ }
1786+ break;
1787+ case VIDIOC_PRIVATE_ISP_AF_REQ: {
1788+ struct isp_af_data *data;
1789+ data = (struct isp_af_data *)arg;
1790+ rval = isp_af_request_statistics(data);
1791+ }
1792+ break;
1793+ default:
1794+ rval = -EINVAL;
1795+ break;
1796+ }
1797+ return rval;
1798+}
1799+EXPORT_SYMBOL(isp_handle_private);
1800+
1801+/**
1802+ * isp_enum_fmt_cap - Gets more information of chosen format index and type
1803+ * @f: Pointer to structure containing index and type of format to read from.
1804+ *
1805+ * Returns 0 if successful, or -EINVAL if format index or format type is
1806+ * invalid.
1807+ **/
1808+int isp_enum_fmt_cap(struct v4l2_fmtdesc *f)
1809+{
1810+ int index = f->index;
1811+ enum v4l2_buf_type type = f->type;
1812+ int rval = -EINVAL;
1813+
1814+ if (index >= NUM_ISP_CAPTURE_FORMATS)
1815+ goto err;
1816+
1817+ memset(f, 0, sizeof(*f));
1818+ f->index = index;
1819+ f->type = type;
1820+
1821+ switch (f->type) {
1822+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1823+ rval = 0;
1824+ break;
1825+ default:
1826+ goto err;
1827+ }
1828+
1829+ f->flags = isp_formats[index].flags;
1830+ strncpy(f->description, isp_formats[index].description,
1831+ sizeof(f->description));
1832+ f->pixelformat = isp_formats[index].pixelformat;
1833+err:
1834+ return rval;
1835+}
1836+EXPORT_SYMBOL(isp_enum_fmt_cap);
1837+
1838+/**
1839+ * isp_g_fmt_cap - Gets current output image format.
1840+ * @f: Pointer to V4L2 format structure to be filled with current output format
1841+ **/
1842+void isp_g_fmt_cap(struct v4l2_pix_format *pix)
1843+{
1844+ *pix = isp_obj.module.pix;
1845+ return;
1846+}
1847+EXPORT_SYMBOL(isp_g_fmt_cap);
1848+
1849+/**
1850+ * isp_s_fmt_cap - Sets I/O formats and crop and configures pipeline in ISP
1851+ * @f: Pointer to V4L2 format structure to be filled with current output format
1852+ *
1853+ * Returns 0 if successful, or return value of either isp_try_size or
1854+ * isp_try_fmt if there is an error.
1855+ **/
1856+int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
1857+ struct v4l2_pix_format *pix_output)
1858+{
1859+ int crop_scaling_w = 0, crop_scaling_h = 0;
1860+ int rval = 0;
1861+
1862+ if (!isp_obj.ref_count)
1863+ return -EINVAL;
1864+
1865+ rval = isp_calc_pipeline(pix_input, pix_output);
1866+ if (rval)
1867+ goto out;
1868+
1869+ rval = isp_try_size(pix_input, pix_output);
1870+ if (rval)
1871+ goto out;
1872+
1873+ rval = isp_try_fmt(pix_input, pix_output);
1874+ if (rval)
1875+ goto out;
1876+
1877+ if (ispcroprect.width != pix_output->width) {
1878+ crop_scaling_w = 1;
1879+ ispcroprect.left = 0;
1880+ ispcroprect.width = pix_output->width;
1881+ }
1882+
1883+ if (ispcroprect.height != pix_output->height) {
1884+ crop_scaling_h = 1;
1885+ ispcroprect.top = 0;
1886+ ispcroprect.height = pix_output->height;
1887+ }
1888+
1889+ isp_config_pipeline(pix_input, pix_output);
1890+
1891+ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER
1892+ && (crop_scaling_h || crop_scaling_w))
1893+ isp_config_crop(pix_output);
1894+
1895+out:
1896+ return rval;
1897+}
1898+EXPORT_SYMBOL(isp_s_fmt_cap);
1899+
1900+/**
1901+ * isp_config_crop - Configures crop parameters in isp resizer.
1902+ * @croppix: Pointer to V4L2 pixel format structure containing crop parameters
1903+ **/
1904+void isp_config_crop(struct v4l2_pix_format *croppix)
1905+{
1906+ u8 crop_scaling_w;
1907+ u8 crop_scaling_h;
1908+ unsigned long org_left, num_pix, new_top;
1909+
1910+ struct v4l2_pix_format *pix = croppix;
1911+
1912+ crop_scaling_w = (isp_obj.module.preview_output_width * 10) /
1913+ pix->width;
1914+ crop_scaling_h = (isp_obj.module.preview_output_height * 10) /
1915+ pix->height;
1916+
1917+ cur_rect.left = (ispcroprect.left * crop_scaling_w) / 10;
1918+ cur_rect.top = (ispcroprect.top * crop_scaling_h) / 10;
1919+ cur_rect.width = (ispcroprect.width * crop_scaling_w) / 10;
1920+ cur_rect.height = (ispcroprect.height * crop_scaling_h) / 10;
1921+
1922+ org_left = cur_rect.left;
1923+ while (((int)cur_rect.left & 0xFFFFFFF0) != (int)cur_rect.left)
1924+ (int)cur_rect.left--;
1925+
1926+ num_pix = org_left - cur_rect.left;
1927+ new_top = (int)(num_pix * 3) / 4;
1928+ cur_rect.top = cur_rect.top - new_top;
1929+ cur_rect.height = (2 * new_top) + cur_rect.height;
1930+
1931+ cur_rect.width = cur_rect.width + (2 * num_pix);
1932+ while (((int)cur_rect.width & 0xFFFFFFF0) != (int)cur_rect.width)
1933+ (int)cur_rect.width--;
1934+
1935+ isp_obj.tmp_buf_offset =
1936+ cur_rect.left * 2 +
1937+ isp_obj.module.preview_output_width * 2 * cur_rect.top;
1938+
1939+ ispresizer_trycrop(cur_rect.left, cur_rect.top, cur_rect.width,
1940+ cur_rect.height,
1941+ isp_obj.module.resizer_output_width,
1942+ isp_obj.module.resizer_output_height);
1943+
1944+ return;
1945+}
1946+EXPORT_SYMBOL(isp_config_crop);
1947+
1948+/**
1949+ * isp_g_crop - Gets crop rectangle size and position.
1950+ * @a: Pointer to V4L2 crop structure to be filled.
1951+ *
1952+ * Always returns 0.
1953+ **/
1954+int isp_g_crop(struct v4l2_crop *a)
1955+{
1956+ struct v4l2_crop *crop = a;
1957+
1958+ crop->c = ispcroprect;
1959+
1960+ return 0;
1961+}
1962+EXPORT_SYMBOL(isp_g_crop);
1963+
1964+/**
1965+ * isp_s_crop - Sets crop rectangle size and position and queues crop operation
1966+ * @a: Pointer to V4L2 crop structure with desired parameters.
1967+ * @pix: Pointer to V4L2 pixel format structure with desired parameters.
1968+ *
1969+ * Returns 0 if successful, or -EINVAL if crop parameters are out of bounds.
1970+ **/
1971+int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix)
1972+{
1973+ struct v4l2_crop *crop = a;
1974+ int rval = 0;
1975+
1976+ if (!isp_obj.ref_count)
1977+ return -EINVAL;
1978+
1979+ if (crop->c.left < 0)
1980+ crop->c.left = 0;
1981+ if (crop->c.width < 0)
1982+ crop->c.width = 0;
1983+ if (crop->c.top < 0)
1984+ crop->c.top = 0;
1985+ if (crop->c.height < 0)
1986+ crop->c.height = 0;
1987+
1988+ if (crop->c.left >= pix->width)
1989+ crop->c.left = pix->width - 1;
1990+ if (crop->c.top >= pix->height)
1991+ crop->c.top = pix->height - 1;
1992+
1993+ if (crop->c.left + crop->c.width > pix->width)
1994+ crop->c.width = pix->width - crop->c.left;
1995+ if (crop->c.top + crop->c.height > pix->height)
1996+ crop->c.height = pix->height - crop->c.top;
1997+
1998+ ispcroprect.left = crop->c.left;
1999+ ispcroprect.top = crop->c.top;
2000+ ispcroprect.width = crop->c.width;
2001+ ispcroprect.height = crop->c.height;
2002+
2003+ isp_config_crop(pix);
2004+
2005+ isp_obj.module.applyCrop = 1;
2006+
2007+ return rval;
2008+}
2009+EXPORT_SYMBOL(isp_s_crop);
2010+
2011+/**
2012+ * isp_try_fmt_cap - Tries desired input/output image formats
2013+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
2014+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
2015+ *
2016+ * Returns 0 if successful, or return value of either isp_try_size or
2017+ * isp_try_fmt if there is an error.
2018+ **/
2019+int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
2020+ struct v4l2_pix_format *pix_output)
2021+{
2022+ int rval = 0;
2023+
2024+ rval = isp_calc_pipeline(pix_input, pix_output);
2025+ if (rval)
2026+ goto out;
2027+
2028+ rval = isp_try_size(pix_input, pix_output);
2029+ if (rval)
2030+ goto out;
2031+
2032+ rval = isp_try_fmt(pix_input, pix_output);
2033+ if (rval)
2034+ goto out;
2035+
2036+out:
2037+ return rval;
2038+}
2039+EXPORT_SYMBOL(isp_try_fmt_cap);
2040+
2041+/**
2042+ * isp_try_size - Tries size configuration for I/O images of each ISP submodule
2043+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
2044+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
2045+ *
2046+ * Returns 0 if successful, or return value of ispccdc_try_size,
2047+ * isppreview_try_size, or ispresizer_try_size (depending on the pipeline
2048+ * configuration) if there is an error.
2049+ **/
2050+static int isp_try_size(struct v4l2_pix_format *pix_input,
2051+ struct v4l2_pix_format *pix_output)
2052+{
2053+ int rval = 0;
2054+
2055+ if (pix_output->width <= ISPRSZ_MIN_OUTPUT
2056+ || pix_output->height <= ISPRSZ_MIN_OUTPUT)
2057+ return -EINVAL;
2058+
2059+ if (pix_output->width >= ISPRSZ_MAX_OUTPUT
2060+ || pix_output->height > ISPRSZ_MAX_OUTPUT)
2061+ return -EINVAL;
2062+
2063+ isp_obj.module.ccdc_input_width = pix_input->width;
2064+ isp_obj.module.ccdc_input_height = pix_input->height;
2065+ isp_obj.module.resizer_output_width = pix_output->width;
2066+ isp_obj.module.resizer_output_height = pix_output->height;
2067+
2068+ if (isp_obj.module.isp_pipeline & OMAP_ISP_CCDC) {
2069+ rval = ispccdc_try_size(isp_obj.module.ccdc_input_width,
2070+ isp_obj.module.ccdc_input_height,
2071+ &isp_obj.module.ccdc_output_width,
2072+ &isp_obj.module.ccdc_output_height);
2073+ if (rval) {
2074+ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
2075+ " supported\n", pix_input->width,
2076+ pix_input->height);
2077+ return rval;
2078+ }
2079+ pix_output->width = isp_obj.module.ccdc_output_width;
2080+ pix_output->height = isp_obj.module.ccdc_output_height;
2081+ }
2082+
2083+ if (isp_obj.module.isp_pipeline & OMAP_ISP_PREVIEW) {
2084+ isp_obj.module.preview_input_width =
2085+ isp_obj.module.ccdc_output_width;
2086+ isp_obj.module.preview_input_height =
2087+ isp_obj.module.ccdc_output_height;
2088+ rval = isppreview_try_size(
2089+ isp_obj.module.preview_input_width,
2090+ isp_obj.module.preview_input_height,
2091+ &isp_obj.module.preview_output_width,
2092+ &isp_obj.module.preview_output_height);
2093+ if (rval) {
2094+ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
2095+ " supported\n", pix_input->width,
2096+ pix_input->height);
2097+ return rval;
2098+ }
2099+ pix_output->width = isp_obj.module.preview_output_width;
2100+ pix_output->height = isp_obj.module.preview_output_height;
2101+ }
2102+
2103+ if (isp_obj.module.isp_pipeline & OMAP_ISP_RESIZER) {
2104+ isp_obj.module.resizer_input_width =
2105+ isp_obj.module.preview_output_width;
2106+ isp_obj.module.resizer_input_height =
2107+ isp_obj.module.preview_output_height;
2108+ rval = ispresizer_try_size(
2109+ &isp_obj.module.resizer_input_width,
2110+ &isp_obj.module.resizer_input_height,
2111+ &isp_obj.module.resizer_output_width,
2112+ &isp_obj.module.resizer_output_height);
2113+ if (rval) {
2114+ printk(KERN_ERR "ISP_ERR: The dimensions %dx%d are not"
2115+ " supported\n", pix_input->width,
2116+ pix_input->height);
2117+ return rval;
2118+ }
2119+ pix_output->width = isp_obj.module.resizer_output_width;
2120+ pix_output->height = isp_obj.module.resizer_output_height;
2121+ }
2122+
2123+ return rval;
2124+}
2125+
2126+/**
2127+ * isp_try_fmt - Validates input/output format parameters.
2128+ * @pix_input: Pointer to V4L2 pixel format structure for input image.
2129+ * @pix_output: Pointer to V4L2 pixel format structure for output image.
2130+ *
2131+ * Always returns 0.
2132+ **/
2133+int isp_try_fmt(struct v4l2_pix_format *pix_input,
2134+ struct v4l2_pix_format *pix_output)
2135+{
2136+ int ifmt;
2137+
2138+ for (ifmt = 0; ifmt < NUM_ISP_CAPTURE_FORMATS; ifmt++) {
2139+ if (pix_output->pixelformat == isp_formats[ifmt].pixelformat)
2140+ break;
2141+ }
2142+ if (ifmt == NUM_ISP_CAPTURE_FORMATS)
2143+ ifmt = 1;
2144+ pix_output->pixelformat = isp_formats[ifmt].pixelformat;
2145+ pix_output->field = V4L2_FIELD_NONE;
2146+ pix_output->bytesperline = pix_output->width * ISP_BYTES_PER_PIXEL;
2147+ pix_output->sizeimage =
2148+ PAGE_ALIGN(pix_output->bytesperline * pix_output->height);
2149+ pix_output->priv = 0;
2150+ switch (pix_output->pixelformat) {
2151+ case V4L2_PIX_FMT_YUYV:
2152+ case V4L2_PIX_FMT_UYVY:
2153+ pix_output->colorspace = V4L2_COLORSPACE_JPEG;
2154+ break;
2155+ default:
2156+ pix_output->colorspace = V4L2_COLORSPACE_SRGB;
2157+ }
2158+
2159+ isp_obj.module.pix.pixelformat = pix_output->pixelformat;
2160+ isp_obj.module.pix.width = pix_output->width;
2161+ isp_obj.module.pix.height = pix_output->height;
2162+ isp_obj.module.pix.field = pix_output->field;
2163+ isp_obj.module.pix.bytesperline = pix_output->bytesperline;
2164+ isp_obj.module.pix.sizeimage = pix_output->sizeimage;
2165+ isp_obj.module.pix.priv = pix_output->priv;
2166+ isp_obj.module.pix.colorspace = pix_output->colorspace;
2167+
2168+ return 0;
2169+}
2170+EXPORT_SYMBOL(isp_try_fmt);
2171+
2172+/**
2173+ * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
2174+ *
2175+ * Routine for saving the context of each module in the ISP.
2176+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
2177+ **/
2178+static void isp_save_ctx(void)
2179+{
2180+ isp_save_context(isp_reg_list);
2181+ ispccdc_save_context();
2182+ ispmmu_save_context();
2183+ isphist_save_context();
2184+ isph3a_save_context();
2185+ isppreview_save_context();
2186+ ispresizer_save_context();
2187+}
2188+
2189+/**
2190+ * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
2191+ *
2192+ * Routine for restoring the context of each module in the ISP.
2193+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
2194+ **/
2195+static void isp_restore_ctx(void)
2196+{
2197+ isp_restore_context(isp_reg_list);
2198+ ispccdc_restore_context();
2199+ ispmmu_restore_context();
2200+ isphist_restore_context();
2201+ isph3a_restore_context();
2202+ isppreview_restore_context();
2203+ ispresizer_restore_context();
2204+}
2205+
2206+static int isp_enable_clocks(void)
2207+{
2208+ int r;
2209+
2210+ r = clk_enable(isp_obj.cam_ick);
2211+ if (r) {
2212+ DPRINTK_ISPCTRL("ISP_ERR: clk_en for ick failed\n");
2213+ goto out_clk_enable_ick;
2214+ }
2215+ r = clk_enable(isp_obj.cam_mclk);
2216+ if (r) {
2217+ DPRINTK_ISPCTRL("ISP_ERR: clk_en for mclk failed\n");
2218+ goto out_clk_enable_mclk;
2219+ }
2220+ r = clk_enable(isp_obj.csi2_fck);
2221+ if (r) {
2222+ DPRINTK_ISPCTRL("ISP_ERR: clk_en for csi2_fclk"
2223+ " failed\n");
2224+ goto out_clk_enable_csi2_fclk;
2225+ }
2226+ return 0;
2227+
2228+out_clk_enable_csi2_fclk:
2229+ clk_disable(isp_obj.cam_mclk);
2230+out_clk_enable_mclk:
2231+ clk_disable(isp_obj.cam_ick);
2232+out_clk_enable_ick:
2233+ return r;
2234+}
2235+
2236+static void isp_disable_clocks(void)
2237+{
2238+ clk_disable(isp_obj.cam_ick);
2239+ clk_disable(isp_obj.cam_mclk);
2240+ clk_disable(isp_obj.csi2_fck);
2241+}
2242+
2243+/**
2244+ * isp_get - Adquires the ISP resource.
2245+ *
2246+ * Initializes the clocks for the first acquire.
2247+ **/
2248+int isp_get(void)
2249+{
2250+ static int has_context;
2251+ int ret_err = 0;
2252+
2253+ if (omap3isp == NULL)
2254+ return -EBUSY;
2255+
2256+ DPRINTK_ISPCTRL("isp_get: old %d\n", isp_obj.ref_count);
2257+ mutex_lock(&(isp_obj.isp_mutex));
2258+ if (isp_obj.ref_count == 0) {
2259+ ret_err = isp_enable_clocks();
2260+ if (ret_err)
2261+ goto out_err;
2262+ /* We don't want to restore context before saving it! */
2263+ if (has_context)
2264+ isp_restore_ctx();
2265+ else
2266+ has_context = 1;
2267+ } else {
2268+ mutex_unlock(&isp_obj.isp_mutex);
2269+ return -EBUSY;
2270+ }
2271+ isp_obj.ref_count++;
2272+ mutex_unlock(&(isp_obj.isp_mutex));
2273+
2274+ DPRINTK_ISPCTRL("isp_get: new %d\n", isp_obj.ref_count);
2275+ return isp_obj.ref_count;
2276+
2277+out_err:
2278+ mutex_unlock(&(isp_obj.isp_mutex));
2279+ return ret_err;
2280+}
2281+EXPORT_SYMBOL(isp_get);
2282+
2283+/**
2284+ * isp_put - Releases the ISP resource.
2285+ *
2286+ * Releases the clocks also for the last release.
2287+ **/
2288+int isp_put(void)
2289+{
2290+ if (omap3isp == NULL)
2291+ return -EBUSY;
2292+
2293+ DPRINTK_ISPCTRL("isp_put: old %d\n", isp_obj.ref_count);
2294+ mutex_lock(&(isp_obj.isp_mutex));
2295+ if (isp_obj.ref_count) {
2296+ if (--isp_obj.ref_count == 0) {
2297+ isp_save_ctx();
2298+ isp_tmp_buf_free();
2299+ isp_release_resources();
2300+ isp_obj.module.isp_pipeline = 0;
2301+ isp_disable_clocks();
2302+ memset(&ispcroprect, 0, sizeof(ispcroprect));
2303+ memset(&cur_rect, 0, sizeof(cur_rect));
2304+ }
2305+ }
2306+ mutex_unlock(&(isp_obj.isp_mutex));
2307+ DPRINTK_ISPCTRL("isp_put: new %d\n", isp_obj.ref_count);
2308+ return isp_obj.ref_count;
2309+}
2310+EXPORT_SYMBOL(isp_put);
2311+
2312+/**
2313+ * isp_save_context - Saves the values of the ISP module registers.
2314+ * @reg_list: Structure containing pairs of register address and value to
2315+ * modify on OMAP.
2316+ **/
2317+void isp_save_context(struct isp_reg *reg_list)
2318+{
2319+ struct isp_reg *next = reg_list;
2320+
2321+ for (; next->reg != ISP_TOK_TERM; next++)
2322+ next->val = isp_reg_readl(next->mmio_range, next->reg);
2323+}
2324+EXPORT_SYMBOL(isp_save_context);
2325+
2326+/**
2327+ * isp_restore_context - Restores the values of the ISP module registers.
2328+ * @reg_list: Structure containing pairs of register address and value to
2329+ * modify on OMAP.
2330+ **/
2331+void isp_restore_context(struct isp_reg *reg_list)
2332+{
2333+ struct isp_reg *next = reg_list;
2334+
2335+ for (; next->reg != ISP_TOK_TERM; next++)
2336+ isp_reg_writel(next->val, next->mmio_range, next->reg);
2337+}
2338+EXPORT_SYMBOL(isp_restore_context);
2339+
2340+static int isp_remove(struct platform_device *pdev)
2341+{
2342+ struct isp_device *isp = platform_get_drvdata(pdev);
2343+ int i;
2344+
2345+ isp_csi2_cleanup();
2346+ isp_af_exit();
2347+ isp_resizer_cleanup();
2348+ isp_preview_cleanup();
2349+ ispmmu_cleanup();
2350+ isph3a_aewb_cleanup();
2351+ isp_hist_cleanup();
2352+ isp_ccdc_cleanup();
2353+
2354+ if (!isp)
2355+ return 0;
2356+
2357+ clk_put(isp_obj.cam_ick);
2358+ clk_put(isp_obj.cam_mclk);
2359+ clk_put(isp_obj.csi2_fck);
2360+
2361+ free_irq(isp->irq, &isp_obj);
2362+
2363+ for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
2364+ if (isp->mmio_base[i]) {
2365+ iounmap((void *)isp->mmio_base[i]);
2366+ isp->mmio_base[i] = 0;
2367+ }
2368+
2369+ if (isp->mmio_base_phys[i]) {
2370+ release_mem_region(isp->mmio_base_phys[i],
2371+ isp->mmio_size[i]);
2372+ isp->mmio_base_phys[i] = 0;
2373+ }
2374+ }
2375+
2376+ omap3isp = NULL;
2377+
2378+ kfree(isp);
2379+
2380+ return 0;
2381+}
2382+
2383+#ifdef CONFIG_PM
2384+
2385+static int isp_suspend(struct platform_device *pdev, pm_message_t state)
2386+{
2387+ int reset;
2388+
2389+ mutex_lock(&(isp_obj.isp_mutex));
2390+ DPRINTK_ISPCTRL("isp_suspend: starting\n");
2391+ if (isp_obj.ref_count == 0)
2392+ goto out;
2393+
2394+ isp_disable_interrupts();
2395+ reset = isp_suspend_modules();
2396+ isp_save_ctx();
2397+ if (reset)
2398+ isp_reset();
2399+
2400+ isp_disable_clocks();
2401+
2402+out:
2403+ DPRINTK_ISPCTRL("isp_suspend: done\n");
2404+ mutex_unlock(&(isp_obj.isp_mutex));
2405+ return 0;
2406+}
2407+
2408+static int isp_resume(struct platform_device *pdev)
2409+{
2410+ int ret_err = 0;
2411+
2412+ DPRINTK_ISPCTRL("isp_resume: starting\n");
2413+
2414+ if (omap3isp == NULL)
2415+ goto out;
2416+
2417+ if (isp_obj.ref_count >= 0) {
2418+ ret_err = isp_enable_clocks();
2419+ if (ret_err)
2420+ goto out;
2421+ isp_restore_ctx();
2422+ isp_resume_modules();
2423+ isp_enable_interrupts(RAW_CAPTURE(&isp_obj));
2424+ isp_start();
2425+ }
2426+
2427+out:
2428+ DPRINTK_ISPCTRL("isp_resume: done \n");
2429+ return ret_err;
2430+}
2431+
2432+#else
2433+
2434+#define isp_suspend NULL
2435+#define isp_resume NULL
2436+
2437+#endif /* CONFIG_PM */
2438+
2439+
2440+static int isp_probe(struct platform_device *pdev)
2441+{
2442+ struct isp_device *isp;
2443+ int ret_err = 0;
2444+ int i;
2445+
2446+ isp = kzalloc(sizeof(*isp), GFP_KERNEL);
2447+ if (!isp) {
2448+ dev_err(&pdev->dev, "could not allocate memory\n");
2449+ return -ENOMEM;
2450+ }
2451+
2452+ platform_set_drvdata(pdev, isp);
2453+
2454+ isp->dev = &pdev->dev;
2455+
2456+ for (i = 0; i <= OMAP3_ISP_IOMEM_CSI2PHY; i++) {
2457+ struct resource *mem;
2458+ /* request the mem region for the camera registers */
2459+ mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
2460+ if (!mem) {
2461+ dev_err(isp->dev, "no mem resource?\n");
2462+ return -ENODEV;
2463+ }
2464+
2465+ if (!request_mem_region(mem->start, mem->end - mem->start + 1,
2466+ pdev->name)) {
2467+ dev_err(isp->dev,
2468+ "cannot reserve camera register I/O region\n");
2469+ return -ENODEV;
2470+
2471+ }
2472+ isp->mmio_base_phys[i] = mem->start;
2473+ isp->mmio_size[i] = mem->end - mem->start + 1;
2474+
2475+ /* map the region */
2476+ isp->mmio_base[i] = (unsigned long)
2477+ ioremap_nocache(isp->mmio_base_phys[i],
2478+ isp->mmio_size[i]);
2479+ if (!isp->mmio_base[i]) {
2480+ dev_err(isp->dev,
2481+ "cannot map camera register I/O region\n");
2482+ return -ENODEV;
2483+ }
2484+ }
2485+
2486+ isp->irq = platform_get_irq(pdev, 0);
2487+ if (isp->irq <= 0) {
2488+ dev_err(isp->dev, "no irq for camera?\n");
2489+ return -ENODEV;
2490+ }
2491+
2492+ isp_obj.cam_ick = clk_get(&camera_dev, "cam_ick");
2493+ if (IS_ERR(isp_obj.cam_ick)) {
2494+ DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
2495+ "cam_ick failed\n");
2496+ return PTR_ERR(isp_obj.cam_ick);
2497+ }
2498+ isp_obj.cam_mclk = clk_get(&camera_dev, "cam_mclk");
2499+ if (IS_ERR(isp_obj.cam_mclk)) {
2500+ DPRINTK_ISPCTRL("ISP_ERR: clk_get for "
2501+ "cam_mclk failed\n");
2502+ ret_err = PTR_ERR(isp_obj.cam_mclk);
2503+ goto out_clk_get_mclk;
2504+ }
2505+ isp_obj.csi2_fck = clk_get(&camera_dev, "csi2_96m_fck");
2506+ if (IS_ERR(isp_obj.csi2_fck)) {
2507+ DPRINTK_ISPCTRL("ISP_ERR: clk_get for csi2_fclk"
2508+ " failed\n");
2509+ ret_err = PTR_ERR(isp_obj.csi2_fck);
2510+ goto out_clk_get_csi2_fclk;
2511+ }
2512+
2513+ if (request_irq(isp->irq, omap34xx_isp_isr, IRQF_SHARED,
2514+ "Omap 3 Camera ISP", &isp_obj)) {
2515+ DPRINTK_ISPCTRL("Could not install ISR\n");
2516+ ret_err = -EINVAL;
2517+ goto out_request_irq;
2518+ }
2519+
2520+ isp_obj.ref_count = 0;
2521+
2522+ mutex_init(&(isp_obj.isp_mutex));
2523+ spin_lock_init(&isp_obj.lock);
2524+ spin_lock_init(&isp_obj.bufs.lock);
2525+
2526+ omap3isp = isp;
2527+
2528+ ret_err = ispmmu_init();
2529+ if (ret_err)
2530+ goto out_ispmmu_init;
2531+
2532+ isp_ccdc_init();
2533+ isp_hist_init();
2534+ isph3a_aewb_init();
2535+ isp_preview_init();
2536+ isp_resizer_init();
2537+ isp_af_init();
2538+ isp_csi2_init();
2539+
2540+ isp_get();
2541+ isp_power_settings(1);
2542+ isp_put();
2543+
2544+ isph3a_notify(1);
2545+ isp_af_notify(1);
2546+
2547+ return 0;
2548+
2549+out_ispmmu_init:
2550+ omap3isp = NULL;
2551+ free_irq(isp->irq, &isp_obj);
2552+out_request_irq:
2553+ clk_put(isp_obj.csi2_fck);
2554+out_clk_get_csi2_fclk:
2555+ clk_put(isp_obj.cam_mclk);
2556+out_clk_get_mclk:
2557+ clk_put(isp_obj.cam_ick);
2558+
2559+ return ret_err;
2560+}
2561+
2562+static struct platform_driver omap3isp_driver = {
2563+ .probe = isp_probe,
2564+ .remove = isp_remove,
2565+ .suspend = isp_suspend,
2566+ .resume = isp_resume,
2567+ .driver = {
2568+ .name = "omap3isp",
2569+ },
2570+};
2571+
2572+/**
2573+ * isp_init - ISP module initialization.
2574+ **/
2575+static int __init isp_init(void)
2576+{
2577+ return platform_driver_register(&omap3isp_driver);
2578+}
2579+
2580+/**
2581+ * isp_cleanup - ISP module cleanup.
2582+ **/
2583+static void __exit isp_cleanup(void)
2584+{
2585+ platform_driver_unregister(&omap3isp_driver);
2586+}
2587+
2588+/**
2589+ * isp_print_status - Prints the values of the ISP Control Module registers
2590+ *
2591+ * Also prints other debug information stored in the ISP module structure.
2592+ **/
2593+void isp_print_status(void)
2594+{
2595+ if (!is_ispctrl_debug_enabled())
2596+ return;
2597+
2598+ DPRINTK_ISPCTRL("###ISP_CTRL=0x%x\n",
2599+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
2600+ DPRINTK_ISPCTRL("###ISP_TCTRL_CTRL=0x%x\n",
2601+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
2602+ DPRINTK_ISPCTRL("###ISP_SYSCONFIG=0x%x\n",
2603+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG));
2604+ DPRINTK_ISPCTRL("###ISP_SYSSTATUS=0x%x\n",
2605+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_SYSSTATUS));
2606+ DPRINTK_ISPCTRL("###ISP_IRQ0ENABLE=0x%x\n",
2607+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
2608+ DPRINTK_ISPCTRL("###ISP_IRQ0STATUS=0x%x\n",
2609+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
2610+}
2611+EXPORT_SYMBOL(isp_print_status);
2612+
2613+module_init(isp_init);
2614+module_exit(isp_cleanup);
2615+
2616+MODULE_AUTHOR("Texas Instruments");
2617+MODULE_DESCRIPTION("ISP Control Module Library");
2618+MODULE_LICENSE("GPL");
2619diff --git a/drivers/media/video/isp/isp.h b/drivers/media/video/isp/isp.h
2620new file mode 100644
2621index 0000000..55c98a9
2622--- /dev/null
2623+++ b/drivers/media/video/isp/isp.h
2624@@ -0,0 +1,318 @@
2625+/*
2626+ * isp.h
2627+ *
2628+ * Top level public header file for ISP Control module in
2629+ * TI's OMAP3 Camera ISP
2630+ *
2631+ * Copyright (C) 2009 Texas Instruments.
2632+ * Copyright (C) 2009 Nokia.
2633+ *
2634+ * Contributors:
2635+ * Sameer Venkatraman <sameerv@ti.com>
2636+ * Mohit Jalori <mjalori@ti.com>
2637+ * Sergio Aguirre <saaguirre@ti.com>
2638+ * Sakari Ailus <sakari.ailus@nokia.com>
2639+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2640+ *
2641+ * This package is free software; you can redistribute it and/or modify
2642+ * it under the terms of the GNU General Public License version 2 as
2643+ * published by the Free Software Foundation.
2644+ *
2645+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2646+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2647+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2648+ */
2649+
2650+#ifndef OMAP_ISP_TOP_H
2651+#define OMAP_ISP_TOP_H
2652+#include <mach/cpu.h>
2653+#include <media/videobuf-dma-sg.h>
2654+#include <linux/videodev2.h>
2655+#define OMAP_ISP_CCDC (1 << 0)
2656+#define OMAP_ISP_PREVIEW (1 << 1)
2657+#define OMAP_ISP_RESIZER (1 << 2)
2658+#define OMAP_ISP_AEWB (1 << 3)
2659+#define OMAP_ISP_AF (1 << 4)
2660+#define OMAP_ISP_HIST (1 << 5)
2661+
2662+#define ISP_TOK_TERM 0xFFFFFFFF /*
2663+ * terminating token for ISP
2664+ * modules reg list
2665+ */
2666+#define NUM_BUFS VIDEO_MAX_FRAME
2667+
2668+#ifndef CONFIG_ARCH_OMAP3410
2669+#define USE_ISP_PREVIEW
2670+#define USE_ISP_RESZ
2671+#define is_isppreview_enabled() 1
2672+#define is_ispresizer_enabled() 1
2673+#else
2674+#define is_isppreview_enabled() 0
2675+#define is_ispresizer_enabled() 0
2676+#endif
2677+
2678+#define ISP_BYTES_PER_PIXEL 2
2679+#define NUM_ISP_CAPTURE_FORMATS (sizeof(isp_formats) / \
2680+ sizeof(isp_formats[0]))
2681+typedef int (*isp_vbq_callback_ptr) (struct videobuf_buffer *vb);
2682+typedef void (*isp_callback_t) (unsigned long status,
2683+ isp_vbq_callback_ptr arg1, void *arg2);
2684+
2685+enum isp_mem_resources {
2686+ OMAP3_ISP_IOMEM_MAIN,
2687+ OMAP3_ISP_IOMEM_CBUFF,
2688+ OMAP3_ISP_IOMEM_CCP2,
2689+ OMAP3_ISP_IOMEM_CCDC,
2690+ OMAP3_ISP_IOMEM_HIST,
2691+ OMAP3_ISP_IOMEM_H3A,
2692+ OMAP3_ISP_IOMEM_PREV,
2693+ OMAP3_ISP_IOMEM_RESZ,
2694+ OMAP3_ISP_IOMEM_SBL,
2695+ OMAP3_ISP_IOMEM_CSI2A,
2696+ OMAP3_ISP_IOMEM_CSI2PHY
2697+};
2698+
2699+struct isp_device {
2700+ struct device *dev;
2701+
2702+ /*** platform HW resources ***/
2703+ unsigned int irq;
2704+
2705+#define mmio_base_main mmio_base[OMAP3_ISP_IOMEM_MAIN]
2706+#define mmio_cbuff_main mmio_base[OMAP3_ISP_IOMEM_CBUFF]
2707+#define mmio_ccp2_main mmio_base[OMAP3_ISP_IOMEM_CCP2]
2708+#define mmio_ccdc_main mmio_base[OMAP3_ISP_IOMEM_CCDC]
2709+#define mmio_hist_main mmio_base[OMAP3_ISP_IOMEM_HIST]
2710+#define mmio_h3a_main mmio_base[OMAP3_ISP_IOMEM_H3A]
2711+#define mmio_prev_main mmio_base[OMAP3_ISP_IOMEM_PREV]
2712+#define mmio_resz_main mmio_base[OMAP3_ISP_IOMEM_RESZ]
2713+#define mmio_sbl_main mmio_base[OMAP3_ISP_IOMEM_SBL]
2714+#define mmio_csi2_main mmio_base[OMAP3_ISP_IOMEM_CSI2A]
2715+#define mmio_csi2phy_main mmio_base[OMAP3_ISP_IOMEM_CSI2PHY]
2716+ unsigned long mmio_base[OMAP3_ISP_IOMEM_CSI2PHY + 1];
2717+ unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_CSI2PHY + 1];
2718+ unsigned long mmio_size[OMAP3_ISP_IOMEM_CSI2PHY + 1];
2719+};
2720+
2721+enum isp_interface_type {
2722+ ISP_PARLL = 1,
2723+ ISP_CSIA = 2,
2724+ ISP_CSIB = 4,
2725+ ISP_NONE = 8 /* memory input to preview / resizer */
2726+};
2727+
2728+enum isp_irqevents {
2729+ CSIA = 0x01,
2730+ CSIB = 0x10,
2731+ CCDC_VD0 = 0x100,
2732+ CCDC_VD1 = 0x200,
2733+ CCDC_VD2 = 0x400,
2734+ CCDC_ERR = 0x800,
2735+ H3A_AWB_DONE = 0x2000,
2736+ H3A_AF_DONE = 0x1000,
2737+ HIST_DONE = 0x10000,
2738+ PREV_DONE = 0x100000,
2739+ LSC_DONE = 0x20000,
2740+ LSC_PRE_COMP = 0x40000,
2741+ LSC_PRE_ERR = 0x80000,
2742+ RESZ_DONE = 0x1000000,
2743+ SBL_OVF = 0x2000000,
2744+ MMU_ERR = 0x10000000,
2745+ OCP_ERR = 0x20000000,
2746+ HS_VS = 0x80000000
2747+};
2748+
2749+enum isp_callback_type {
2750+ CBK_CCDC_VD0,
2751+ CBK_CCDC_VD1,
2752+ CBK_PREV_DONE,
2753+ CBK_RESZ_DONE,
2754+ CBK_MMU_ERR,
2755+ CBK_H3A_AWB_DONE,
2756+ CBK_HIST_DONE,
2757+ CBK_HS_VS,
2758+ CBK_LSC_ISR,
2759+ CBK_H3A_AF_DONE,
2760+ CBK_CATCHALL,
2761+ CBK_CSIA,
2762+ CBK_CSIB,
2763+ CBK_END,
2764+};
2765+
2766+/**
2767+ * struct isp_reg - Structure for ISP register values.
2768+ * @reg: 32-bit Register address.
2769+ * @val: 32-bit Register value.
2770+ */
2771+struct isp_reg {
2772+ enum isp_mem_resources mmio_range;
2773+ u32 reg;
2774+ u32 val;
2775+};
2776+
2777+/**
2778+ * struct isp_interface_config - ISP interface configuration.
2779+ * @ccdc_par_ser: ISP interface type. 0 - Parallel, 1 - CSIA, 2 - CSIB to CCDC.
2780+ * @par_bridge: CCDC Bridge input control. Parallel interface.
2781+ * 0 - Disable, 1 - Enable, first byte->cam_d(bits 7 to 0)
2782+ * 2 - Enable, first byte -> cam_d(bits 15 to 8)
2783+ * @par_clk_pol: Pixel clock polarity on the parallel interface.
2784+ * 0 - Non Inverted, 1 - Inverted
2785+ * @dataline_shift: Data lane shifter.
2786+ * 0 - No Shift, 1 - CAMEXT[13 to 2]->CAM[11 to 0]
2787+ * 2 - CAMEXT[13 to 4]->CAM[9 to 0]
2788+ * 3 - CAMEXT[13 to 6]->CAM[7 to 0]
2789+ * @hsvs_syncdetect: HS or VS synchronization signal detection.
2790+ * 0 - HS Falling, 1 - HS rising
2791+ * 2 - VS falling, 3 - VS rising
2792+ * @strobe: Strobe related parameter.
2793+ * @prestrobe: PreStrobe related parameter.
2794+ * @shutter: Shutter related parameter.
2795+ * @hskip: Horizontal Start Pixel performed in Preview module.
2796+ * @vskip: Vertical Start Line performed in Preview module.
2797+ * @wenlog: Store the value for the sensor specific wenlog field.
2798+ * @wait_hs_vs: Wait for this many hs_vs before anything else in the beginning.
2799+ */
2800+struct isp_interface_config {
2801+ enum isp_interface_type ccdc_par_ser;
2802+ u8 dataline_shift;
2803+ u32 hsvs_syncdetect;
2804+ int strobe;
2805+ int prestrobe;
2806+ int shutter;
2807+ u32 prev_sph;
2808+ u32 prev_slv;
2809+ u32 wenlog;
2810+ int wait_hs_vs;
2811+ union {
2812+ struct par {
2813+ unsigned par_bridge:2;
2814+ unsigned par_clk_pol:1;
2815+ } par;
2816+ struct csi {
2817+ unsigned crc:1;
2818+ unsigned mode:1;
2819+ unsigned edge:1;
2820+ unsigned signalling:1;
2821+ unsigned strobe_clock_inv:1;
2822+ unsigned vs_edge:1;
2823+ unsigned channel:3;
2824+ unsigned vpclk:2; /* Video port output clock */
2825+ unsigned int data_start;
2826+ unsigned int data_size;
2827+ u32 format; /* V4L2_PIX_FMT_* */
2828+ } csi;
2829+ } u;
2830+};
2831+
2832+u32 isp_reg_readl(enum isp_mem_resources isp_mmio_range, u32 reg_offset);
2833+
2834+void isp_reg_writel(u32 reg_value, enum isp_mem_resources isp_mmio_range,
2835+ u32 reg_offset);
2836+
2837+static inline void isp_reg_and(enum isp_mem_resources mmio_range, u32 reg,
2838+ u32 and_bits)
2839+{
2840+ u32 v = isp_reg_readl(mmio_range, reg);
2841+
2842+ isp_reg_writel(v & and_bits, mmio_range, reg);
2843+}
2844+
2845+static inline void isp_reg_or(enum isp_mem_resources mmio_range, u32 reg,
2846+ u32 or_bits)
2847+{
2848+ u32 v = isp_reg_readl(mmio_range, reg);
2849+
2850+ isp_reg_writel(v | or_bits, mmio_range, reg);
2851+}
2852+
2853+static inline void isp_reg_and_or(enum isp_mem_resources mmio_range, u32 reg,
2854+ u32 and_bits, u32 or_bits)
2855+{
2856+ u32 v = isp_reg_readl(mmio_range, reg);
2857+
2858+ isp_reg_writel((v & and_bits) | or_bits, mmio_range, reg);
2859+}
2860+
2861+void isp_start(void);
2862+
2863+void isp_stop(void);
2864+
2865+int isp_buf_queue(struct videobuf_buffer *vb,
2866+ void (*complete)(struct videobuf_buffer *vb, void *priv),
2867+ void *priv);
2868+
2869+int isp_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
2870+ unsigned int *size);
2871+
2872+int isp_vbq_prepare(struct videobuf_queue *vbq, struct videobuf_buffer *vb,
2873+ enum v4l2_field field);
2874+
2875+void isp_vbq_release(struct videobuf_queue *vbq, struct videobuf_buffer *vb);
2876+
2877+int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
2878+ isp_vbq_callback_ptr arg1, void *arg2);
2879+
2880+int isp_unset_callback(enum isp_callback_type type);
2881+
2882+u32 isp_set_xclk(u32 xclk, u8 xclksel);
2883+
2884+int isp_configure_interface(struct isp_interface_config *config);
2885+
2886+int isp_get(void);
2887+
2888+int isp_put(void);
2889+
2890+int isp_queryctrl(struct v4l2_queryctrl *a);
2891+
2892+int isp_querymenu(struct v4l2_querymenu *a);
2893+
2894+int isp_g_ctrl(struct v4l2_control *a);
2895+
2896+int isp_s_ctrl(struct v4l2_control *a);
2897+
2898+int isp_enum_fmt_cap(struct v4l2_fmtdesc *f);
2899+
2900+int isp_try_fmt_cap(struct v4l2_pix_format *pix_input,
2901+ struct v4l2_pix_format *pix_output);
2902+
2903+void isp_g_fmt_cap(struct v4l2_pix_format *pix);
2904+
2905+int isp_s_fmt_cap(struct v4l2_pix_format *pix_input,
2906+ struct v4l2_pix_format *pix_output);
2907+
2908+int isp_g_crop(struct v4l2_crop *a);
2909+
2910+int isp_s_crop(struct v4l2_crop *a, struct v4l2_pix_format *pix);
2911+
2912+void isp_config_crop(struct v4l2_pix_format *pix);
2913+
2914+int isp_try_fmt(struct v4l2_pix_format *pix_input,
2915+ struct v4l2_pix_format *pix_output);
2916+
2917+int isp_handle_private(int cmd, void *arg);
2918+
2919+void isp_save_context(struct isp_reg *);
2920+
2921+void isp_restore_context(struct isp_reg *);
2922+
2923+void isp_print_status(void);
2924+
2925+int __init isp_ccdc_init(void);
2926+int __init isp_hist_init(void);
2927+int __init isph3a_aewb_init(void);
2928+int __init isp_preview_init(void);
2929+int __init isp_resizer_init(void);
2930+int __init isp_af_init(void);
2931+int __init isp_csi2_init(void);
2932+
2933+void isp_ccdc_cleanup(void);
2934+void isp_hist_cleanup(void);
2935+void isph3a_aewb_cleanup(void);
2936+void isp_preview_cleanup(void);
2937+void isp_hist_cleanup(void);
2938+void isp_resizer_cleanup(void);
2939+void isp_af_exit(void);
2940+void isp_csi2_cleanup(void);
2941+
2942+#endif /* OMAP_ISP_TOP_H */
2943diff --git a/drivers/media/video/isp/ispreg.h b/drivers/media/video/isp/ispreg.h
2944new file mode 100644
2945index 0000000..4f8e1ef
2946--- /dev/null
2947+++ b/drivers/media/video/isp/ispreg.h
2948@@ -0,0 +1,1674 @@
2949+/*
2950+ * ispreg.h
2951+ *
2952+ * Header file for all the ISP module in TI's OMAP3 Camera ISP.
2953+ * It has the OMAP HW register definitions.
2954+ *
2955+ * Copyright (C) 2009 Texas Instruments.
2956+ * Copyright (C) 2009 Nokia.
2957+ *
2958+ * Contributors:
2959+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2960+ * Thara Gopinath <thara@ti.com>
2961+ * Sergio Aguirre <saaguirre@ti.com>
2962+ *
2963+ * This package is free software; you can redistribute it and/or modify
2964+ * it under the terms of the GNU General Public License version 2 as
2965+ * published by the Free Software Foundation.
2966+ *
2967+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2968+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2969+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2970+ */
2971+
2972+#ifndef __ISPREG_H__
2973+#define __ISPREG_H__
2974+
2975+#include <mach/omap34xx.h>
2976+
2977+/* Note: Uncomment below defines as needed for enabling module specific debug
2978+ * messages
2979+ */
2980+
2981+/*
2982+ #define OMAP_ISPCTRL_DEBUG
2983+ #define OMAP_ISPCCDC_DEBUG
2984+ #define OMAP_ISPPREV_DEBUG
2985+ #define OMAP_ISPRESZ_DEBUG
2986+ #define OMAP_ISPMMU_DEBUG
2987+ #define OMAP_ISPH3A_DEBUG
2988+ #define OMAP_ISP_AF_DEBUG
2989+ #define OMAP_ISPHIST_DEBUG
2990+*/
2991+
2992+#ifdef OMAP_ISPCTRL_DEBUG
2993+#define DPRINTK_ISPCTRL(format, ...) \
2994+ printk(KERN_INFO "ISPCTRL: " format, ## __VA_ARGS__)
2995+#define is_ispctrl_debug_enabled() 1
2996+#else
2997+#define DPRINTK_ISPCTRL(format, ...)
2998+#define is_ispctrl_debug_enabled() 0
2999+#endif
3000+
3001+#ifdef OMAP_ISPCCDC_DEBUG
3002+#define DPRINTK_ISPCCDC(format, ...) \
3003+ printk(KERN_INFO "ISPCCDC: " format, ## __VA_ARGS__)
3004+#define is_ispccdc_debug_enabled() 1
3005+#else
3006+#define DPRINTK_ISPCCDC(format, ...)
3007+#define is_ispccdc_debug_enabled() 0
3008+#endif
3009+
3010+#ifdef OMAP_ISPPREV_DEBUG
3011+#define DPRINTK_ISPPREV(format, ...) \
3012+ printk(KERN_INFO "ISPPREV: " format, ## __VA_ARGS__)
3013+#define is_ispprev_debug_enabled() 1
3014+#else
3015+#define DPRINTK_ISPPREV(format, ...)
3016+#define is_ispprev_debug_enabled() 0
3017+#endif
3018+
3019+#ifdef OMAP_ISPRESZ_DEBUG
3020+#define DPRINTK_ISPRESZ(format, ...) \
3021+ printk(KERN_INFO "ISPRESZ: " format, ## __VA_ARGS__)
3022+#define is_ispresz_debug_enabled() 1
3023+#else
3024+#define DPRINTK_ISPRESZ(format, ...)
3025+#define is_ispresz_debug_enabled() 0
3026+#endif
3027+
3028+#ifdef OMAP_ISPMMU_DEBUG
3029+#define DPRINTK_ISPMMU(format, ...) \
3030+ printk(KERN_INFO "ISPMMU: " format, ## __VA_ARGS__)
3031+#define is_ispmmu_debug_enabled() 1
3032+#else
3033+#define DPRINTK_ISPMMU(format, ...)
3034+#define is_ispmmu_debug_enabled() 0
3035+#endif
3036+
3037+#ifdef OMAP_ISPH3A_DEBUG
3038+#define DPRINTK_ISPH3A(format, ...) \
3039+ printk(KERN_INFO "ISPH3A: " format, ## __VA_ARGS__)
3040+#define is_isph3a_debug_enabled() 1
3041+#else
3042+#define DPRINTK_ISPH3A(format, ...)
3043+#define is_isph3a_debug_enabled() 0
3044+#endif
3045+
3046+#ifdef OMAP_ISP_AF_DEBUG
3047+#define DPRINTK_ISP_AF(format, ...) \
3048+ printk(KERN_INFO "ISP_AF: " format, ## __VA_ARGS__)
3049+#define is_isp_af_debug_enabled() 1
3050+#else
3051+#define DPRINTK_ISP_AF(format, ...)
3052+#define is_isp_af_debug_enabled() 0
3053+#endif
3054+
3055+#ifdef OMAP_ISPHIST_DEBUG
3056+#define DPRINTK_ISPHIST(format, ...) \
3057+ printk(KERN_INFO "ISPHIST: " format, ## __VA_ARGS__)
3058+#define is_isphist_debug_enabled() 1
3059+#else
3060+#define DPRINTK_ISPHIST(format, ...)
3061+#define is_isphist_debug_enabled() 0
3062+#endif
3063+
3064+#define ISP_32B_BOUNDARY_BUF 0xFFFFFFE0
3065+#define ISP_32B_BOUNDARY_OFFSET 0x0000FFE0
3066+
3067+#define CM_CAM_MCLK_HZ 216000000
3068+
3069+/* ISP Submodules offset */
3070+
3071+#define OMAP3ISP_REG_BASE OMAP3430_ISP_BASE
3072+#define OMAP3ISP_REG(offset) (OMAP3ISP_REG_BASE + (offset))
3073+
3074+#define OMAP3ISP_CBUFF_REG_OFFSET 0x0100
3075+#define OMAP3ISP_CBUFF_REG_BASE (OMAP3ISP_REG_BASE + \
3076+ OMAP3ISP_CBUFF_REG_OFFSET)
3077+#define OMAP3ISP_CBUFF_REG(offset) (OMAP3ISP_CBUFF_REG_BASE + (offset))
3078+
3079+#define OMAP3ISP_CCP2_REG_OFFSET 0x0400
3080+#define OMAP3ISP_CCP2_REG_BASE (OMAP3ISP_REG_BASE + \
3081+ OMAP3ISP_CCP2_REG_OFFSET)
3082+#define OMAP3ISP_CCP2_REG(offset) (OMAP3ISP_CCP2_REG_BASE + (offset))
3083+
3084+#define OMAP3ISP_CCDC_REG_OFFSET 0x0600
3085+#define OMAP3ISP_CCDC_REG_BASE (OMAP3ISP_REG_BASE + \
3086+ OMAP3ISP_CCDC_REG_OFFSET)
3087+#define OMAP3ISP_CCDC_REG(offset) (OMAP3ISP_CCDC_REG_BASE + (offset))
3088+
3089+#define OMAP3ISP_HIST_REG_OFFSET 0x0A00
3090+#define OMAP3ISP_HIST_REG_BASE (OMAP3ISP_REG_BASE + \
3091+ OMAP3ISP_HIST_REG_OFFSET)
3092+#define OMAP3ISP_HIST_REG(offset) (OMAP3ISP_HIST_REG_BASE + (offset))
3093+
3094+#define OMAP3ISP_H3A_REG_OFFSET 0x0C00
3095+#define OMAP3ISP_H3A_REG_BASE (OMAP3ISP_REG_BASE + \
3096+ OMAP3ISP_H3A_REG_OFFSET)
3097+#define OMAP3ISP_H3A_REG(offset) (OMAP3ISP_H3A_REG_BASE + (offset))
3098+
3099+#define OMAP3ISP_PREV_REG_OFFSET 0x0E00
3100+#define OMAP3ISP_PREV_REG_BASE (OMAP3ISP_REG_BASE + \
3101+ OMAP3ISP_PREV_REG_OFFSET)
3102+#define OMAP3ISP_PREV_REG(offset) (OMAP3ISP_PREV_REG_BASE + (offset))
3103+
3104+#define OMAP3ISP_RESZ_REG_OFFSET 0x1000
3105+#define OMAP3ISP_RESZ_REG_BASE (OMAP3ISP_REG_BASE + \
3106+ OMAP3ISP_RESZ_REG_OFFSET)
3107+#define OMAP3ISP_RESZ_REG(offset) (OMAP3ISP_RESZ_REG_BASE + (offset))
3108+
3109+#define OMAP3ISP_SBL_REG_OFFSET 0x1200
3110+#define OMAP3ISP_SBL_REG_BASE (OMAP3ISP_REG_BASE + \
3111+ OMAP3ISP_SBL_REG_OFFSET)
3112+#define OMAP3ISP_SBL_REG(offset) (OMAP3ISP_SBL_REG_BASE + (offset))
3113+
3114+#define OMAP3ISP_MMU_REG_OFFSET 0x1400
3115+#define OMAP3ISP_MMU_REG_BASE (OMAP3ISP_REG_BASE + \
3116+ OMAP3ISP_MMU_REG_OFFSET)
3117+#define OMAP3ISP_MMU_REG(offset) (OMAP3ISP_MMU_REG_BASE + (offset))
3118+
3119+#define OMAP3ISP_CSI2A_REG_OFFSET 0x1800
3120+#define OMAP3ISP_CSI2A_REG_BASE (OMAP3ISP_REG_BASE + \
3121+ OMAP3ISP_CSI2A_REG_OFFSET)
3122+#define OMAP3ISP_CSI2A_REG(offset) (OMAP3ISP_CSI2A_REG_BASE + (offset))
3123+
3124+#define OMAP3ISP_CSI2PHY_REG_OFFSET 0x1970
3125+#define OMAP3ISP_CSI2PHY_REG_BASE (OMAP3ISP_REG_BASE + \
3126+ OMAP3ISP_CSI2PHY_REG_OFFSET)
3127+#define OMAP3ISP_CSI2PHY_REG(offset) (OMAP3ISP_CSI2PHY_REG_BASE + (offset))
3128+
3129+/* ISP module register offset */
3130+
3131+#define ISP_REVISION (0x000)
3132+#define ISP_SYSCONFIG (0x004)
3133+#define ISP_SYSSTATUS (0x008)
3134+#define ISP_IRQ0ENABLE (0x00C)
3135+#define ISP_IRQ0STATUS (0x010)
3136+#define ISP_IRQ1ENABLE (0x014)
3137+#define ISP_IRQ1STATUS (0x018)
3138+#define ISP_TCTRL_GRESET_LENGTH (0x030)
3139+#define ISP_TCTRL_PSTRB_REPLAY (0x034)
3140+#define ISP_CTRL (0x040)
3141+#define ISP_SECURE (0x044)
3142+#define ISP_TCTRL_CTRL (0x050)
3143+#define ISP_TCTRL_FRAME (0x054)
3144+#define ISP_TCTRL_PSTRB_DELAY (0x058)
3145+#define ISP_TCTRL_STRB_DELAY (0x05C)
3146+#define ISP_TCTRL_SHUT_DELAY (0x060)
3147+#define ISP_TCTRL_PSTRB_LENGTH (0x064)
3148+#define ISP_TCTRL_STRB_LENGTH (0x068)
3149+#define ISP_TCTRL_SHUT_LENGTH (0x06C)
3150+#define ISP_PING_PONG_ADDR (0x070)
3151+#define ISP_PING_PONG_MEM_RANGE (0x074)
3152+#define ISP_PING_PONG_BUF_SIZE (0x078)
3153+
3154+/* CSI1 receiver registers (ES2.0) */
3155+#define ISPCSI1_REVISION (0x000)
3156+#define ISPCSI1_SYSCONFIG (0x004)
3157+#define ISPCSI1_SYSSTATUS (0x008)
3158+#define ISPCSI1_LC01_IRQENABLE (0x00C)
3159+#define ISPCSI1_LC01_IRQSTATUS (0x010)
3160+#define ISPCSI1_LC23_IRQENABLE (0x014)
3161+#define ISPCSI1_LC23_IRQSTATUS (0x018)
3162+#define ISPCSI1_LCM_IRQENABLE (0x02C)
3163+#define ISPCSI1_LCM_IRQSTATUS (0x030)
3164+#define ISPCSI1_CTRL (0x040)
3165+#define ISPCSI1_DBG (0x044)
3166+#define ISPCSI1_GNQ (0x048)
3167+#define ISPCSI1_LCx_CTRL(x) ((0x050)+0x30*(x))
3168+#define ISPCSI1_LCx_CODE(x) ((0x054)+0x30*(x))
3169+#define ISPCSI1_LCx_STAT_START(x) ((0x058)+0x30*(x))
3170+#define ISPCSI1_LCx_STAT_SIZE(x) ((0x05C)+0x30*(x))
3171+#define ISPCSI1_LCx_SOF_ADDR(x) ((0x060)+0x30*(x))
3172+#define ISPCSI1_LCx_EOF_ADDR(x) ((0x064)+0x30*(x))
3173+#define ISPCSI1_LCx_DAT_START(x) ((0x068)+0x30*(x))
3174+#define ISPCSI1_LCx_DAT_SIZE(x) ((0x06C)+0x30*(x))
3175+#define ISPCSI1_LCx_DAT_PING_ADDR(x) ((0x070)+0x30*(x))
3176+#define ISPCSI1_LCx_DAT_PONG_ADDR(x) ((0x074)+0x30*(x))
3177+#define ISPCSI1_LCx_DAT_OFST(x) ((0x078)+0x30*(x))
3178+#define ISPCSI1_LCM_CTRL (0x1D0)
3179+#define ISPCSI1_LCM_VSIZE (0x1D4)
3180+#define ISPCSI1_LCM_HSIZE (0x1D8)
3181+#define ISPCSI1_LCM_PREFETCH (0x1DC)
3182+#define ISPCSI1_LCM_SRC_ADDR (0x1E0)
3183+#define ISPCSI1_LCM_SRC_OFST (0x1E4)
3184+#define ISPCSI1_LCM_DST_ADDR (0x1E8)
3185+#define ISPCSI1_LCM_DST_OFST (0x1EC)
3186+#define ISP_CSIB_SYSCONFIG ISPCSI1_SYSCONFIG
3187+#define ISP_CSIA_SYSCONFIG ISPCSI2_SYSCONFIG
3188+
3189+/* ISP_CBUFF Registers */
3190+
3191+#define ISP_CBUFF_SYSCONFIG (0x010)
3192+#define ISP_CBUFF_IRQENABLE (0x01C)
3193+
3194+#define ISP_CBUFF0_CTRL (0x020)
3195+#define ISP_CBUFF1_CTRL (0x024)
3196+
3197+#define ISP_CBUFF0_START (0x040)
3198+#define ISP_CBUFF1_START (0x044)
3199+
3200+#define ISP_CBUFF0_END (0x050)
3201+#define ISP_CBUFF1_END (0x054)
3202+
3203+#define ISP_CBUFF0_WINDOWSIZE (0x060)
3204+#define ISP_CBUFF1_WINDOWSIZE (0x064)
3205+
3206+#define ISP_CBUFF0_THRESHOLD (0x070)
3207+#define ISP_CBUFF1_THRESHOLD (0x074)
3208+
3209+/* CCDC module register offset */
3210+
3211+#define ISPCCDC_PID (0x000)
3212+#define ISPCCDC_PCR (0x004)
3213+#define ISPCCDC_SYN_MODE (0x008)
3214+#define ISPCCDC_HD_VD_WID (0x00C)
3215+#define ISPCCDC_PIX_LINES (0x010)
3216+#define ISPCCDC_HORZ_INFO (0x014)
3217+#define ISPCCDC_VERT_START (0x018)
3218+#define ISPCCDC_VERT_LINES (0x01C)
3219+#define ISPCCDC_CULLING (0x020)
3220+#define ISPCCDC_HSIZE_OFF (0x024)
3221+#define ISPCCDC_SDOFST (0x028)
3222+#define ISPCCDC_SDR_ADDR (0x02C)
3223+#define ISPCCDC_CLAMP (0x030)
3224+#define ISPCCDC_DCSUB (0x034)
3225+#define ISPCCDC_COLPTN (0x038)
3226+#define ISPCCDC_BLKCMP (0x03C)
3227+#define ISPCCDC_FPC (0x040)
3228+#define ISPCCDC_FPC_ADDR (0x044)
3229+#define ISPCCDC_VDINT (0x048)
3230+#define ISPCCDC_ALAW (0x04C)
3231+#define ISPCCDC_REC656IF (0x050)
3232+#define ISPCCDC_CFG (0x054)
3233+#define ISPCCDC_FMTCFG (0x058)
3234+#define ISPCCDC_FMT_HORZ (0x05C)
3235+#define ISPCCDC_FMT_VERT (0x060)
3236+#define ISPCCDC_FMT_ADDR0 (0x064)
3237+#define ISPCCDC_FMT_ADDR1 (0x068)
3238+#define ISPCCDC_FMT_ADDR2 (0x06C)
3239+#define ISPCCDC_FMT_ADDR3 (0x070)
3240+#define ISPCCDC_FMT_ADDR4 (0x074)
3241+#define ISPCCDC_FMT_ADDR5 (0x078)
3242+#define ISPCCDC_FMT_ADDR6 (0x07C)
3243+#define ISPCCDC_FMT_ADDR7 (0x080)
3244+#define ISPCCDC_PRGEVEN0 (0x084)
3245+#define ISPCCDC_PRGEVEN1 (0x088)
3246+#define ISPCCDC_PRGODD0 (0x08C)
3247+#define ISPCCDC_PRGODD1 (0x090)
3248+#define ISPCCDC_VP_OUT (0x094)
3249+
3250+#define ISPCCDC_LSC_CONFIG (0x098)
3251+#define ISPCCDC_LSC_INITIAL (0x09C)
3252+#define ISPCCDC_LSC_TABLE_BASE (0x0A0)
3253+#define ISPCCDC_LSC_TABLE_OFFSET (0x0A4)
3254+
3255+/* SBL */
3256+#define ISPSBL_CCDC_WR_0 (0x028)
3257+#define ISPSBL_CCDC_WR_0_DATA_READY (1 << 21)
3258+#define ISPSBL_CCDC_WR_1 (0x02C)
3259+#define ISPSBL_CCDC_WR_2 (0x030)
3260+#define ISPSBL_CCDC_WR_3 (0x034)
3261+
3262+/* Histogram registers */
3263+#define ISPHIST_PID (0x000)
3264+#define ISPHIST_PCR (0x004)
3265+#define ISPHIST_CNT (0x008)
3266+#define ISPHIST_WB_GAIN (0x00C)
3267+#define ISPHIST_R0_HORZ (0x010)
3268+#define ISPHIST_R0_VERT (0x014)
3269+#define ISPHIST_R1_HORZ (0x018)
3270+#define ISPHIST_R1_VERT (0x01C)
3271+#define ISPHIST_R2_HORZ (0x020)
3272+#define ISPHIST_R2_VERT (0x024)
3273+#define ISPHIST_R3_HORZ (0x028)
3274+#define ISPHIST_R3_VERT (0x02C)
3275+#define ISPHIST_ADDR (0x030)
3276+#define ISPHIST_DATA (0x034)
3277+#define ISPHIST_RADD (0x038)
3278+#define ISPHIST_RADD_OFF (0x03C)
3279+#define ISPHIST_H_V_INFO (0x040)
3280+
3281+/* H3A module registers */
3282+#define ISPH3A_PID (0x000)
3283+#define ISPH3A_PCR (0x004)
3284+#define ISPH3A_AEWWIN1 (0x04C)
3285+#define ISPH3A_AEWINSTART (0x050)
3286+#define ISPH3A_AEWINBLK (0x054)
3287+#define ISPH3A_AEWSUBWIN (0x058)
3288+#define ISPH3A_AEWBUFST (0x05C)
3289+#define ISPH3A_AFPAX1 (0x008)
3290+#define ISPH3A_AFPAX2 (0x00C)
3291+#define ISPH3A_AFPAXSTART (0x010)
3292+#define ISPH3A_AFIIRSH (0x014)
3293+#define ISPH3A_AFBUFST (0x018)
3294+#define ISPH3A_AFCOEF010 (0x01C)
3295+#define ISPH3A_AFCOEF032 (0x020)
3296+#define ISPH3A_AFCOEF054 (0x024)
3297+#define ISPH3A_AFCOEF076 (0x028)
3298+#define ISPH3A_AFCOEF098 (0x02C)
3299+#define ISPH3A_AFCOEF0010 (0x030)
3300+#define ISPH3A_AFCOEF110 (0x034)
3301+#define ISPH3A_AFCOEF132 (0x038)
3302+#define ISPH3A_AFCOEF154 (0x03C)
3303+#define ISPH3A_AFCOEF176 (0x040)
3304+#define ISPH3A_AFCOEF198 (0x044)
3305+#define ISPH3A_AFCOEF1010 (0x048)
3306+
3307+#define ISPPRV_PCR (0x004)
3308+#define ISPPRV_HORZ_INFO (0x008)
3309+#define ISPPRV_VERT_INFO (0x00C)
3310+#define ISPPRV_RSDR_ADDR (0x010)
3311+#define ISPPRV_RADR_OFFSET (0x014)
3312+#define ISPPRV_DSDR_ADDR (0x018)
3313+#define ISPPRV_DRKF_OFFSET (0x01C)
3314+#define ISPPRV_WSDR_ADDR (0x020)
3315+#define ISPPRV_WADD_OFFSET (0x024)
3316+#define ISPPRV_AVE (0x028)
3317+#define ISPPRV_HMED (0x02C)
3318+#define ISPPRV_NF (0x030)
3319+#define ISPPRV_WB_DGAIN (0x034)
3320+#define ISPPRV_WBGAIN (0x038)
3321+#define ISPPRV_WBSEL (0x03C)
3322+#define ISPPRV_CFA (0x040)
3323+#define ISPPRV_BLKADJOFF (0x044)
3324+#define ISPPRV_RGB_MAT1 (0x048)
3325+#define ISPPRV_RGB_MAT2 (0x04C)
3326+#define ISPPRV_RGB_MAT3 (0x050)
3327+#define ISPPRV_RGB_MAT4 (0x054)
3328+#define ISPPRV_RGB_MAT5 (0x058)
3329+#define ISPPRV_RGB_OFF1 (0x05C)
3330+#define ISPPRV_RGB_OFF2 (0x060)
3331+#define ISPPRV_CSC0 (0x064)
3332+#define ISPPRV_CSC1 (0x068)
3333+#define ISPPRV_CSC2 (0x06C)
3334+#define ISPPRV_CSC_OFFSET (0x070)
3335+#define ISPPRV_CNT_BRT (0x074)
3336+#define ISPPRV_CSUP (0x078)
3337+#define ISPPRV_SETUP_YC (0x07C)
3338+#define ISPPRV_SET_TBL_ADDR (0x080)
3339+#define ISPPRV_SET_TBL_DATA (0x084)
3340+#define ISPPRV_CDC_THR0 (0x090)
3341+#define ISPPRV_CDC_THR1 (ISPPRV_CDC_THR0 + (0x4))
3342+#define ISPPRV_CDC_THR2 (ISPPRV_CDC_THR0 + (0x4) * 2)
3343+#define ISPPRV_CDC_THR3 (ISPPRV_CDC_THR0 + (0x4) * 3)
3344+
3345+#define ISPPRV_REDGAMMA_TABLE_ADDR 0x0000
3346+#define ISPPRV_GREENGAMMA_TABLE_ADDR 0x0400
3347+#define ISPPRV_BLUEGAMMA_TABLE_ADDR 0x0800
3348+#define ISPPRV_NF_TABLE_ADDR 0x0C00
3349+#define ISPPRV_YENH_TABLE_ADDR 0x1000
3350+#define ISPPRV_CFA_TABLE_ADDR 0x1400
3351+
3352+#define ISPPRV_MAXOUTPUT_WIDTH 1280
3353+#define ISPPRV_MAXOUTPUT_WIDTH_ES2 3300
3354+#define ISPRSZ_MIN_OUTPUT 64
3355+#define ISPRSZ_MAX_OUTPUT 3312
3356+
3357+/* Resizer module register offset */
3358+#define ISPRSZ_PID (0x000)
3359+#define ISPRSZ_PCR (0x004)
3360+#define ISPRSZ_CNT (0x008)
3361+#define ISPRSZ_OUT_SIZE (0x00C)
3362+#define ISPRSZ_IN_START (0x010)
3363+#define ISPRSZ_IN_SIZE (0x014)
3364+#define ISPRSZ_SDR_INADD (0x018)
3365+#define ISPRSZ_SDR_INOFF (0x01C)
3366+#define ISPRSZ_SDR_OUTADD (0x020)
3367+#define ISPRSZ_SDR_OUTOFF (0x024)
3368+#define ISPRSZ_HFILT10 (0x028)
3369+#define ISPRSZ_HFILT32 (0x02C)
3370+#define ISPRSZ_HFILT54 (0x030)
3371+#define ISPRSZ_HFILT76 (0x034)
3372+#define ISPRSZ_HFILT98 (0x038)
3373+#define ISPRSZ_HFILT1110 (0x03C)
3374+#define ISPRSZ_HFILT1312 (0x040)
3375+#define ISPRSZ_HFILT1514 (0x044)
3376+#define ISPRSZ_HFILT1716 (0x048)
3377+#define ISPRSZ_HFILT1918 (0x04C)
3378+#define ISPRSZ_HFILT2120 (0x050)
3379+#define ISPRSZ_HFILT2322 (0x054)
3380+#define ISPRSZ_HFILT2524 (0x058)
3381+#define ISPRSZ_HFILT2726 (0x05C)
3382+#define ISPRSZ_HFILT2928 (0x060)
3383+#define ISPRSZ_HFILT3130 (0x064)
3384+#define ISPRSZ_VFILT10 (0x068)
3385+#define ISPRSZ_VFILT32 (0x06C)
3386+#define ISPRSZ_VFILT54 (0x070)
3387+#define ISPRSZ_VFILT76 (0x074)
3388+#define ISPRSZ_VFILT98 (0x078)
3389+#define ISPRSZ_VFILT1110 (0x07C)
3390+#define ISPRSZ_VFILT1312 (0x080)
3391+#define ISPRSZ_VFILT1514 (0x084)
3392+#define ISPRSZ_VFILT1716 (0x088)
3393+#define ISPRSZ_VFILT1918 (0x08C)
3394+#define ISPRSZ_VFILT2120 (0x090)
3395+#define ISPRSZ_VFILT2322 (0x094)
3396+#define ISPRSZ_VFILT2524 (0x098)
3397+#define ISPRSZ_VFILT2726 (0x09C)
3398+#define ISPRSZ_VFILT2928 (0x0A0)
3399+#define ISPRSZ_VFILT3130 (0x0A4)
3400+#define ISPRSZ_YENH (0x0A8)
3401+
3402+/* MMU module registers */
3403+#define ISPMMU_REVISION (0x000)
3404+#define ISPMMU_SYSCONFIG (0x010)
3405+#define ISPMMU_SYSSTATUS (0x014)
3406+#define ISPMMU_IRQSTATUS (0x018)
3407+#define ISPMMU_IRQENABLE (0x01C)
3408+#define ISPMMU_WALKING_ST (0x040)
3409+#define ISPMMU_CNTL (0x044)
3410+#define ISPMMU_FAULT_AD (0x048)
3411+#define ISPMMU_TTB (0x04C)
3412+#define ISPMMU_LOCK (0x050)
3413+#define ISPMMU_LD_TLB (0x054)
3414+#define ISPMMU_CAM (0x058)
3415+#define ISPMMU_RAM (0x05C)
3416+#define ISPMMU_GFLUSH (0x060)
3417+#define ISPMMU_FLUSH_ENTRY (0x064)
3418+#define ISPMMU_READ_CAM (0x068)
3419+#define ISPMMU_READ_RAM (0x06c)
3420+#define ISPMMU_EMU_FAULT_AD (0x070)
3421+
3422+#define ISP_INT_CLR 0xFF113F11
3423+#define ISPPRV_PCR_EN 1
3424+#define ISPPRV_PCR_BUSY (1 << 1)
3425+#define ISPPRV_PCR_SOURCE (1 << 2)
3426+#define ISPPRV_PCR_ONESHOT (1 << 3)
3427+#define ISPPRV_PCR_WIDTH (1 << 4)
3428+#define ISPPRV_PCR_INVALAW (1 << 5)
3429+#define ISPPRV_PCR_DRKFEN (1 << 6)
3430+#define ISPPRV_PCR_DRKFCAP (1 << 7)
3431+#define ISPPRV_PCR_HMEDEN (1 << 8)
3432+#define ISPPRV_PCR_NFEN (1 << 9)
3433+#define ISPPRV_PCR_CFAEN (1 << 10)
3434+#define ISPPRV_PCR_CFAFMT_SHIFT 11
3435+#define ISPPRV_PCR_CFAFMT_MASK 0x7800
3436+#define ISPPRV_PCR_CFAFMT_BAYER (0 << 11)
3437+#define ISPPRV_PCR_CFAFMT_SONYVGA (1 << 11)
3438+#define ISPPRV_PCR_CFAFMT_RGBFOVEON (2 << 11)
3439+#define ISPPRV_PCR_CFAFMT_DNSPL (3 << 11)
3440+#define ISPPRV_PCR_CFAFMT_HONEYCOMB (4 << 11)
3441+#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON (5 << 11)
3442+#define ISPPRV_PCR_YNENHEN (1 << 15)
3443+#define ISPPRV_PCR_SUPEN (1 << 16)
3444+#define ISPPRV_PCR_YCPOS_SHIFT 17
3445+#define ISPPRV_PCR_YCPOS_YCrYCb (0 << 17)
3446+#define ISPPRV_PCR_YCPOS_YCbYCr (1 << 17)
3447+#define ISPPRV_PCR_YCPOS_CbYCrY (2 << 17)
3448+#define ISPPRV_PCR_YCPOS_CrYCbY (3 << 17)
3449+#define ISPPRV_PCR_RSZPORT (1 << 19)
3450+#define ISPPRV_PCR_SDRPORT (1 << 20)
3451+#define ISPPRV_PCR_SCOMP_EN (1 << 21)
3452+#define ISPPRV_PCR_SCOMP_SFT_SHIFT (22)
3453+#define ISPPRV_PCR_SCOMP_SFT_MASK (~(7 << 22))
3454+#define ISPPRV_PCR_GAMMA_BYPASS (1 << 26)
3455+#define ISPPRV_PCR_DCOREN (1 << 27)
3456+#define ISPPRV_PCR_DCCOUP (1 << 28)
3457+#define ISPPRV_PCR_DRK_FAIL (1 << 31)
3458+
3459+#define ISPPRV_HORZ_INFO_EPH_SHIFT 0
3460+#define ISPPRV_HORZ_INFO_EPH_MASK 0x3fff
3461+#define ISPPRV_HORZ_INFO_SPH_SHIFT 16
3462+#define ISPPRV_HORZ_INFO_SPH_MASK 0x3fff0
3463+
3464+#define ISPPRV_VERT_INFO_ELV_SHIFT 0
3465+#define ISPPRV_VERT_INFO_ELV_MASK 0x3fff
3466+#define ISPPRV_VERT_INFO_SLV_SHIFT 16
3467+#define ISPPRV_VERT_INFO_SLV_MASK 0x3fff0
3468+
3469+#define ISPPRV_AVE_EVENDIST_SHIFT 2
3470+#define ISPPRV_AVE_EVENDIST_1 0x0
3471+#define ISPPRV_AVE_EVENDIST_2 0x1
3472+#define ISPPRV_AVE_EVENDIST_3 0x2
3473+#define ISPPRV_AVE_EVENDIST_4 0x3
3474+#define ISPPRV_AVE_ODDDIST_SHIFT 4
3475+#define ISPPRV_AVE_ODDDIST_1 0x0
3476+#define ISPPRV_AVE_ODDDIST_2 0x1
3477+#define ISPPRV_AVE_ODDDIST_3 0x2
3478+#define ISPPRV_AVE_ODDDIST_4 0x3
3479+
3480+#define ISPPRV_HMED_THRESHOLD_SHIFT 0
3481+#define ISPPRV_HMED_EVENDIST (1 << 8)
3482+#define ISPPRV_HMED_ODDDIST (1 << 9)
3483+
3484+#define ISPPRV_WBGAIN_COEF0_SHIFT 0
3485+#define ISPPRV_WBGAIN_COEF1_SHIFT 8
3486+#define ISPPRV_WBGAIN_COEF2_SHIFT 16
3487+#define ISPPRV_WBGAIN_COEF3_SHIFT 24
3488+
3489+#define ISPPRV_WBSEL_COEF0 0x0
3490+#define ISPPRV_WBSEL_COEF1 0x1
3491+#define ISPPRV_WBSEL_COEF2 0x2
3492+#define ISPPRV_WBSEL_COEF3 0x3
3493+
3494+#define ISPPRV_WBSEL_N0_0_SHIFT 0
3495+#define ISPPRV_WBSEL_N0_1_SHIFT 2
3496+#define ISPPRV_WBSEL_N0_2_SHIFT 4
3497+#define ISPPRV_WBSEL_N0_3_SHIFT 6
3498+#define ISPPRV_WBSEL_N1_0_SHIFT 8
3499+#define ISPPRV_WBSEL_N1_1_SHIFT 10
3500+#define ISPPRV_WBSEL_N1_2_SHIFT 12
3501+#define ISPPRV_WBSEL_N1_3_SHIFT 14
3502+#define ISPPRV_WBSEL_N2_0_SHIFT 16
3503+#define ISPPRV_WBSEL_N2_1_SHIFT 18
3504+#define ISPPRV_WBSEL_N2_2_SHIFT 20
3505+#define ISPPRV_WBSEL_N2_3_SHIFT 22
3506+#define ISPPRV_WBSEL_N3_0_SHIFT 24
3507+#define ISPPRV_WBSEL_N3_1_SHIFT 26
3508+#define ISPPRV_WBSEL_N3_2_SHIFT 28
3509+#define ISPPRV_WBSEL_N3_3_SHIFT 30
3510+
3511+#define ISPPRV_CFA_GRADTH_HOR_SHIFT 0
3512+#define ISPPRV_CFA_GRADTH_VER_SHIFT 8
3513+
3514+#define ISPPRV_BLKADJOFF_B_SHIFT 0
3515+#define ISPPRV_BLKADJOFF_G_SHIFT 8
3516+#define ISPPRV_BLKADJOFF_R_SHIFT 16
3517+
3518+#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT 0
3519+#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT 16
3520+
3521+#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT 0
3522+#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT 16
3523+
3524+#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT 0
3525+#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT 16
3526+
3527+#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT 0
3528+#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT 16
3529+
3530+#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT 0
3531+
3532+#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT 0
3533+#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT 16
3534+
3535+#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT 0
3536+
3537+#define ISPPRV_CSC0_RY_SHIFT 0
3538+#define ISPPRV_CSC0_GY_SHIFT 10
3539+#define ISPPRV_CSC0_BY_SHIFT 20
3540+
3541+#define ISPPRV_CSC1_RCB_SHIFT 0
3542+#define ISPPRV_CSC1_GCB_SHIFT 10
3543+#define ISPPRV_CSC1_BCB_SHIFT 20
3544+
3545+#define ISPPRV_CSC2_RCR_SHIFT 0
3546+#define ISPPRV_CSC2_GCR_SHIFT 10
3547+#define ISPPRV_CSC2_BCR_SHIFT 20
3548+
3549+#define ISPPRV_CSC_OFFSET_CR_SHIFT 0
3550+#define ISPPRV_CSC_OFFSET_CB_SHIFT 8
3551+#define ISPPRV_CSC_OFFSET_Y_SHIFT 16
3552+
3553+#define ISPPRV_CNT_BRT_BRT_SHIFT 0
3554+#define ISPPRV_CNT_BRT_CNT_SHIFT 8
3555+
3556+#define ISPPRV_CONTRAST_MAX 0x10
3557+#define ISPPRV_CONTRAST_MIN 0xFF
3558+#define ISPPRV_BRIGHT_MIN 0x00
3559+#define ISPPRV_BRIGHT_MAX 0xFF
3560+
3561+#define ISPPRV_CSUP_CSUPG_SHIFT 0
3562+#define ISPPRV_CSUP_THRES_SHIFT 8
3563+#define ISPPRV_CSUP_HPYF_SHIFT 16
3564+
3565+#define ISPPRV_SETUP_YC_MINC_SHIFT 0
3566+#define ISPPRV_SETUP_YC_MAXC_SHIFT 8
3567+#define ISPPRV_SETUP_YC_MINY_SHIFT 16
3568+#define ISPPRV_SETUP_YC_MAXY_SHIFT 24
3569+#define ISPPRV_YC_MAX 0xFF
3570+#define ISPPRV_YC_MIN 0x0
3571+
3572+/* Define bit fields within selected registers */
3573+#define ISP_REVISION_SHIFT 0
3574+
3575+#define ISP_SYSCONFIG_AUTOIDLE 0
3576+#define ISP_SYSCONFIG_SOFTRESET (1 << 1)
3577+#define ISP_SYSCONFIG_MIDLEMODE_SHIFT 12
3578+#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY 0x0
3579+#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY 0x1
3580+#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY 0x2
3581+
3582+#define ISP_SYSSTATUS_RESETDONE 0
3583+
3584+#define IRQ0ENABLE_CSIA_IRQ 1
3585+#define IRQ0ENABLE_CSIA_LC1_IRQ (1 << 1)
3586+#define IRQ0ENABLE_CSIA_LC2_IRQ (1 << 2)
3587+#define IRQ0ENABLE_CSIA_LC3_IRQ (1 << 3)
3588+#define IRQ0ENABLE_CSIB_IRQ (1 << 4)
3589+#define IRQ0ENABLE_CSIB_LC1_IRQ (1 << 5)
3590+#define IRQ0ENABLE_CSIB_LC2_IRQ (1 << 6)
3591+#define IRQ0ENABLE_CSIB_LC3_IRQ (1 << 7)
3592+#define IRQ0ENABLE_CCDC_VD0_IRQ (1 << 8)
3593+#define IRQ0ENABLE_CCDC_VD1_IRQ (1 << 9)
3594+#define IRQ0ENABLE_CCDC_VD2_IRQ (1 << 10)
3595+#define IRQ0ENABLE_CCDC_ERR_IRQ (1 << 11)
3596+#define IRQ0ENABLE_H3A_AF_DONE_IRQ (1 << 12)
3597+#define IRQ0ENABLE_H3A_AWB_DONE_IRQ (1 << 13)
3598+#define IRQ0ENABLE_HIST_DONE_IRQ (1 << 16)
3599+#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ (1 << 17)
3600+#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ (1 << 18)
3601+#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ (1 << 19)
3602+#define IRQ0ENABLE_PRV_DONE_IRQ (1 << 20)
3603+#define IRQ0ENABLE_RSZ_DONE_IRQ (1 << 24)
3604+#define IRQ0ENABLE_OVF_IRQ (1 << 25)
3605+#define IRQ0ENABLE_PING_IRQ (1 << 26)
3606+#define IRQ0ENABLE_PONG_IRQ (1 << 27)
3607+#define IRQ0ENABLE_MMU_ERR_IRQ (1 << 28)
3608+#define IRQ0ENABLE_OCP_ERR_IRQ (1 << 29)
3609+#define IRQ0ENABLE_SEC_ERR_IRQ (1 << 30)
3610+#define IRQ0ENABLE_HS_VS_IRQ (1 << 31)
3611+
3612+#define IRQ0STATUS_CSIA_IRQ 1
3613+#define IRQ0STATUS_CSIA_LC1_IRQ (1 << 1)
3614+#define IRQ0STATUS_CSIA_LC2_IRQ (1 << 2)
3615+#define IRQ0STATUS_CSIA_LC3_IRQ (1 << 3)
3616+#define IRQ0STATUS_CSIB_IRQ (1 << 4)
3617+#define IRQ0STATUS_CSIB_LC1_IRQ (1 << 5)
3618+#define IRQ0STATUS_CSIB_LC2_IRQ (1 << 6)
3619+#define IRQ0STATUS_CSIB_LC3_IRQ (1 << 7)
3620+#define IRQ0STATUS_CCDC_VD0_IRQ (1 << 8)
3621+#define IRQ0STATUS_CCDC_VD1_IRQ (1 << 9)
3622+#define IRQ0STATUS_CCDC_VD2_IRQ (1 << 10)
3623+#define IRQ0STATUS_CCDC_ERR_IRQ (1 << 11)
3624+#define IRQ0STATUS_H3A_AF_DONE_IRQ (1 << 12)
3625+#define IRQ0STATUS_H3A_AWB_DONE_IRQ (1 << 13)
3626+#define IRQ0STATUS_HIST_DONE_IRQ (1 << 16)
3627+#define IRQ0STATUS_PRV_DONE_IRQ (1 << 20)
3628+#define IRQ0STATUS_RSZ_DONE_IRQ (1 << 24)
3629+#define IRQ0STATUS_OVF_IRQ (1 << 25)
3630+#define IRQ0STATUS_PING_IRQ (1 << 26)
3631+#define IRQ0STATUS_PONG_IRQ (1 << 27)
3632+#define IRQ0STATUS_MMU_ERR_IRQ (1 << 28)
3633+#define IRQ0STATUS_OCP_ERR_IRQ (1 << 29)
3634+#define IRQ0STATUS_SEC_ERR_IRQ (1 << 30)
3635+#define IRQ0STATUS_HS_VS_IRQ (1 << 31)
3636+
3637+#define TCTRL_GRESET_LEN 0
3638+
3639+#define TCTRL_PSTRB_REPLAY_DELAY 0
3640+#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT 25
3641+
3642+#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL 0x0
3643+#define ISPCTRL_PAR_SER_CLK_SEL_CSIA 0x1
3644+#define ISPCTRL_PAR_SER_CLK_SEL_CSIB 0x2
3645+#define ISPCTRL_PAR_SER_CLK_SEL_MASK 0xFFFFFFFC
3646+
3647+#define ISPCTRL_PAR_BRIDGE_SHIFT 2
3648+#define ISPCTRL_PAR_BRIDGE_DISABLE (0x0 << 2)
3649+#define ISPCTRL_PAR_BRIDGE_LENDIAN (0x2 << 2)
3650+#define ISPCTRL_PAR_BRIDGE_BENDIAN (0x3 << 2)
3651+
3652+#define ISPCTRL_PAR_CLK_POL_SHIFT 4
3653+#define ISPCTRL_PAR_CLK_POL_INV (1 << 4)
3654+#define ISPCTRL_PING_PONG_EN (1 << 5)
3655+#define ISPCTRL_SHIFT_SHIFT 6
3656+#define ISPCTRL_SHIFT_0 (0x0 << 6)
3657+#define ISPCTRL_SHIFT_2 (0x1 << 6)
3658+#define ISPCTRL_SHIFT_4 (0x2 << 6)
3659+#define ISPCTRL_SHIFT_MASK (~(0x3 << 6))
3660+
3661+#define ISPCTRL_CCDC_CLK_EN (1 << 8)
3662+#define ISPCTRL_SCMP_CLK_EN (1 << 9)
3663+#define ISPCTRL_H3A_CLK_EN (1 << 10)
3664+#define ISPCTRL_HIST_CLK_EN (1 << 11)
3665+#define ISPCTRL_PREV_CLK_EN (1 << 12)
3666+#define ISPCTRL_RSZ_CLK_EN (1 << 13)
3667+#define ISPCTRL_SYNC_DETECT_SHIFT 14
3668+#define ISPCTRL_SYNC_DETECT_HSFALL (0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
3669+#define ISPCTRL_SYNC_DETECT_HSRISE (0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
3670+#define ISPCTRL_SYNC_DETECT_VSFALL (0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
3671+#define ISPCTRL_SYNC_DETECT_VSRISE (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
3672+#define ISPCTRL_SYNC_DETECT_MASK (0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
3673+
3674+#define ISPCTRL_CCDC_RAM_EN (1 << 16)
3675+#define ISPCTRL_PREV_RAM_EN (1 << 17)
3676+#define ISPCTRL_SBL_RD_RAM_EN (1 << 18)
3677+#define ISPCTRL_SBL_WR1_RAM_EN (1 << 19)
3678+#define ISPCTRL_SBL_WR0_RAM_EN (1 << 20)
3679+#define ISPCTRL_SBL_AUTOIDLE (1 << 21)
3680+#define ISPCTRL_SBL_SHARED_RPORTB (1 << 28)
3681+#define ISPCTRL_JPEG_FLUSH (1 << 30)
3682+#define ISPCTRL_CCDC_FLUSH (1 << 31)
3683+
3684+#define ISPSECURE_SECUREMODE 0
3685+
3686+#define ISPTCTRL_CTRL_DIV_LOW 0x0
3687+#define ISPTCTRL_CTRL_DIV_HIGH 0x1
3688+#define ISPTCTRL_CTRL_DIV_BYPASS 0x1F
3689+
3690+#define ISPTCTRL_CTRL_DIVA_SHIFT 0
3691+#define ISPTCTRL_CTRL_DIVA_MASK (0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
3692+
3693+#define ISPTCTRL_CTRL_DIVB_SHIFT 5
3694+#define ISPTCTRL_CTRL_DIVB_MASK (0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
3695+
3696+#define ISPTCTRL_CTRL_DIVC_SHIFT 10
3697+#define ISPTCTRL_CTRL_DIVC_NOCLOCK (0x0 << 10)
3698+
3699+#define ISPTCTRL_CTRL_SHUTEN (1 << 21)
3700+#define ISPTCTRL_CTRL_PSTRBEN (1 << 22)
3701+#define ISPTCTRL_CTRL_STRBEN (1 << 23)
3702+#define ISPTCTRL_CTRL_SHUTPOL (1 << 24)
3703+#define ISPTCTRL_CTRL_STRBPSTRBPOL (1 << 26)
3704+
3705+#define ISPTCTRL_CTRL_INSEL_SHIFT 27
3706+#define ISPTCTRL_CTRL_INSEL_PARALLEL (0x0 << 27)
3707+#define ISPTCTRL_CTRL_INSEL_CSIA (0x1 << 27)
3708+#define ISPTCTRL_CTRL_INSEL_CSIB (0x2 << 27)
3709+
3710+#define ISPTCTRL_CTRL_GRESETEn (1 << 29)
3711+#define ISPTCTRL_CTRL_GRESETPOL (1 << 30)
3712+#define ISPTCTRL_CTRL_GRESETDIR (1 << 31)
3713+
3714+#define ISPTCTRL_FRAME_SHUT_SHIFT 0
3715+#define ISPTCTRL_FRAME_PSTRB_SHIFT 6
3716+#define ISPTCTRL_FRAME_STRB_SHIFT 12
3717+
3718+#define ISPCCDC_PID_PREV_SHIFT 0
3719+#define ISPCCDC_PID_CID_SHIFT 8
3720+#define ISPCCDC_PID_TID_SHIFT 16
3721+
3722+#define ISPCCDC_PCR_EN 1
3723+#define ISPCCDC_PCR_BUSY (1 << 1)
3724+
3725+#define ISPCCDC_SYN_MODE_VDHDOUT 0x1
3726+#define ISPCCDC_SYN_MODE_FLDOUT (1 << 1)
3727+#define ISPCCDC_SYN_MODE_VDPOL (1 << 2)
3728+#define ISPCCDC_SYN_MODE_HDPOL (1 << 3)
3729+#define ISPCCDC_SYN_MODE_FLDPOL (1 << 4)
3730+#define ISPCCDC_SYN_MODE_EXWEN (1 << 5)
3731+#define ISPCCDC_SYN_MODE_DATAPOL (1 << 6)
3732+#define ISPCCDC_SYN_MODE_FLDMODE (1 << 7)
3733+#define ISPCCDC_SYN_MODE_DATSIZ_MASK 0xFFFFF8FF
3734+#define ISPCCDC_SYN_MODE_DATSIZ_8_16 (0x0 << 8)
3735+#define ISPCCDC_SYN_MODE_DATSIZ_12 (0x4 << 8)
3736+#define ISPCCDC_SYN_MODE_DATSIZ_11 (0x5 << 8)
3737+#define ISPCCDC_SYN_MODE_DATSIZ_10 (0x6 << 8)
3738+#define ISPCCDC_SYN_MODE_DATSIZ_8 (0x7 << 8)
3739+#define ISPCCDC_SYN_MODE_PACK8 (1 << 11)
3740+#define ISPCCDC_SYN_MODE_INPMOD_MASK 0xFFFFCFFF
3741+#define ISPCCDC_SYN_MODE_INPMOD_RAW (0 << 12)
3742+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16 (1 << 12)
3743+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8 (2 << 12)
3744+#define ISPCCDC_SYN_MODE_LPF (1 << 14)
3745+#define ISPCCDC_SYN_MODE_FLDSTAT (1 << 15)
3746+#define ISPCCDC_SYN_MODE_VDHDEN (1 << 16)
3747+#define ISPCCDC_SYN_MODE_WEN (1 << 17)
3748+#define ISPCCDC_SYN_MODE_VP2SDR (1 << 18)
3749+#define ISPCCDC_SYN_MODE_SDR2RSZ (1 << 19)
3750+
3751+#define ISPCCDC_HD_VD_WID_VDW_SHIFT 0
3752+#define ISPCCDC_HD_VD_WID_HDW_SHIFT 16
3753+
3754+#define ISPCCDC_PIX_LINES_HLPRF_SHIFT 0
3755+#define ISPCCDC_PIX_LINES_PPLN_SHIFT 16
3756+
3757+#define ISPCCDC_HORZ_INFO_NPH_SHIFT 0
3758+#define ISPCCDC_HORZ_INFO_NPH_MASK 0xFFFF8000
3759+#define ISPCCDC_HORZ_INFO_SPH_MASK 0x1000FFFF
3760+#define ISPCCDC_HORZ_INFO_SPH_SHIFT 16
3761+
3762+#define ISPCCDC_VERT_START_SLV0_SHIFT 16
3763+#define ISPCCDC_VERT_START_SLV0_MASK 0x1000FFFF
3764+#define ISPCCDC_VERT_START_SLV1_SHIFT 0
3765+
3766+#define ISPCCDC_VERT_LINES_NLV_MASK 0xFFFF8000
3767+#define ISPCCDC_VERT_LINES_NLV_SHIFT 0
3768+
3769+#define ISPCCDC_CULLING_CULV_SHIFT 0
3770+#define ISPCCDC_CULLING_CULHODD_SHIFT 16
3771+#define ISPCCDC_CULLING_CULHEVN_SHIFT 24
3772+
3773+#define ISPCCDC_HSIZE_OFF_SHIFT 0
3774+
3775+#define ISPCCDC_SDOFST_FINV (1 << 14)
3776+#define ISPCCDC_SDOFST_FOFST_1L 0
3777+#define ISPCCDC_SDOFST_FOFST_4L (3 << 12)
3778+#define ISPCCDC_SDOFST_LOFST3_SHIFT 0
3779+#define ISPCCDC_SDOFST_LOFST2_SHIFT 3
3780+#define ISPCCDC_SDOFST_LOFST1_SHIFT 6
3781+#define ISPCCDC_SDOFST_LOFST0_SHIFT 9
3782+#define EVENEVEN 1
3783+#define ODDEVEN 2
3784+#define EVENODD 3
3785+#define ODDODD 4
3786+
3787+#define ISPCCDC_CLAMP_OBGAIN_SHIFT 0
3788+#define ISPCCDC_CLAMP_OBST_SHIFT 10
3789+#define ISPCCDC_CLAMP_OBSLN_SHIFT 25
3790+#define ISPCCDC_CLAMP_OBSLEN_SHIFT 28
3791+#define ISPCCDC_CLAMP_CLAMPEN (1 << 31)
3792+
3793+#define ISPCCDC_COLPTN_R_Ye 0x0
3794+#define ISPCCDC_COLPTN_Gr_Cy 0x1
3795+#define ISPCCDC_COLPTN_Gb_G 0x2
3796+#define ISPCCDC_COLPTN_B_Mg 0x3
3797+#define ISPCCDC_COLPTN_CP0PLC0_SHIFT 0
3798+#define ISPCCDC_COLPTN_CP0PLC1_SHIFT 2
3799+#define ISPCCDC_COLPTN_CP0PLC2_SHIFT 4
3800+#define ISPCCDC_COLPTN_CP0PLC3_SHIFT 6
3801+#define ISPCCDC_COLPTN_CP1PLC0_SHIFT 8
3802+#define ISPCCDC_COLPTN_CP1PLC1_SHIFT 10
3803+#define ISPCCDC_COLPTN_CP1PLC2_SHIFT 12
3804+#define ISPCCDC_COLPTN_CP1PLC3_SHIFT 14
3805+#define ISPCCDC_COLPTN_CP2PLC0_SHIFT 16
3806+#define ISPCCDC_COLPTN_CP2PLC1_SHIFT 18
3807+#define ISPCCDC_COLPTN_CP2PLC2_SHIFT 20
3808+#define ISPCCDC_COLPTN_CP2PLC3_SHIFT 22
3809+#define ISPCCDC_COLPTN_CP3PLC0_SHIFT 24
3810+#define ISPCCDC_COLPTN_CP3PLC1_SHIFT 26
3811+#define ISPCCDC_COLPTN_CP3PLC2_SHIFT 28
3812+#define ISPCCDC_COLPTN_CP3PLC3_SHIFT 30
3813+
3814+#define ISPCCDC_BLKCMP_B_MG_SHIFT 0
3815+#define ISPCCDC_BLKCMP_GB_G_SHIFT 8
3816+#define ISPCCDC_BLKCMP_GR_CY_SHIFT 16
3817+#define ISPCCDC_BLKCMP_R_YE_SHIFT 24
3818+
3819+#define ISPCCDC_FPC_FPNUM_SHIFT 0
3820+#define ISPCCDC_FPC_FPCEN (1 << 15)
3821+#define ISPCCDC_FPC_FPERR (1 << 16)
3822+
3823+#define ISPCCDC_VDINT_1_SHIFT 0
3824+#define ISPCCDC_VDINT_0_SHIFT 16
3825+#define ISPCCDC_VDINT_0_MASK 0x7FFF
3826+#define ISPCCDC_VDINT_1_MASK 0x7FFF
3827+
3828+#define ISPCCDC_ALAW_GWDI_SHIFT 0
3829+#define ISPCCDC_ALAW_CCDTBL (1 << 3)
3830+
3831+#define ISPCCDC_REC656IF_R656ON 1
3832+#define ISPCCDC_REC656IF_ECCFVH (1 << 1)
3833+
3834+#define ISPCCDC_CFG_BW656 (1 << 5)
3835+#define ISPCCDC_CFG_FIDMD_SHIFT 6
3836+#define ISPCCDC_CFG_WENLOG (1 << 8)
3837+#define ISPCCDC_CFG_WENLOG_AND (0 << 8)
3838+#define ISPCCDC_CFG_WENLOG_OR (1 << 8)
3839+#define ISPCCDC_CFG_Y8POS (1 << 11)
3840+#define ISPCCDC_CFG_BSWD (1 << 12)
3841+#define ISPCCDC_CFG_MSBINVI (1 << 13)
3842+#define ISPCCDC_CFG_VDLC (1 << 15)
3843+
3844+#define ISPCCDC_FMTCFG_FMTEN 0x1
3845+#define ISPCCDC_FMTCFG_LNALT (1 << 1)
3846+#define ISPCCDC_FMTCFG_LNUM_SHIFT 2
3847+#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT 4
3848+#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT 8
3849+#define ISPCCDC_FMTCFG_VPIN_MASK 0xFFFF8000
3850+#define ISPCCDC_FMTCFG_VPIN_12_3 (0x3 << 12)
3851+#define ISPCCDC_FMTCFG_VPIN_11_2 (0x4 << 12)
3852+#define ISPCCDC_FMTCFG_VPIN_10_1 (0x5 << 12)
3853+#define ISPCCDC_FMTCFG_VPIN_9_0 (0x6 << 12)
3854+#define ISPCCDC_FMTCFG_VPEN (1 << 15)
3855+
3856+#define ISPCCDC_FMTCF_VPIF_FRQ_MASK 0xFFF8FFFF
3857+#define ISPCCDC_FMTCF_VPIF_FRQ_BY2 (0x0 << 16)
3858+#define ISPCCDC_FMTCF_VPIF_FRQ_BY3 (0x1 << 16)
3859+#define ISPCCDC_FMTCF_VPIF_FRQ_BY4 (0x2 << 16)
3860+#define ISPCCDC_FMTCF_VPIF_FRQ_BY5 (0x3 << 16)
3861+#define ISPCCDC_FMTCF_VPIF_FRQ_BY6 (0x4 << 16)
3862+
3863+#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT 0
3864+#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT 16
3865+
3866+#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT 0
3867+#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT 16
3868+
3869+#define ISPCCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF0000
3870+#define ISPCCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
3871+
3872+#define ISPCCDC_FMT_VERT_FMTSLV_MASK 0x1FFF0000
3873+#define ISPCCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
3874+
3875+#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT 0
3876+#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT 4
3877+#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT 17
3878+
3879+#define ISPRSZ_PID_PREV_SHIFT 0
3880+#define ISPRSZ_PID_CID_SHIFT 8
3881+#define ISPRSZ_PID_TID_SHIFT 16
3882+
3883+#define ISPRSZ_PCR_ENABLE 0x5
3884+#define ISPRSZ_PCR_BUSY (1 << 1)
3885+
3886+#define ISPRSZ_CNT_HRSZ_SHIFT 0
3887+#define ISPRSZ_CNT_HRSZ_MASK 0x3FF
3888+#define ISPRSZ_CNT_VRSZ_SHIFT 10
3889+#define ISPRSZ_CNT_VRSZ_MASK 0xFFC00
3890+#define ISPRSZ_CNT_HSTPH_SHIFT 20
3891+#define ISPRSZ_CNT_HSTPH_MASK 0x700000
3892+#define ISPRSZ_CNT_VSTPH_SHIFT 23
3893+#define ISPRSZ_CNT_VSTPH_MASK 0x3800000
3894+#define ISPRSZ_CNT_CBILIN_MASK 0x20000000
3895+#define ISPRSZ_CNT_INPTYP_MASK 0x08000000
3896+#define ISPRSZ_CNT_PIXFMT_MASK 0x04000000
3897+#define ISPRSZ_CNT_YCPOS (1 << 26)
3898+#define ISPRSZ_CNT_INPTYP (1 << 27)
3899+#define ISPRSZ_CNT_INPSRC (1 << 28)
3900+#define ISPRSZ_CNT_CBILIN (1 << 29)
3901+
3902+#define ISPRSZ_OUT_SIZE_HORZ_SHIFT 0
3903+#define ISPRSZ_OUT_SIZE_HORZ_MASK 0x7FF
3904+#define ISPRSZ_OUT_SIZE_VERT_SHIFT 16
3905+#define ISPRSZ_OUT_SIZE_VERT_MASK 0x7FF0000
3906+
3907+
3908+#define ISPRSZ_IN_START_HORZ_ST_SHIFT 0
3909+#define ISPRSZ_IN_START_HORZ_ST_MASK 0x1FFF
3910+#define ISPRSZ_IN_START_VERT_ST_SHIFT 16
3911+#define ISPRSZ_IN_START_VERT_ST_MASK 0x1FFF0000
3912+
3913+
3914+#define ISPRSZ_IN_SIZE_HORZ_SHIFT 0
3915+#define ISPRSZ_IN_SIZE_HORZ_MASK 0x1FFF
3916+#define ISPRSZ_IN_SIZE_VERT_SHIFT 16
3917+#define ISPRSZ_IN_SIZE_VERT_MASK 0x1FFF0000
3918+
3919+#define ISPRSZ_SDR_INADD_ADDR_SHIFT 0
3920+#define ISPRSZ_SDR_INADD_ADDR_MASK 0xFFFFFFFF
3921+
3922+#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT 0
3923+#define ISPRSZ_SDR_INOFF_OFFSET_MASK 0xFFFF
3924+
3925+#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT 0
3926+#define ISPRSZ_SDR_OUTADD_ADDR_MASK 0xFFFFFFFF
3927+
3928+
3929+#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT 0
3930+#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK 0xFFFF
3931+
3932+#define ISPRSZ_HFILT10_COEF0_SHIFT 0
3933+#define ISPRSZ_HFILT10_COEF0_MASK 0x3FF
3934+#define ISPRSZ_HFILT10_COEF1_SHIFT 16
3935+#define ISPRSZ_HFILT10_COEF1_MASK 0x3FF0000
3936+
3937+#define ISPRSZ_HFILT32_COEF2_SHIFT 0
3938+#define ISPRSZ_HFILT32_COEF2_MASK 0x3FF
3939+#define ISPRSZ_HFILT32_COEF3_SHIFT 16
3940+#define ISPRSZ_HFILT32_COEF3_MASK 0x3FF0000
3941+
3942+#define ISPRSZ_HFILT54_COEF4_SHIFT 0
3943+#define ISPRSZ_HFILT54_COEF4_MASK 0x3FF
3944+#define ISPRSZ_HFILT54_COEF5_SHIFT 16
3945+#define ISPRSZ_HFILT54_COEF5_MASK 0x3FF0000
3946+
3947+#define ISPRSZ_HFILT76_COEFF6_SHIFT 0
3948+#define ISPRSZ_HFILT76_COEFF6_MASK 0x3FF
3949+#define ISPRSZ_HFILT76_COEFF7_SHIFT 16
3950+#define ISPRSZ_HFILT76_COEFF7_MASK 0x3FF0000
3951+
3952+#define ISPRSZ_HFILT98_COEFF8_SHIFT 0
3953+#define ISPRSZ_HFILT98_COEFF8_MASK 0x3FF
3954+#define ISPRSZ_HFILT98_COEFF9_SHIFT 16
3955+#define ISPRSZ_HFILT98_COEFF9_MASK 0x3FF0000
3956+
3957+#define ISPRSZ_HFILT1110_COEF10_SHIFT 0
3958+#define ISPRSZ_HFILT1110_COEF10_MASK 0x3FF
3959+#define ISPRSZ_HFILT1110_COEF11_SHIFT 16
3960+#define ISPRSZ_HFILT1110_COEF11_MASK 0x3FF0000
3961+
3962+#define ISPRSZ_HFILT1312_COEFF12_SHIFT 0
3963+#define ISPRSZ_HFILT1312_COEFF12_MASK 0x3FF
3964+#define ISPRSZ_HFILT1312_COEFF13_SHIFT 16
3965+#define ISPRSZ_HFILT1312_COEFF13_MASK 0x3FF0000
3966+
3967+#define ISPRSZ_HFILT1514_COEFF14_SHIFT 0
3968+#define ISPRSZ_HFILT1514_COEFF14_MASK 0x3FF
3969+#define ISPRSZ_HFILT1514_COEFF15_SHIFT 16
3970+#define ISPRSZ_HFILT1514_COEFF15_MASK 0x3FF0000
3971+
3972+#define ISPRSZ_HFILT1716_COEF16_SHIFT 0
3973+#define ISPRSZ_HFILT1716_COEF16_MASK 0x3FF
3974+#define ISPRSZ_HFILT1716_COEF17_SHIFT 16
3975+#define ISPRSZ_HFILT1716_COEF17_MASK 0x3FF0000
3976+
3977+#define ISPRSZ_HFILT1918_COEF18_SHIFT 0
3978+#define ISPRSZ_HFILT1918_COEF18_MASK 0x3FF
3979+#define ISPRSZ_HFILT1918_COEF19_SHIFT 16
3980+#define ISPRSZ_HFILT1918_COEF19_MASK 0x3FF0000
3981+
3982+#define ISPRSZ_HFILT2120_COEF20_SHIFT 0
3983+#define ISPRSZ_HFILT2120_COEF20_MASK 0x3FF
3984+#define ISPRSZ_HFILT2120_COEF21_SHIFT 16
3985+#define ISPRSZ_HFILT2120_COEF21_MASK 0x3FF0000
3986+
3987+#define ISPRSZ_HFILT2322_COEF22_SHIFT 0
3988+#define ISPRSZ_HFILT2322_COEF22_MASK 0x3FF
3989+#define ISPRSZ_HFILT2322_COEF23_SHIFT 16
3990+#define ISPRSZ_HFILT2322_COEF23_MASK 0x3FF0000
3991+
3992+#define ISPRSZ_HFILT2524_COEF24_SHIFT 0
3993+#define ISPRSZ_HFILT2524_COEF24_MASK 0x3FF
3994+#define ISPRSZ_HFILT2524_COEF25_SHIFT 16
3995+#define ISPRSZ_HFILT2524_COEF25_MASK 0x3FF0000
3996+
3997+#define ISPRSZ_HFILT2726_COEF26_SHIFT 0
3998+#define ISPRSZ_HFILT2726_COEF26_MASK 0x3FF
3999+#define ISPRSZ_HFILT2726_COEF27_SHIFT 16
4000+#define ISPRSZ_HFILT2726_COEF27_MASK 0x3FF0000
4001+
4002+#define ISPRSZ_HFILT2928_COEF28_SHIFT 0
4003+#define ISPRSZ_HFILT2928_COEF28_MASK 0x3FF
4004+#define ISPRSZ_HFILT2928_COEF29_SHIFT 16
4005+#define ISPRSZ_HFILT2928_COEF29_MASK 0x3FF0000
4006+
4007+#define ISPRSZ_HFILT3130_COEF30_SHIFT 0
4008+#define ISPRSZ_HFILT3130_COEF30_MASK 0x3FF
4009+#define ISPRSZ_HFILT3130_COEF31_SHIFT 16
4010+#define ISPRSZ_HFILT3130_COEF31_MASK 0x3FF0000
4011+
4012+#define ISPRSZ_VFILT10_COEF0_SHIFT 0
4013+#define ISPRSZ_VFILT10_COEF0_MASK 0x3FF
4014+#define ISPRSZ_VFILT10_COEF1_SHIFT 16
4015+#define ISPRSZ_VFILT10_COEF1_MASK 0x3FF0000
4016+
4017+#define ISPRSZ_VFILT32_COEF2_SHIFT 0
4018+#define ISPRSZ_VFILT32_COEF2_MASK 0x3FF
4019+#define ISPRSZ_VFILT32_COEF3_SHIFT 16
4020+#define ISPRSZ_VFILT32_COEF3_MASK 0x3FF0000
4021+
4022+#define ISPRSZ_VFILT54_COEF4_SHIFT 0
4023+#define ISPRSZ_VFILT54_COEF4_MASK 0x3FF
4024+#define ISPRSZ_VFILT54_COEF5_SHIFT 16
4025+#define ISPRSZ_VFILT54_COEF5_MASK 0x3FF0000
4026+
4027+#define ISPRSZ_VFILT76_COEFF6_SHIFT 0
4028+#define ISPRSZ_VFILT76_COEFF6_MASK 0x3FF
4029+#define ISPRSZ_VFILT76_COEFF7_SHIFT 16
4030+#define ISPRSZ_VFILT76_COEFF7_MASK 0x3FF0000
4031+
4032+#define ISPRSZ_VFILT98_COEFF8_SHIFT 0
4033+#define ISPRSZ_VFILT98_COEFF8_MASK 0x3FF
4034+#define ISPRSZ_VFILT98_COEFF9_SHIFT 16
4035+#define ISPRSZ_VFILT98_COEFF9_MASK 0x3FF0000
4036+
4037+#define ISPRSZ_VFILT1110_COEF10_SHIFT 0
4038+#define ISPRSZ_VFILT1110_COEF10_MASK 0x3FF
4039+#define ISPRSZ_VFILT1110_COEF11_SHIFT 16
4040+#define ISPRSZ_VFILT1110_COEF11_MASK 0x3FF0000
4041+
4042+#define ISPRSZ_VFILT1312_COEFF12_SHIFT 0
4043+#define ISPRSZ_VFILT1312_COEFF12_MASK 0x3FF
4044+#define ISPRSZ_VFILT1312_COEFF13_SHIFT 16
4045+#define ISPRSZ_VFILT1312_COEFF13_MASK 0x3FF0000
4046+
4047+#define ISPRSZ_VFILT1514_COEFF14_SHIFT 0
4048+#define ISPRSZ_VFILT1514_COEFF14_MASK 0x3FF
4049+#define ISPRSZ_VFILT1514_COEFF15_SHIFT 16
4050+#define ISPRSZ_VFILT1514_COEFF15_MASK 0x3FF0000
4051+
4052+#define ISPRSZ_VFILT1716_COEF16_SHIFT 0
4053+#define ISPRSZ_VFILT1716_COEF16_MASK 0x3FF
4054+#define ISPRSZ_VFILT1716_COEF17_SHIFT 16
4055+#define ISPRSZ_VFILT1716_COEF17_MASK 0x3FF0000
4056+
4057+#define ISPRSZ_VFILT1918_COEF18_SHIFT 0
4058+#define ISPRSZ_VFILT1918_COEF18_MASK 0x3FF
4059+#define ISPRSZ_VFILT1918_COEF19_SHIFT 16
4060+#define ISPRSZ_VFILT1918_COEF19_MASK 0x3FF0000
4061+
4062+#define ISPRSZ_VFILT2120_COEF20_SHIFT 0
4063+#define ISPRSZ_VFILT2120_COEF20_MASK 0x3FF
4064+#define ISPRSZ_VFILT2120_COEF21_SHIFT 16
4065+#define ISPRSZ_VFILT2120_COEF21_MASK 0x3FF0000
4066+
4067+#define ISPRSZ_VFILT2322_COEF22_SHIFT 0
4068+#define ISPRSZ_VFILT2322_COEF22_MASK 0x3FF
4069+#define ISPRSZ_VFILT2322_COEF23_SHIFT 16
4070+#define ISPRSZ_VFILT2322_COEF23_MASK 0x3FF0000
4071+
4072+#define ISPRSZ_VFILT2524_COEF24_SHIFT 0
4073+#define ISPRSZ_VFILT2524_COEF24_MASK 0x3FF
4074+#define ISPRSZ_VFILT2524_COEF25_SHIFT 16
4075+#define ISPRSZ_VFILT2524_COEF25_MASK 0x3FF0000
4076+
4077+#define ISPRSZ_VFILT2726_COEF26_SHIFT 0
4078+#define ISPRSZ_VFILT2726_COEF26_MASK 0x3FF
4079+#define ISPRSZ_VFILT2726_COEF27_SHIFT 16
4080+#define ISPRSZ_VFILT2726_COEF27_MASK 0x3FF0000
4081+
4082+#define ISPRSZ_VFILT2928_COEF28_SHIFT 0
4083+#define ISPRSZ_VFILT2928_COEF28_MASK 0x3FF
4084+#define ISPRSZ_VFILT2928_COEF29_SHIFT 16
4085+#define ISPRSZ_VFILT2928_COEF29_MASK 0x3FF0000
4086+
4087+#define ISPRSZ_VFILT3130_COEF30_SHIFT 0
4088+#define ISPRSZ_VFILT3130_COEF30_MASK 0x3FF
4089+#define ISPRSZ_VFILT3130_COEF31_SHIFT 16
4090+#define ISPRSZ_VFILT3130_COEF31_MASK 0x3FF0000
4091+
4092+#define ISPRSZ_YENH_CORE_SHIFT 0
4093+#define ISPRSZ_YENH_CORE_MASK 0xFF
4094+#define ISPRSZ_YENH_SLOP_SHIFT 8
4095+#define ISPRSZ_YENH_SLOP_MASK 0xF00
4096+#define ISPRSZ_YENH_GAIN_SHIFT 12
4097+#define ISPRSZ_YENH_GAIN_MASK 0xF000
4098+#define ISPRSZ_YENH_ALGO_SHIFT 16
4099+#define ISPRSZ_YENH_ALGO_MASK 0x30000
4100+
4101+#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT 1
4102+#define ISPH3A_PCR_AF_MED_TH_SHIFT 3
4103+#define ISPH3A_PCR_AF_RGBPOS_SHIFT 11
4104+#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT 22
4105+#define ISPH3A_PCR_AEW_AVE2LMT_MASK 0xFFC00000
4106+#define ISPH3A_PCR_BUSYAF (1 << 15)
4107+#define ISPH3A_PCR_BUSYAEAWB (1 << 18)
4108+
4109+#define ISPH3A_AEWWIN1_WINHC_SHIFT 0
4110+#define ISPH3A_AEWWIN1_WINHC_MASK 0x3F
4111+#define ISPH3A_AEWWIN1_WINVC_SHIFT 6
4112+#define ISPH3A_AEWWIN1_WINVC_MASK 0x1FC0
4113+#define ISPH3A_AEWWIN1_WINW_SHIFT 13
4114+#define ISPH3A_AEWWIN1_WINW_MASK 0xFE000
4115+#define ISPH3A_AEWWIN1_WINH_SHIFT 24
4116+#define ISPH3A_AEWWIN1_WINH_MASK 0x7F000000
4117+
4118+#define ISPH3A_AEWINSTART_WINSH_SHIFT 0
4119+#define ISPH3A_AEWINSTART_WINSH_MASK 0x0FFF
4120+#define ISPH3A_AEWINSTART_WINSV_SHIFT 16
4121+#define ISPH3A_AEWINSTART_WINSV_MASK 0x0FFF0000
4122+
4123+#define ISPH3A_AEWINBLK_WINH_SHIFT 0
4124+#define ISPH3A_AEWINBLK_WINH_MASK 0x7F
4125+#define ISPH3A_AEWINBLK_WINSV_SHIFT 16
4126+#define ISPH3A_AEWINBLK_WINSV_MASK 0x0FFF0000
4127+
4128+#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT 0
4129+#define ISPH3A_AEWSUBWIN_AEWINCH_MASK 0x0F
4130+#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT 8
4131+#define ISPH3A_AEWSUBWIN_AEWINCV_MASK 0x0F00
4132+
4133+#define ISPHIST_PCR_ENABLE_SHIFT 0
4134+#define ISPHIST_PCR_ENABLE_MASK 0x01
4135+#define ISPHIST_PCR_BUSY 0x02
4136+
4137+#define ISPHIST_CNT_DATASIZE_SHIFT 8
4138+#define ISPHIST_CNT_DATASIZE_MASK 0x0100
4139+#define ISPHIST_CNT_CLEAR_SHIFT 7
4140+#define ISPHIST_CNT_CLEAR_MASK 0x080
4141+#define ISPHIST_CNT_CFA_SHIFT 6
4142+#define ISPHIST_CNT_CFA_MASK 0x040
4143+#define ISPHIST_CNT_BINS_SHIFT 4
4144+#define ISPHIST_CNT_BINS_MASK 0x030
4145+#define ISPHIST_CNT_SOURCE_SHIFT 3
4146+#define ISPHIST_CNT_SOURCE_MASK 0x08
4147+#define ISPHIST_CNT_SHIFT_SHIFT 0
4148+#define ISPHIST_CNT_SHIFT_MASK 0x07
4149+
4150+#define ISPHIST_WB_GAIN_WG00_SHIFT 24
4151+#define ISPHIST_WB_GAIN_WG00_MASK 0xFF000000
4152+#define ISPHIST_WB_GAIN_WG01_SHIFT 16
4153+#define ISPHIST_WB_GAIN_WG01_MASK 0xFF0000
4154+#define ISPHIST_WB_GAIN_WG02_SHIFT 8
4155+#define ISPHIST_WB_GAIN_WG02_MASK 0xFF00
4156+#define ISPHIST_WB_GAIN_WG03_SHIFT 0
4157+#define ISPHIST_WB_GAIN_WG03_MASK 0xFF
4158+
4159+#define ISPHIST_REGHORIZ_HSTART_SHIFT 16 /*
4160+ * REGION 0 to 3 HORZ
4161+ * and VERT
4162+ */
4163+#define ISPHIST_REGHORIZ_HSTART_MASK 0x3FFF0000
4164+#define ISPHIST_REGHORIZ_HEND_SHIFT 0
4165+#define ISPHIST_REGHORIZ_HEND_MASK 0x3FFF
4166+#define ISPHIST_REGVERT_VSTART_SHIFT 16
4167+#define ISPHIST_REGVERT_VSTART_MASK 0x3FFF0000
4168+#define ISPHIST_REGVERT_VEND_SHIFT 0
4169+#define ISPHIST_REGVERT_VEND_MASK 0x3FFF
4170+
4171+#define ISPHIST_REGHORIZ_MASK 0x3FFF3FFF
4172+#define ISPHIST_REGVERT_MASK 0x3FFF3FFF
4173+
4174+#define ISPHIST_ADDR_SHIFT 0
4175+#define ISPHIST_ADDR_MASK 0x3FF
4176+
4177+#define ISPHIST_DATA_SHIFT 0
4178+#define ISPHIST_DATA_MASK 0xFFFFF
4179+
4180+#define ISPHIST_RADD_SHIFT 0
4181+#define ISPHIST_RADD_MASK 0xFFFFFFFF
4182+
4183+#define ISPHIST_RADD_OFF_SHIFT 0
4184+#define ISPHIST_RADD_OFF_MASK 0xFFFF
4185+
4186+#define ISPHIST_HV_INFO_HSIZE_SHIFT 16
4187+#define ISPHIST_HV_INFO_HSIZE_MASK 0x3FFF0000
4188+#define ISPHIST_HV_INFO_VSIZE_SHIFT 0
4189+#define ISPHIST_HV_INFO_VSIZE_MASK 0x3FFF
4190+
4191+#define ISPHIST_HV_INFO_MASK 0x3FFF3FFF
4192+
4193+#define ISPCCDC_LSC_GAIN_MODE_N_MASK 0x700
4194+#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT 8
4195+#define ISPCCDC_LSC_GAIN_MODE_M_MASK 0x3800
4196+#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT 12
4197+#define ISPCCDC_LSC_GAIN_FORMAT_MASK 0xE
4198+#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT 1
4199+#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK (1<<6)
4200+
4201+#define ISPCCDC_LSC_INITIAL_X_MASK 0x3F
4202+#define ISPCCDC_LSC_INITIAL_X_SHIFT 0
4203+#define ISPCCDC_LSC_INITIAL_Y_MASK 0x3F0000
4204+#define ISPCCDC_LSC_INITIAL_Y_SHIFT 16
4205+
4206+#define ISPMMU_REVISION_REV_MINOR_MASK 0xF
4207+#define ISPMMU_REVISION_REV_MAJOR_SHIFT 0x4
4208+
4209+#define IRQENABLE_MULTIHITFAULT (1<<4)
4210+#define IRQENABLE_TWFAULT (1<<3)
4211+#define IRQENABLE_EMUMISS (1<<2)
4212+#define IRQENABLE_TRANSLNFAULT (1<<1)
4213+#define IRQENABLE_TLBMISS (1)
4214+
4215+#define ISPMMU_MMUCNTL_MMU_EN (1<<1)
4216+#define ISPMMU_MMUCNTL_TWL_EN (1<<2)
4217+#define ISPMMU_MMUCNTL_EMUTLBUPDATE (1<<3)
4218+#define ISPMMU_AUTOIDLE 0x1
4219+#define ISPMMU_SIDLEMODE_FORCEIDLE 0
4220+#define ISPMMU_SIDLEMODE_NOIDLE 1
4221+#define ISPMMU_SIDLEMODE_SMARTIDLE 2
4222+#define ISPMMU_SIDLEMODE_SHIFT 3
4223+
4224+#define ISPCSI1_AUTOIDLE 0x1
4225+#define ISPCSI1_MIDLEMODE_SHIFT 12
4226+#define ISPCSI1_MIDLEMODE_FORCESTANDBY 0x0
4227+#define ISPCSI1_MIDLEMODE_NOSTANDBY 0x1
4228+#define ISPCSI1_MIDLEMODE_SMARTSTANDBY 0x2
4229+
4230+/* CSI2 receiver registers (ES2.0) */
4231+#define ISPCSI2_REVISION (0x000)
4232+#define ISPCSI2_SYSCONFIG (0x010)
4233+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT 12
4234+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK \
4235+ (0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
4236+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE \
4237+ (0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
4238+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO \
4239+ (0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
4240+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART \
4241+ (0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
4242+#define ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT 1
4243+#define ISPCSI2_SYSCONFIG_SOFT_RESET_MASK \
4244+ (0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
4245+#define ISPCSI2_SYSCONFIG_SOFT_RESET_NORMAL \
4246+ (0x0 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
4247+#define ISPCSI2_SYSCONFIG_SOFT_RESET_RESET \
4248+ (0x1 << ISPCSI2_SYSCONFIG_SOFT_RESET_SHIFT)
4249+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT 0
4250+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK \
4251+ (0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
4252+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_FREE \
4253+ (0x0 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
4254+#define ISPCSI2_SYSCONFIG_AUTO_IDLE_AUTO \
4255+ (0x1 << ISPCSI2_SYSCONFIG_AUTO_IDLE_SHIFT)
4256+#define ISPCSI2_SYSSTATUS (0x014)
4257+#define ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT 0
4258+#define ISPCSI2_SYSSTATUS_RESET_DONE_MASK \
4259+ (0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
4260+#define ISPCSI2_SYSSTATUS_RESET_DONE_ONGOING \
4261+ (0x0 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
4262+#define ISPCSI2_SYSSTATUS_RESET_DONE_DONE \
4263+ (0x1 << ISPCSI2_SYSSTATUS_RESET_DONE_SHIFT)
4264+#define ISPCSI2_IRQSTATUS (0x018)
4265+#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ (1 << 14)
4266+#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ (1 << 13)
4267+#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 12)
4268+#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ (1 << 11)
4269+#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ (1 << 10)
4270+#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ (1 << 9)
4271+#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ (1 << 8)
4272+#define ISPCSI2_IRQSTATUS_CONTEXT(n) (1 << (n))
4273+
4274+#define ISPCSI2_IRQENABLE (0x01C)
4275+#define ISPCSI2_CTRL (0x040)
4276+#define ISPCSI2_CTRL_VP_CLK_EN_SHIFT 15
4277+#define ISPCSI2_CTRL_VP_CLK_EN_MASK (0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
4278+#define ISPCSI2_CTRL_VP_CLK_EN_DISABLE (0x0 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
4279+#define ISPCSI2_CTRL_VP_CLK_EN_ENABLE (0x1 << ISPCSI2_CTRL_VP_CLK_EN_SHIFT)
4280+
4281+#define ISPCSI2_CTRL_VP_ONLY_EN_SHIFT 11
4282+#define ISPCSI2_CTRL_VP_ONLY_EN_MASK (0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
4283+#define ISPCSI2_CTRL_VP_ONLY_EN_DISABLE (0x0 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
4284+#define ISPCSI2_CTRL_VP_ONLY_EN_ENABLE (0x1 << ISPCSI2_CTRL_VP_ONLY_EN_SHIFT)
4285+
4286+#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT 8
4287+#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK (0x3 << \
4288+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
4289+#define ISPCSI2_CTRL_VP_OUT_CTRL_DISABLE (0x0 << \
4290+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
4291+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV2 (0x1 << \
4292+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
4293+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV3 (0x2 << \
4294+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
4295+#define ISPCSI2_CTRL_VP_OUT_CTRL_DIV4 (0x3 << \
4296+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
4297+
4298+#define ISPCSI2_CTRL_DBG_EN_SHIFT 7
4299+#define ISPCSI2_CTRL_DBG_EN_MASK (0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
4300+#define ISPCSI2_CTRL_DBG_EN_DISABLE (0x0 << ISPCSI2_CTRL_DBG_EN_SHIFT)
4301+#define ISPCSI2_CTRL_DBG_EN_ENABLE (0x1 << ISPCSI2_CTRL_DBG_EN_SHIFT)
4302+
4303+#define ISPCSI2_CTRL_BURST_SIZE_SHIFT 5
4304+#define ISPCSI2_CTRL_BURST_SIZE_MASK (0x3 << \
4305+ ISPCSI2_CTRL_BURST_SIZE_SHIFT)
4306+#define ISPCSI2_CTRL_BURST_SIZE_MYSTERY_VAL (0x2 << \
4307+ ISPCSI2_CTRL_BURST_SIZE_SHIFT)
4308+
4309+#define ISPCSI2_CTRL_FRAME_SHIFT 3
4310+#define ISPCSI2_CTRL_FRAME_MASK (0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
4311+#define ISPCSI2_CTRL_FRAME_DISABLE_IMM (0x0 << ISPCSI2_CTRL_FRAME_SHIFT)
4312+#define ISPCSI2_CTRL_FRAME_DISABLE_FEC (0x1 << ISPCSI2_CTRL_FRAME_SHIFT)
4313+
4314+#define ISPCSI2_CTRL_ECC_EN_SHIFT 2
4315+#define ISPCSI2_CTRL_ECC_EN_MASK (0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
4316+#define ISPCSI2_CTRL_ECC_EN_DISABLE (0x0 << ISPCSI2_CTRL_ECC_EN_SHIFT)
4317+#define ISPCSI2_CTRL_ECC_EN_ENABLE (0x1 << ISPCSI2_CTRL_ECC_EN_SHIFT)
4318+
4319+#define ISPCSI2_CTRL_SECURE_SHIFT 1
4320+#define ISPCSI2_CTRL_SECURE_MASK (0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
4321+#define ISPCSI2_CTRL_SECURE_DISABLE (0x0 << ISPCSI2_CTRL_SECURE_SHIFT)
4322+#define ISPCSI2_CTRL_SECURE_ENABLE (0x1 << ISPCSI2_CTRL_SECURE_SHIFT)
4323+
4324+#define ISPCSI2_CTRL_IF_EN_SHIFT 0
4325+#define ISPCSI2_CTRL_IF_EN_MASK (0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
4326+#define ISPCSI2_CTRL_IF_EN_DISABLE (0x0 << ISPCSI2_CTRL_IF_EN_SHIFT)
4327+#define ISPCSI2_CTRL_IF_EN_ENABLE (0x1 << ISPCSI2_CTRL_IF_EN_SHIFT)
4328+
4329+#define ISPCSI2_DBG_H (0x044)
4330+#define ISPCSI2_GNQ (0x048)
4331+#define ISPCSI2_COMPLEXIO_CFG1 (0x050)
4332+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT 29
4333+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_MASK \
4334+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
4335+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_ONGOING \
4336+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
4337+#define ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_DONE \
4338+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_RESET_DONE_SHIFT)
4339+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT 27
4340+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK \
4341+ (0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
4342+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF \
4343+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
4344+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON \
4345+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
4346+#define ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW \
4347+ (0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_SHIFT)
4348+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT 25
4349+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK \
4350+ (0x3 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
4351+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF \
4352+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
4353+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON \
4354+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
4355+#define ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW \
4356+ (0x2 << ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_SHIFT)
4357+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT 24
4358+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK \
4359+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
4360+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE \
4361+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
4362+#define ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE \
4363+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_SHIFT)
4364+
4365+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n) (3 + ((n) * 4))
4366+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(n) \
4367+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
4368+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_PN(n) \
4369+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
4370+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POL_NP(n) \
4371+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(n))
4372+
4373+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n) ((n) * 4)
4374+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(n) \
4375+ (0x7 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4376+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_NC(n) \
4377+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4378+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_1(n) \
4379+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4380+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_2(n) \
4381+ (0x2 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4382+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_3(n) \
4383+ (0x3 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4384+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_4(n) \
4385+ (0x4 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4386+#define ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_5(n) \
4387+ (0x5 << ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(n))
4388+
4389+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT 3
4390+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK \
4391+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
4392+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_PN \
4393+ (0x0 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
4394+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_NP \
4395+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT)
4396+
4397+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT 0
4398+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK \
4399+ (0x7 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4400+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_1 \
4401+ (0x1 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4402+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_2 \
4403+ (0x2 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4404+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_3 \
4405+ (0x3 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4406+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_4 \
4407+ (0x4 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4408+#define ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_5 \
4409+ (0x5 << ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT)
4410+
4411+#define ISPCSI2_COMPLEXIO1_IRQSTATUS (0x054)
4412+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMEXIT (1 << 26)
4413+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEALLULPMENTER (1 << 25)
4414+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM5 (1 << 24)
4415+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM4 (1 << 23)
4416+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM3 (1 << 22)
4417+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM2 (1 << 21)
4418+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_STATEULPM1 (1 << 20)
4419+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL5 (1 << 19)
4420+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL4 (1 << 18)
4421+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL3 (1 << 17)
4422+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL2 (1 << 16)
4423+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRCONTROL1 (1 << 15)
4424+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC5 (1 << 14)
4425+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC4 (1 << 13)
4426+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC3 (1 << 12)
4427+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC2 (1 << 11)
4428+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRESC1 (1 << 10)
4429+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS5 (1 << 9)
4430+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS4 (1 << 8)
4431+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS3 (1 << 7)
4432+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS2 (1 << 6)
4433+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTSYNCHS1 (1 << 5)
4434+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS5 (1 << 4)
4435+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS4 (1 << 3)
4436+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS3 (1 << 2)
4437+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS2 (1 << 1)
4438+#define ISPCSI2_COMPLEXIO1_IRQSTATUS_ERRSOTHS1 1
4439+
4440+#define ISPCSI2_SHORT_PACKET (0x05C)
4441+#define ISPCSI2_COMPLEXIO1_IRQENABLE (0x060)
4442+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT (1 << 26)
4443+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER (1 << 25)
4444+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 (1 << 24)
4445+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 (1 << 23)
4446+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 (1 << 22)
4447+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 (1 << 21)
4448+#define ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 (1 << 20)
4449+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 (1 << 19)
4450+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 (1 << 18)
4451+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 (1 << 17)
4452+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 (1 << 16)
4453+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 (1 << 15)
4454+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 (1 << 14)
4455+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 (1 << 13)
4456+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 (1 << 12)
4457+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 (1 << 11)
4458+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 (1 << 10)
4459+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 (1 << 9)
4460+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 (1 << 8)
4461+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 (1 << 7)
4462+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 (1 << 6)
4463+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 (1 << 5)
4464+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 (1 << 4)
4465+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 (1 << 3)
4466+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 (1 << 2)
4467+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 (1 << 1)
4468+#define ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1 1
4469+#define ISPCSI2_DBG_P (0x068)
4470+#define ISPCSI2_TIMING (0x06C)
4471+
4472+
4473+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n) \
4474+ ((16 * ((n) - 1)) + 15)
4475+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(n) \
4476+ (0x1 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
4477+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE(n) \
4478+ (0x0 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
4479+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(n) \
4480+ (0x1 << ISPCSI2_TIMING_FORCE_RX_MODE_IO_SHIFT(n))
4481+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n) ((16 * ((n) - 1)) + 14)
4482+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(n) \
4483+ (0x1 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
4484+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE(n) \
4485+ (0x0 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
4486+#define ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(n) \
4487+ (0x1 << ISPCSI2_TIMING_STOP_STATE_X16_IO_SHIFT(n))
4488+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n) ((16 * ((n) - 1)) + 13)
4489+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(n) \
4490+ (0x1 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
4491+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE(n) \
4492+ (0x0 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
4493+#define ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(n) \
4494+ (0x1 << ISPCSI2_TIMING_STOP_STATE_X4_IO_SHIFT(n))
4495+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n) (16 * ((n) - 1))
4496+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n) \
4497+ (0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
4498+
4499+#define ISPCSI2_CTX_CTRL1(n) ((0x070) + 0x20 * (n))
4500+#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT 8
4501+#define ISPCSI2_CTX_CTRL1_COUNT_MASK (0xFF << \
4502+ ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
4503+#define ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT 7
4504+#define ISPCSI2_CTX_CTRL1_EOF_EN_MASK \
4505+ (0x1 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
4506+#define ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE \
4507+ (0x0 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
4508+#define ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE \
4509+ (0x1 << ISPCSI2_CTX_CTRL1_EOF_EN_SHIFT)
4510+#define ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT 6
4511+#define ISPCSI2_CTX_CTRL1_EOL_EN_MASK \
4512+ (0x1 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
4513+#define ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE \
4514+ (0x0 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
4515+#define ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE \
4516+ (0x1 << ISPCSI2_CTX_CTRL1_EOL_EN_SHIFT)
4517+#define ISPCSI2_CTX_CTRL1_CS_EN_SHIFT 5
4518+#define ISPCSI2_CTX_CTRL1_CS_EN_MASK \
4519+ (0x1 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
4520+#define ISPCSI2_CTX_CTRL1_CS_EN_DISABLE \
4521+ (0x0 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
4522+#define ISPCSI2_CTX_CTRL1_CS_EN_ENABLE \
4523+ (0x1 << ISPCSI2_CTX_CTRL1_CS_EN_SHIFT)
4524+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT 4
4525+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_MASK \
4526+ (0x1 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
4527+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_DISABLE \
4528+ (0x0 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
4529+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_ENABLE \
4530+ (0x1 << ISPCSI2_CTX_CTRL1_COUNT_UNLOCK_EN_SHIFT)
4531+#define ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT 3
4532+#define ISPCSI2_CTX_CTRL1_PING_PONG_MASK \
4533+ (0x1 << ISPCSI2_CTX_CTRL1_PING_PONG_SHIFT)
4534+#define ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT 0
4535+#define ISPCSI2_CTX_CTRL1_CTX_EN_MASK \
4536+ (0x1 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
4537+#define ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE \
4538+ (0x0 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
4539+#define ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE \
4540+ (0x1 << ISPCSI2_CTX_CTRL1_CTX_EN_SHIFT)
4541+
4542+#define ISPCSI2_CTX_CTRL2(n) ((0x074) + 0x20 * (n))
4543+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT 11
4544+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK \
4545+ (0x3 << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
4546+#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT 0
4547+#define ISPCSI2_CTX_CTRL2_FORMAT_MASK (0x3FF << \
4548+ ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
4549+
4550+#define ISPCSI2_CTX_DAT_OFST(n) ((0x078) + 0x20 * (n))
4551+#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT 5
4552+#define ISPCSI2_CTX_DAT_OFST_OFST_MASK (0x7FF << \
4553+ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
4554+
4555+#define ISPCSI2_CTX_DAT_PING_ADDR(n) ((0x07C) + 0x20 * (n))
4556+#define ISPCSI2_CTX_DAT_PONG_ADDR(n) ((0x080) + 0x20 * (n))
4557+#define ISPCSI2_CTX_IRQENABLE(n) ((0x084) + 0x20 * (n))
4558+#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ (1 << 8)
4559+#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ (1 << 7)
4560+#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ (1 << 6)
4561+#define ISPCSI2_CTX_IRQENABLE_CS_IRQ (1 << 5)
4562+#define ISPCSI2_CTX_IRQENABLE_LE_IRQ (1 << 3)
4563+#define ISPCSI2_CTX_IRQENABLE_LS_IRQ (1 << 2)
4564+#define ISPCSI2_CTX_IRQENABLE_FE_IRQ (1 << 1)
4565+#define ISPCSI2_CTX_IRQENABLE_FS_IRQ 1
4566+#define ISPCSI2_CTX_IRQSTATUS(n) ((0x088) + 0x20 * (n))
4567+#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ (1 << 8)
4568+#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ (1 << 7)
4569+#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ (1 << 6)
4570+#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ (1 << 5)
4571+#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ (1 << 3)
4572+#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ (1 << 2)
4573+#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ (1 << 1)
4574+#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ 1
4575+
4576+#define ISPCSI2_CTX_CTRL3(n) ((0x08C) + 0x20 * (n))
4577+#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT 5
4578+#define ISPCSI2_CTX_CTRL3_ALPHA_MASK (0x3FFF << \
4579+ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
4580+
4581+#define ISPCSI2PHY_CFG0 (0x000)
4582+#define ISPCSI2PHY_CFG0_THS_TERM_SHIFT 8
4583+#define ISPCSI2PHY_CFG0_THS_TERM_MASK \
4584+ (0xFF << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
4585+#define ISPCSI2PHY_CFG0_THS_TERM_RESETVAL \
4586+ (0x04 << ISPCSI2PHY_CFG0_THS_TERM_SHIFT)
4587+#define ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT 0
4588+#define ISPCSI2PHY_CFG0_THS_SETTLE_MASK \
4589+ (0xFF << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
4590+#define ISPCSI2PHY_CFG0_THS_SETTLE_RESETVAL \
4591+ (0x27 << ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT)
4592+#define ISPCSI2PHY_CFG1 (0x004)
4593+#define ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT 18
4594+#define ISPCSI2PHY_CFG1_TCLK_TERM_MASK \
4595+ (0x7F << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
4596+#define ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL \
4597+ (0x00 << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
4598+#define ISPCSI2PHY_CFG1_RESERVED1_SHIFT 10
4599+#define ISPCSI2PHY_CFG1_RESERVED1_MASK \
4600+ (0xFF << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
4601+#define ISPCSI2PHY_CFG1_RESERVED1__RESETVAL \
4602+ (0xB8 << ISPCSI2PHY_CFG1_RESERVED1_SHIFT)
4603+#define ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT 8
4604+#define ISPCSI2PHY_CFG1_TCLK_MISS_MASK \
4605+ (0x3 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
4606+#define ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL \
4607+ (0x1 << ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT)
4608+#define ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT 0
4609+#define ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK \
4610+ (0xFF << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
4611+#define ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL \
4612+ (0x0E << ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT)
4613+#define ISPCSI2PHY_CFG1__RESETVAL (ISPCSI2PHY_CFG1_TCLK_TERM__RESETVAL | \
4614+ ISPCSI2PHY_CFG1_RESERVED1__RESETVAL | \
4615+ ISPCSI2PHY_CFG1_TCLK_MISS__RESETVAL | \
4616+ ISPCSI2PHY_CFG1_TCLK_SETTLE__RESETVAL)
4617+#define ISPCSI2PHY_CFG1__EDITABLE_MASK (ISPCSI2PHY_CFG1_TCLK_TERM_MASK | \
4618+ ISPCSI2PHY_CFG1_RESERVED1_MASK | \
4619+ ISPCSI2PHY_CFG1_TCLK_MISS_MASK | \
4620+ ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK)
4621+
4622+#endif /* __ISPREG_H__ */
4623--
46241.5.6.5
4625
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch
new file mode 100644
index 0000000000..cfca26723a
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0002-omap3isp-Add-ISP-MMU-wrapper.patch
@@ -0,0 +1,209 @@
1From 731527a7dc26533a878c7c5f36fc148fdcaa21b8 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add ISP MMU wrapper
5
6TODO:
7
8- The ISP driver should start using the IOMMU directly without this wrapper.
9
10Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
11---
12 drivers/media/video/isp/ispmmu.c | 141 ++++++++++++++++++++++++++++++++++++++
13 drivers/media/video/isp/ispmmu.h | 36 ++++++++++
14 2 files changed, 177 insertions(+), 0 deletions(-)
15 create mode 100644 drivers/media/video/isp/ispmmu.c
16 create mode 100644 drivers/media/video/isp/ispmmu.h
17
18diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
19new file mode 100644
20index 0000000..f872c71
21--- /dev/null
22+++ b/drivers/media/video/isp/ispmmu.c
23@@ -0,0 +1,141 @@
24+/*
25+ * omap iommu wrapper for TI's OMAP3430 Camera ISP
26+ *
27+ * Copyright (C) 2008--2009 Nokia.
28+ *
29+ * Contributors:
30+ * Hiroshi Doyu <hiroshi.doyu@nokia.com>
31+ * Sakari Ailus <sakari.ailus@nokia.com>
32+ *
33+ * This package is free software; you can redistribute it and/or modify
34+ * it under the terms of the GNU General Public License version 2 as
35+ * published by the Free Software Foundation.
36+ *
37+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
38+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
39+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
40+ */
41+
42+#include <linux/module.h>
43+
44+#include "ispmmu.h"
45+#include "isp.h"
46+
47+#include <mach/iommu.h>
48+#include <mach/iovmm.h>
49+
50+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
51+
52+static struct iommu *isp_iommu;
53+
54+dma_addr_t ispmmu_vmalloc(size_t bytes)
55+{
56+ return (dma_addr_t)iommu_vmalloc(isp_iommu, 0, bytes, IOMMU_FLAG);
57+}
58+
59+void ispmmu_vfree(const dma_addr_t da)
60+{
61+ iommu_vfree(isp_iommu, (u32)da);
62+}
63+
64+dma_addr_t ispmmu_kmap(u32 pa, int size)
65+{
66+ void *da;
67+
68+ da = (void *)iommu_kmap(isp_iommu, 0, pa, size, IOMMU_FLAG);
69+ if (IS_ERR(da))
70+ return PTR_ERR(da);
71+
72+ return (dma_addr_t)da;
73+}
74+
75+void ispmmu_kunmap(dma_addr_t da)
76+{
77+ iommu_kunmap(isp_iommu, (u32)da);
78+}
79+
80+dma_addr_t ispmmu_vmap(const struct scatterlist *sglist,
81+ int sglen)
82+{
83+ int err;
84+ void *da;
85+ struct sg_table *sgt;
86+ unsigned int i;
87+ struct scatterlist *sg, *src = (struct scatterlist *)sglist;
88+
89+ /*
90+ * convert isp sglist to iommu sgt
91+ * FIXME: should be fixed in the upper layer?
92+ */
93+ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
94+ if (!sgt)
95+ return -ENOMEM;
96+ err = sg_alloc_table(sgt, sglen, GFP_KERNEL);
97+ if (err)
98+ goto err_sg_alloc;
99+
100+ for_each_sg(sgt->sgl, sg, sgt->nents, i)
101+ sg_set_buf(sg, phys_to_virt(sg_dma_address(src + i)),
102+ sg_dma_len(src + i));
103+
104+ da = (void *)iommu_vmap(isp_iommu, 0, sgt, IOMMU_FLAG);
105+ if (IS_ERR(da))
106+ goto err_vmap;
107+
108+ return (dma_addr_t)da;
109+
110+err_vmap:
111+ sg_free_table(sgt);
112+err_sg_alloc:
113+ kfree(sgt);
114+ return -ENOMEM;
115+}
116+EXPORT_SYMBOL_GPL(ispmmu_vmap);
117+
118+void ispmmu_vunmap(dma_addr_t da)
119+{
120+ struct sg_table *sgt;
121+
122+ sgt = iommu_vunmap(isp_iommu, (u32)da);
123+ if (!sgt)
124+ return;
125+ sg_free_table(sgt);
126+ kfree(sgt);
127+}
128+EXPORT_SYMBOL_GPL(ispmmu_vunmap);
129+
130+void ispmmu_save_context(void)
131+{
132+ if (isp_iommu)
133+ iommu_save_ctx(isp_iommu);
134+}
135+
136+void ispmmu_restore_context(void)
137+{
138+ if (isp_iommu)
139+ iommu_restore_ctx(isp_iommu);
140+}
141+
142+int __init ispmmu_init(void)
143+{
144+ int err = 0;
145+
146+ isp_get();
147+ isp_iommu = iommu_get("isp");
148+ if (IS_ERR(isp_iommu)) {
149+ err = PTR_ERR(isp_iommu);
150+ isp_iommu = NULL;
151+ }
152+ isp_put();
153+
154+ return err;
155+}
156+
157+void ispmmu_cleanup(void)
158+{
159+ isp_get();
160+ if (isp_iommu)
161+ iommu_put(isp_iommu);
162+ isp_put();
163+ isp_iommu = NULL;
164+}
165diff --git a/drivers/media/video/isp/ispmmu.h b/drivers/media/video/isp/ispmmu.h
166new file mode 100644
167index 0000000..0bc5bcb
168--- /dev/null
169+++ b/drivers/media/video/isp/ispmmu.h
170@@ -0,0 +1,36 @@
171+/*
172+ * omap iommu wrapper for TI's OMAP3430 Camera ISP
173+ *
174+ * Copyright (C) 2008--2009 Nokia.
175+ *
176+ * Contributors:
177+ * Hiroshi Doyu <hiroshi.doyu@nokia.com>
178+ * Sakari Ailus <sakari.ailus@nokia.com>
179+ *
180+ * This package is free software; you can redistribute it and/or modify
181+ * it under the terms of the GNU General Public License version 2 as
182+ * published by the Free Software Foundation.
183+ *
184+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
185+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
186+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
187+ */
188+
189+#ifndef OMAP_ISP_MMU_H
190+#define OMAP_ISP_MMU_H
191+
192+#include <linux/err.h>
193+#include <linux/scatterlist.h>
194+
195+dma_addr_t ispmmu_vmalloc(size_t bytes);
196+void ispmmu_vfree(const dma_addr_t da);
197+dma_addr_t ispmmu_kmap(u32 pa, int size);
198+void ispmmu_kunmap(dma_addr_t da);
199+dma_addr_t ispmmu_vmap(const struct scatterlist *sglist, int sglen);
200+void ispmmu_vunmap(dma_addr_t da);
201+void ispmmu_save_context(void);
202+void ispmmu_restore_context(void);
203+int ispmmu_init(void);
204+void ispmmu_cleanup(void);
205+
206+#endif /* OMAP_ISP_MMU_H */
207--
2081.5.6.5
209
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch
new file mode 100644
index 0000000000..66c171f544
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0003-omap3isp-Add-userspace-header.patch
@@ -0,0 +1,696 @@
1From 98ca1ef8c6e2561989aeef981131cf5077eab1d1 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add userspace header
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 arch/arm/plat-omap/include/mach/isp_user.h | 676 ++++++++++++++++++++++++++++
9 1 files changed, 676 insertions(+), 0 deletions(-)
10 create mode 100644 arch/arm/plat-omap/include/mach/isp_user.h
11
12diff --git a/arch/arm/plat-omap/include/mach/isp_user.h b/arch/arm/plat-omap/include/mach/isp_user.h
13new file mode 100644
14index 0000000..b819e26
15--- /dev/null
16+++ b/arch/arm/plat-omap/include/mach/isp_user.h
17@@ -0,0 +1,676 @@
18+/*
19+ * isp_user.h
20+ *
21+ * Include file for OMAP ISP module in TI's OMAP3.
22+ *
23+ * Copyright (C) 2009 Texas Instruments, Inc.
24+ *
25+ * Contributors:
26+ * Mohit Jalori <mjalori@ti.com>
27+ * Sergio Aguirre <saaguirre@ti.com>
28+ *
29+ * This package is free software; you can redistribute it and/or modify
30+ * it under the terms of the GNU General Public License version 2 as
31+ * published by the Free Software Foundation.
32+ *
33+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
34+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
35+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
36+ */
37+
38+#ifndef OMAP_ISP_USER_H
39+#define OMAP_ISP_USER_H
40+
41+/* ISP Private IOCTLs */
42+#define VIDIOC_PRIVATE_ISP_CCDC_CFG \
43+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct ispccdc_update_config)
44+#define VIDIOC_PRIVATE_ISP_PRV_CFG \
45+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct ispprv_update_config)
46+#define VIDIOC_PRIVATE_ISP_AEWB_CFG \
47+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct isph3a_aewb_config)
48+#define VIDIOC_PRIVATE_ISP_AEWB_REQ \
49+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct isph3a_aewb_data)
50+#define VIDIOC_PRIVATE_ISP_HIST_CFG \
51+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct isp_hist_config)
52+#define VIDIOC_PRIVATE_ISP_HIST_REQ \
53+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct isp_hist_data)
54+#define VIDIOC_PRIVATE_ISP_AF_CFG \
55+ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct af_configuration)
56+#define VIDIOC_PRIVATE_ISP_AF_REQ \
57+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct isp_af_data)
58+
59+/* AE/AWB related structures and flags*/
60+
61+/* Flags for update field */
62+#define REQUEST_STATISTICS (1 << 0)
63+#define SET_COLOR_GAINS (1 << 1)
64+#define SET_DIGITAL_GAIN (1 << 2)
65+#define SET_EXPOSURE (1 << 3)
66+#define SET_ANALOG_GAIN (1 << 4)
67+
68+#define MAX_FRAME_COUNT 0x0FFF
69+#define MAX_FUTURE_FRAMES 10
70+
71+#define MAX_SATURATION_LIM 1023
72+#define MIN_WIN_H 2
73+#define MAX_WIN_H 256
74+#define MIN_WIN_W 6
75+#define MAX_WIN_W 256
76+#define MAX_WINVC 128
77+#define MAX_WINHC 36
78+#define MAX_WINSTART 4095
79+#define MIN_SUB_INC 2
80+#define MAX_SUB_INC 32
81+
82+/* Range Constants */
83+#define AF_IIRSH_MIN 0
84+#define AF_IIRSH_MAX 4094
85+#define AF_PAXEL_HORIZONTAL_COUNT_MIN 0
86+#define AF_PAXEL_HORIZONTAL_COUNT_MAX 35
87+#define AF_PAXEL_VERTICAL_COUNT_MIN 0
88+#define AF_PAXEL_VERTICAL_COUNT_MAX 127
89+#define AF_PAXEL_INCREMENT_MIN 0
90+#define AF_PAXEL_INCREMENT_MAX 14
91+#define AF_PAXEL_HEIGHT_MIN 0
92+#define AF_PAXEL_HEIGHT_MAX 127
93+#define AF_PAXEL_WIDTH_MIN 0
94+#define AF_PAXEL_WIDTH_MAX 127
95+#define AF_PAXEL_HZSTART_MIN 2
96+#define AF_PAXEL_HZSTART_MAX 4094
97+
98+#define AF_PAXEL_VTSTART_MIN 0
99+#define AF_PAXEL_VTSTART_MAX 4095
100+#define AF_THRESHOLD_MAX 255
101+#define AF_COEF_MAX 4095
102+#define AF_PAXEL_SIZE 48
103+
104+/**
105+ * struct isph3a_aewb_config - AE AWB configuration reset values.
106+ * saturation_limit: Saturation limit.
107+ * @win_height: Window Height. Range 2 - 256, even values only.
108+ * @win_width: Window Width. Range 6 - 256, even values only.
109+ * @ver_win_count: Vertical Window Count. Range 1 - 128.
110+ * @hor_win_count: Horizontal Window Count. Range 1 - 36.
111+ * @ver_win_start: Vertical Window Start. Range 0 - 4095.
112+ * @hor_win_start: Horizontal Window Start. Range 0 - 4095.
113+ * @blk_ver_win_start: Black Vertical Windows Start. Range 0 - 4095.
114+ * @blk_win_height: Black Window Height. Range 2 - 256, even values only.
115+ * @subsample_ver_inc: Subsample Vertical points increment Range 2 - 32, even
116+ * values only.
117+ * @subsample_hor_inc: Subsample Horizontal points increment Range 2 - 32, even
118+ * values only.
119+ * @alaw_enable: AEW ALAW EN flag.
120+ * @aewb_enable: AE AWB stats generation EN flag.
121+ */
122+struct isph3a_aewb_config {
123+ __u16 saturation_limit;
124+ __u16 win_height;
125+ __u16 win_width;
126+ __u16 ver_win_count;
127+ __u16 hor_win_count;
128+ __u16 ver_win_start;
129+ __u16 hor_win_start;
130+ __u16 blk_ver_win_start;
131+ __u16 blk_win_height;
132+ __u16 subsample_ver_inc;
133+ __u16 subsample_hor_inc;
134+ __u8 alaw_enable;
135+ __u8 aewb_enable;
136+};
137+
138+/**
139+ * struct isph3a_aewb_data - Structure of data sent to or received from user
140+ * @h3a_aewb_statistics_buf: Pointer to pass to user.
141+ * @shutter: Shutter speed.
142+ * @gain: Sensor analog Gain.
143+ * @shutter_cap: Shutter speed for capture.
144+ * @gain_cap: Sensor Gain for capture.
145+ * @dgain: White balance digital gain.
146+ * @wb_gain_b: White balance color gain blue.
147+ * @wb_gain_r: White balance color gain red.
148+ * @wb_gain_gb: White balance color gain green blue.
149+ * @wb_gain_gr: White balance color gain green red.
150+ * @frame_number: Frame number of requested stats.
151+ * @curr_frame: Current frame number being processed.
152+ * @update: Bitwise flags to update parameters.
153+ * @ts: Timestamp of returned framestats.
154+ * @field_count: Sequence number of returned framestats.
155+ */
156+struct isph3a_aewb_data {
157+ void *h3a_aewb_statistics_buf;
158+ __u32 shutter;
159+ __u16 gain;
160+ __u32 shutter_cap;
161+ __u16 gain_cap;
162+ __u16 dgain;
163+ __u16 wb_gain_b;
164+ __u16 wb_gain_r;
165+ __u16 wb_gain_gb;
166+ __u16 wb_gain_gr;
167+ __u16 frame_number;
168+ __u16 curr_frame;
169+ __u8 update;
170+ struct timeval ts;
171+ __u32 config_counter;
172+ unsigned long field_count;
173+};
174+
175+
176+/* Histogram related structs */
177+/* Flags for number of bins */
178+#define BINS_32 0x0
179+#define BINS_64 0x1
180+#define BINS_128 0x2
181+#define BINS_256 0x3
182+
183+struct isp_hist_config {
184+ __u8 hist_source; /* CCDC or Memory */
185+ __u8 input_bit_width; /* Needed o know the size per pixel */
186+ __u8 hist_frames; /* Num of frames to be processed and
187+ * accumulated
188+ */
189+ __u8 hist_h_v_info; /* frame-input width and height if source is
190+ * memory
191+ */
192+ __u16 hist_radd; /* frame-input address in memory */
193+ __u16 hist_radd_off; /* line-offset for frame-input */
194+ __u16 hist_bins; /* number of bins: 32, 64, 128, or 256 */
195+ __u16 wb_gain_R; /* White Balance Field-to-Pattern Assignments */
196+ __u16 wb_gain_RG; /* White Balance Field-to-Pattern Assignments */
197+ __u16 wb_gain_B; /* White Balance Field-to-Pattern Assignments */
198+ __u16 wb_gain_BG; /* White Balance Field-to-Pattern Assignments */
199+ __u8 num_regions; /* number of regions to be configured */
200+ __u16 reg0_hor; /* Region 0 size and position */
201+ __u16 reg0_ver; /* Region 0 size and position */
202+ __u16 reg1_hor; /* Region 1 size and position */
203+ __u16 reg1_ver; /* Region 1 size and position */
204+ __u16 reg2_hor; /* Region 2 size and position */
205+ __u16 reg2_ver; /* Region 2 size and position */
206+ __u16 reg3_hor; /* Region 3 size and position */
207+ __u16 reg3_ver; /* Region 3 size and position */
208+};
209+
210+struct isp_hist_data {
211+ __u32 *hist_statistics_buf; /* Pointer to pass to user */
212+};
213+
214+/* Auto Focus related structs */
215+
216+#define AF_NUMBER_OF_COEF 11
217+
218+/* Flags for update field */
219+#define REQUEST_STATISTICS (1 << 0)
220+#define LENS_DESIRED_POSITION (1 << 1)
221+#define LENS_CURRENT_POSITION (1 << 2)
222+
223+/**
224+ * struct isp_af_xtrastats - Extra statistics related to AF generated stats.
225+ * @ts: Timestamp when the frame gets delivered to the user.
226+ * @field_count: Field count of the frame delivered to the user.
227+ * @lens_position: Lens position when the stats are being generated.
228+ */
229+struct isp_af_xtrastats {
230+ struct timeval ts;
231+ unsigned long field_count;
232+ __u16 lens_position; /* deprecated */
233+};
234+
235+/**
236+ * struct isp_af_data - AF statistics data to transfer between driver and user.
237+ * @af_statistics_buf: Pointer to pass to user.
238+ * @lens_current_position: Read value of lens absolute position.
239+ * @desired_lens_direction: Lens desired location.
240+ * @update: Bitwise flags to update parameters.
241+ * @frame_number: Data for which frame is desired/given.
242+ * @curr_frame: Current frame number being processed by AF module.
243+ * @xtrastats: Extra statistics structure.
244+ */
245+struct isp_af_data {
246+ void *af_statistics_buf;
247+ __u16 lens_current_position; /* deprecated */
248+ __u16 desired_lens_direction; /* deprecated */
249+ __u16 update;
250+ __u16 frame_number;
251+ __u16 curr_frame;
252+ __u32 config_counter;
253+ struct isp_af_xtrastats xtrastats;
254+};
255+
256+/* enum used for status of specific feature */
257+enum af_alaw_enable {
258+ H3A_AF_ALAW_DISABLE = 0,
259+ H3A_AF_ALAW_ENABLE = 1
260+};
261+
262+enum af_hmf_enable {
263+ H3A_AF_HMF_DISABLE = 0,
264+ H3A_AF_HMF_ENABLE = 1
265+};
266+
267+enum af_config_flag {
268+ H3A_AF_CFG_DISABLE = 0,
269+ H3A_AF_CFG_ENABLE = 1
270+};
271+
272+enum af_mode {
273+ ACCUMULATOR_SUMMED = 0,
274+ ACCUMULATOR_PEAK = 1
275+};
276+
277+/* Red, Green, and blue pixel location in the AF windows */
278+enum rgbpos {
279+ GR_GB_BAYER = 0, /* GR and GB as Bayer pattern */
280+ RG_GB_BAYER = 1, /* RG and GB as Bayer pattern */
281+ GR_BG_BAYER = 2, /* GR and BG as Bayer pattern */
282+ RG_BG_BAYER = 3, /* RG and BG as Bayer pattern */
283+ GG_RB_CUSTOM = 4, /* GG and RB as custom pattern */
284+ RB_GG_CUSTOM = 5 /* RB and GG as custom pattern */
285+};
286+
287+/* Contains the information regarding the Horizontal Median Filter */
288+struct af_hmf {
289+ enum af_hmf_enable enable; /* Status of Horizontal Median Filter */
290+ unsigned int threshold; /* Threshhold Value for Horizontal Median
291+ * Filter
292+ */
293+};
294+
295+/* Contains the information regarding the IIR Filters */
296+struct af_iir {
297+ unsigned int hz_start_pos; /* IIR Start Register Value */
298+ int coeff_set0[AF_NUMBER_OF_COEF]; /*
299+ * IIR Filter Coefficient for
300+ * Set 0
301+ */
302+ int coeff_set1[AF_NUMBER_OF_COEF]; /*
303+ * IIR Filter Coefficient for
304+ * Set 1
305+ */
306+};
307+
308+/* Contains the information regarding the Paxels Structure in AF Engine */
309+struct af_paxel {
310+ unsigned int width; /* Width of the Paxel */
311+ unsigned int height; /* Height of the Paxel */
312+ unsigned int hz_start; /* Horizontal Start Position */
313+ unsigned int vt_start; /* Vertical Start Position */
314+ unsigned int hz_cnt; /* Horizontal Count */
315+ unsigned int vt_cnt; /* vertical Count */
316+ unsigned int line_incr; /* Line Increment */
317+};
318+/* Contains the parameters required for hardware set up of AF Engine */
319+struct af_configuration {
320+ enum af_alaw_enable alaw_enable; /*ALWAW status */
321+ struct af_hmf hmf_config; /*HMF configurations */
322+ enum rgbpos rgb_pos; /*RGB Positions */
323+ struct af_iir iir_config; /*IIR filter configurations */
324+ struct af_paxel paxel_config; /*Paxel parameters */
325+ enum af_mode mode; /*Accumulator mode */
326+ enum af_config_flag af_config; /*Flag indicates Engine is configured */
327+};
328+
329+/* ISP CCDC structs */
330+
331+/* Abstraction layer CCDC configurations */
332+#define ISP_ABS_CCDC_ALAW (1 << 0)
333+#define ISP_ABS_CCDC_LPF (1 << 1)
334+#define ISP_ABS_CCDC_BLCLAMP (1 << 2)
335+#define ISP_ABS_CCDC_BCOMP (1 << 3)
336+#define ISP_ABS_CCDC_FPC (1 << 4)
337+#define ISP_ABS_CCDC_CULL (1 << 5)
338+#define ISP_ABS_CCDC_COLPTN (1 << 6)
339+#define ISP_ABS_CCDC_CONFIG_LSC (1 << 7)
340+#define ISP_ABS_TBL_LSC (1 << 8)
341+
342+#define RGB_MAX 3
343+
344+/* Enumeration constants for Alaw input width */
345+enum alaw_ipwidth {
346+ ALAW_BIT12_3 = 0x3,
347+ ALAW_BIT11_2 = 0x4,
348+ ALAW_BIT10_1 = 0x5,
349+ ALAW_BIT9_0 = 0x6
350+};
351+
352+/* Enumeration constants for Video Port */
353+enum vpin {
354+ BIT12_3 = 3,
355+ BIT11_2 = 4,
356+ BIT10_1 = 5,
357+ BIT9_0 = 6
358+};
359+
360+enum vpif_freq {
361+ PIXCLKBY2,
362+ PIXCLKBY3_5,
363+ PIXCLKBY4_5,
364+ PIXCLKBY5_5,
365+ PIXCLKBY6_5
366+};
367+
368+/**
369+ * struct ispccdc_lsc_config - Structure for LSC configuration.
370+ * @offset: Table Offset of the gain table.
371+ * @gain_mode_n: Vertical dimension of a paxel in LSC configuration.
372+ * @gain_mode_m: Horizontal dimension of a paxel in LSC configuration.
373+ * @gain_format: Gain table format.
374+ * @fmtsph: Start pixel horizontal from start of the HS sync pulse.
375+ * @fmtlnh: Number of pixels in horizontal direction to use for the data
376+ * reformatter.
377+ * @fmtslv: Start line from start of VS sync pulse for the data reformatter.
378+ * @fmtlnv: Number of lines in vertical direction for the data reformatter.
379+ * @initial_x: X position, in pixels, of the first active pixel in reference
380+ * to the first active paxel. Must be an even number.
381+ * @initial_y: Y position, in pixels, of the first active pixel in reference
382+ * to the first active paxel. Must be an even number.
383+ * @size: Size of LSC gain table. Filled when loaded from userspace.
384+ */
385+struct ispccdc_lsc_config {
386+ __u16 offset;
387+ __u8 gain_mode_n;
388+ __u8 gain_mode_m;
389+ __u8 gain_format;
390+ __u16 fmtsph;
391+ __u16 fmtlnh;
392+ __u16 fmtslv;
393+ __u16 fmtlnv;
394+ __u8 initial_x;
395+ __u8 initial_y;
396+ __u32 size;
397+};
398+
399+/**
400+ * struct ispccdc_bclamp - Structure for Optical & Digital black clamp subtract
401+ * @obgain: Optical black average gain.
402+ * @obstpixel: Start Pixel w.r.t. HS pulse in Optical black sample.
403+ * @oblines: Optical Black Sample lines.
404+ * @oblen: Optical Black Sample Length.
405+ * @dcsubval: Digital Black Clamp subtract value.
406+ */
407+struct ispccdc_bclamp {
408+ __u8 obgain;
409+ __u8 obstpixel;
410+ __u8 oblines;
411+ __u8 oblen;
412+ __u16 dcsubval;
413+};
414+
415+/**
416+ * ispccdc_fpc - Structure for FPC
417+ * @fpnum: Number of faulty pixels to be corrected in the frame.
418+ * @fpcaddr: Memory address of the FPC Table
419+ */
420+struct ispccdc_fpc {
421+ __u16 fpnum;
422+ __u32 fpcaddr;
423+};
424+
425+/**
426+ * ispccdc_blcomp - Structure for Black Level Compensation parameters.
427+ * @b_mg: B/Mg pixels. 2's complement. -128 to +127.
428+ * @gb_g: Gb/G pixels. 2's complement. -128 to +127.
429+ * @gr_cy: Gr/Cy pixels. 2's complement. -128 to +127.
430+ * @r_ye: R/Ye pixels. 2's complement. -128 to +127.
431+ */
432+struct ispccdc_blcomp {
433+ __u8 b_mg;
434+ __u8 gb_g;
435+ __u8 gr_cy;
436+ __u8 r_ye;
437+};
438+
439+/**
440+ * struct ispccdc_vp - Structure for Video Port parameters
441+ * @bitshift_sel: Video port input select. 3 - bits 12-3, 4 - bits 11-2,
442+ * 5 - bits 10-1, 6 - bits 9-0.
443+ * @freq_sel: Video port data ready frequency. 1 - 1/3.5, 2 - 1/4.5,
444+ * 3 - 1/5.5, 4 - 1/6.5.
445+ */
446+struct ispccdc_vp {
447+ enum vpin bitshift_sel;
448+ enum vpif_freq freq_sel;
449+};
450+
451+/**
452+ * ispccdc_culling - Structure for Culling parameters.
453+ * @v_pattern: Vertical culling pattern.
454+ * @h_odd: Horizontal Culling pattern for odd lines.
455+ * @h_even: Horizontal Culling pattern for even lines.
456+ */
457+struct ispccdc_culling {
458+ __u8 v_pattern;
459+ __u16 h_odd;
460+ __u16 h_even;
461+};
462+
463+/**
464+ * ispccdc_update_config - Structure for CCDC configuration.
465+ * @update: Specifies which CCDC registers should be updated.
466+ * @flag: Specifies which CCDC functions should be enabled.
467+ * @alawip: Enable/Disable A-Law compression.
468+ * @bclamp: Black clamp control register.
469+ * @blcomp: Black level compensation value for RGrGbB Pixels. 2's complement.
470+ * @fpc: Number of faulty pixels corrected in the frame, address of FPC table.
471+ * @cull: Cull control register.
472+ * @colptn: Color pattern of the sensor.
473+ * @lsc: Pointer to LSC gain table.
474+ */
475+struct ispccdc_update_config {
476+ __u16 update;
477+ __u16 flag;
478+ enum alaw_ipwidth alawip;
479+ struct ispccdc_bclamp *bclamp;
480+ struct ispccdc_blcomp *blcomp;
481+ struct ispccdc_fpc *fpc;
482+ struct ispccdc_lsc_config *lsc_cfg;
483+ struct ispccdc_culling *cull;
484+ __u32 colptn;
485+ __u8 *lsc;
486+};
487+
488+/* Preview configuration */
489+
490+/*Abstraction layer preview configurations*/
491+#define ISP_ABS_PREV_LUMAENH (1 << 0)
492+#define ISP_ABS_PREV_INVALAW (1 << 1)
493+#define ISP_ABS_PREV_HRZ_MED (1 << 2)
494+#define ISP_ABS_PREV_CFA (1 << 3)
495+#define ISP_ABS_PREV_CHROMA_SUPP (1 << 4)
496+#define ISP_ABS_PREV_WB (1 << 5)
497+#define ISP_ABS_PREV_BLKADJ (1 << 6)
498+#define ISP_ABS_PREV_RGB2RGB (1 << 7)
499+#define ISP_ABS_PREV_COLOR_CONV (1 << 8)
500+#define ISP_ABS_PREV_YC_LIMIT (1 << 9)
501+#define ISP_ABS_PREV_DEFECT_COR (1 << 10)
502+#define ISP_ABS_PREV_GAMMABYPASS (1 << 11)
503+#define ISP_ABS_TBL_NF (1 << 12)
504+#define ISP_ABS_TBL_REDGAMMA (1 << 13)
505+#define ISP_ABS_TBL_GREENGAMMA (1 << 14)
506+#define ISP_ABS_TBL_BLUEGAMMA (1 << 15)
507+
508+#define ISPPRV_NF_TBL_SIZE 64
509+#define ISPPRV_CFA_TBL_SIZE 576
510+#define ISPPRV_GAMMA_TBL_SIZE 1024
511+#define ISPPRV_YENH_TBL_SIZE 128
512+
513+/**
514+ * struct ispprev_hmed - Structure for Horizontal Median Filter.
515+ * @odddist: Distance between consecutive pixels of same color in the odd line.
516+ * @evendist: Distance between consecutive pixels of same color in the even
517+ * line.
518+ * @thres: Horizontal median filter threshold.
519+ */
520+struct ispprev_hmed {
521+ __u8 odddist;
522+ __u8 evendist;
523+ __u8 thres;
524+};
525+
526+/*
527+ * Enumeration for CFA Formats supported by preview
528+ */
529+enum cfa_fmt {
530+ CFAFMT_BAYER, CFAFMT_SONYVGA, CFAFMT_RGBFOVEON,
531+ CFAFMT_DNSPL, CFAFMT_HONEYCOMB, CFAFMT_RRGGBBFOVEON
532+};
533+
534+/**
535+ * struct ispprev_cfa - Structure for CFA Inpterpolation.
536+ * @cfafmt: CFA Format Enum value supported by preview.
537+ * @cfa_gradthrs_vert: CFA Gradient Threshold - Vertical.
538+ * @cfa_gradthrs_horz: CFA Gradient Threshold - Horizontal.
539+ * @cfa_table: Pointer to the CFA table.
540+ */
541+struct ispprev_cfa {
542+ enum cfa_fmt cfafmt;
543+ __u8 cfa_gradthrs_vert;
544+ __u8 cfa_gradthrs_horz;
545+ __u32 *cfa_table;
546+};
547+
548+/**
549+ * struct ispprev_csup - Structure for Chrominance Suppression.
550+ * @gain: Gain.
551+ * @thres: Threshold.
552+ * @hypf_en: Flag to enable/disable the High Pass Filter.
553+ */
554+struct ispprev_csup {
555+ __u8 gain;
556+ __u8 thres;
557+ __u8 hypf_en;
558+};
559+
560+/**
561+ * struct ispprev_wbal - Structure for White Balance.
562+ * @dgain: Digital gain (U10Q8).
563+ * @coef3: White balance gain - COEF 3 (U8Q5).
564+ * @coef2: White balance gain - COEF 2 (U8Q5).
565+ * @coef1: White balance gain - COEF 1 (U8Q5).
566+ * @coef0: White balance gain - COEF 0 (U8Q5).
567+ */
568+struct ispprev_wbal {
569+ __u16 dgain;
570+ __u8 coef3;
571+ __u8 coef2;
572+ __u8 coef1;
573+ __u8 coef0;
574+};
575+
576+/**
577+ * struct ispprev_blkadj - Structure for Black Adjustment.
578+ * @red: Black level offset adjustment for Red in 2's complement format
579+ * @green: Black level offset adjustment for Green in 2's complement format
580+ * @blue: Black level offset adjustment for Blue in 2's complement format
581+ */
582+struct ispprev_blkadj {
583+ /*Black level offset adjustment for Red in 2's complement format */
584+ __u8 red;
585+ /*Black level offset adjustment for Green in 2's complement format */
586+ __u8 green;
587+ /* Black level offset adjustment for Blue in 2's complement format */
588+ __u8 blue;
589+};
590+
591+/**
592+ * struct ispprev_rgbtorgb - Structure for RGB to RGB Blending.
593+ * @matrix: Blending values(S12Q8 format)
594+ * [RR] [GR] [BR]
595+ * [RG] [GG] [BG]
596+ * [RB] [GB] [BB]
597+ * @offset: Blending offset value for R,G,B in 2's complement integer format.
598+ */
599+struct ispprev_rgbtorgb {
600+ __u16 matrix[3][3];
601+ __u16 offset[3];
602+};
603+
604+/**
605+ * struct ispprev_csc - Structure for Color Space Conversion from RGB-YCbYCr
606+ * @matrix: Color space conversion coefficients(S10Q8)
607+ * [CSCRY] [CSCGY] [CSCBY]
608+ * [CSCRCB] [CSCGCB] [CSCBCB]
609+ * [CSCRCR] [CSCGCR] [CSCBCR]
610+ * @offset: CSC offset values for Y offset, CB offset and CR offset respectively
611+ */
612+struct ispprev_csc {
613+ __u16 matrix[RGB_MAX][RGB_MAX];
614+ __s16 offset[RGB_MAX];
615+};
616+
617+/**
618+ * struct ispprev_yclimit - Structure for Y, C Value Limit.
619+ * @minC: Minimum C value
620+ * @maxC: Maximum C value
621+ * @minY: Minimum Y value
622+ * @maxY: Maximum Y value
623+ */
624+struct ispprev_yclimit {
625+ __u8 minC;
626+ __u8 maxC;
627+ __u8 minY;
628+ __u8 maxY;
629+};
630+
631+/**
632+ * struct ispprev_dcor - Structure for Defect correction.
633+ * @couplet_mode_en: Flag to enable or disable the couplet dc Correction in NF
634+ * @detect_correct: Thresholds for correction bit 0:10 detect 16:25 correct
635+ */
636+struct ispprev_dcor {
637+ __u8 couplet_mode_en;
638+ __u32 detect_correct[4];
639+};
640+
641+/**
642+ * struct ispprev_nf - Structure for Noise Filter
643+ * @spread: Spread value to be used in Noise Filter
644+ * @table: Pointer to the Noise Filter table
645+ */
646+struct ispprev_nf {
647+ __u8 spread;
648+ __u32 table[ISPPRV_NF_TBL_SIZE];
649+};
650+
651+/**
652+ * struct ispprv_update_config - Structure for Preview Configuration (user).
653+ * @update: Specifies which ISP Preview registers should be updated.
654+ * @flag: Specifies which ISP Preview functions should be enabled.
655+ * @yen: Pointer to luma enhancement table.
656+ * @shading_shift: 3bit value of shift used in shading compensation.
657+ * @prev_hmed: Pointer to structure containing the odd and even distance.
658+ * between the pixels in the image along with the filter threshold.
659+ * @prev_cfa: Pointer to structure containing the CFA interpolation table, CFA.
660+ * format in the image, vertical and horizontal gradient threshold.
661+ * @csup: Pointer to Structure for Chrominance Suppression coefficients.
662+ * @prev_wbal: Pointer to structure for White Balance.
663+ * @prev_blkadj: Pointer to structure for Black Adjustment.
664+ * @rgb2rgb: Pointer to structure for RGB to RGB Blending.
665+ * @prev_csc: Pointer to structure for Color Space Conversion from RGB-YCbYCr.
666+ * @yclimit: Pointer to structure for Y, C Value Limit.
667+ * @prev_dcor: Pointer to structure for defect correction.
668+ * @prev_nf: Pointer to structure for Noise Filter
669+ * @red_gamma: Pointer to red gamma correction table.
670+ * @green_gamma: Pointer to green gamma correction table.
671+ * @blue_gamma: Pointer to blue gamma correction table.
672+ */
673+struct ispprv_update_config {
674+ __u16 update;
675+ __u16 flag;
676+ void *yen;
677+ __u32 shading_shift;
678+ struct ispprev_hmed *prev_hmed;
679+ struct ispprev_cfa *prev_cfa;
680+ struct ispprev_csup *csup;
681+ struct ispprev_wbal *prev_wbal;
682+ struct ispprev_blkadj *prev_blkadj;
683+ struct ispprev_rgbtorgb *rgb2rgb;
684+ struct ispprev_csc *prev_csc;
685+ struct ispprev_yclimit *yclimit;
686+ struct ispprev_dcor *prev_dcor;
687+ struct ispprev_nf *prev_nf;
688+ __u32 *red_gamma;
689+ __u32 *green_gamma;
690+ __u32 *blue_gamma;
691+};
692+
693+#endif /* OMAP_ISP_USER_H */
694--
6951.5.6.5
696
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
new file mode 100644
index 0000000000..4a161729fd
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
@@ -0,0 +1,1875 @@
1From 9ea796fe5383a6961125a6a18185a901fe8627d7 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add ISP frontend (CCDC)
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 drivers/media/video/isp/ispccdc.c | 1638 +++++++++++++++++++++++++++++++++++++
9 drivers/media/video/isp/ispccdc.h | 209 +++++
10 2 files changed, 1847 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/media/video/isp/ispccdc.c
12 create mode 100644 drivers/media/video/isp/ispccdc.h
13
14diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c
15new file mode 100644
16index 0000000..2574ea2
17--- /dev/null
18+++ b/drivers/media/video/isp/ispccdc.c
19@@ -0,0 +1,1638 @@
20+/*
21+ * ispccdc.c
22+ *
23+ * Driver Library for CCDC module in TI's OMAP3 Camera ISP
24+ *
25+ * Copyright (C) 2009 Texas Instruments, Inc.
26+ *
27+ * Contributors:
28+ * Senthilvadivu Guruswamy <svadivu@ti.com>
29+ * Pallavi Kulkarni <p-kulkarni@ti.com>
30+ * Sergio Aguirre <saaguirre@ti.com>
31+ *
32+ * This package is free software; you can redistribute it and/or modify
33+ * it under the terms of the GNU General Public License version 2 as
34+ * published by the Free Software Foundation.
35+ *
36+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
37+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
38+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39+ */
40+
41+#include <linux/mutex.h>
42+#include <linux/module.h>
43+#include <linux/uaccess.h>
44+
45+#include "isp.h"
46+#include "ispreg.h"
47+#include "ispccdc.h"
48+#include "ispmmu.h"
49+
50+#define LSC_TABLE_INIT_SIZE 50052
51+
52+static u32 *fpc_table_add;
53+static unsigned long fpc_table_add_m;
54+
55+/**
56+ * struct isp_ccdc - Structure for the CCDC module to store its own information
57+ * @ccdc_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
58+ * @ccdcout_w: CCDC output width.
59+ * @ccdcout_h: CCDC output height.
60+ * @ccdcin_w: CCDC input width.
61+ * @ccdcin_h: CCDC input height.
62+ * @ccdcin_woffset: CCDC input horizontal offset.
63+ * @ccdcin_hoffset: CCDC input vertical offset.
64+ * @crop_w: Crop width.
65+ * @crop_h: Crop weight.
66+ * @ccdc_inpfmt: CCDC input format.
67+ * @ccdc_outfmt: CCDC output format.
68+ * @vpout_en: Video port output enable.
69+ * @wen: Data write enable.
70+ * @exwen: External data write enable.
71+ * @refmt_en: Reformatter enable.
72+ * @ccdcslave: CCDC slave mode enable.
73+ * @syncif_ipmod: Image
74+ * @obclamp_en: Data input format.
75+ * @mutexlock: Mutex used to get access to the CCDC.
76+ */
77+static struct isp_ccdc {
78+ u8 ccdc_inuse;
79+ u32 ccdcout_w;
80+ u32 ccdcout_h;
81+ u32 ccdcin_w;
82+ u32 ccdcin_h;
83+ u32 ccdcin_woffset;
84+ u32 ccdcin_hoffset;
85+ u32 crop_w;
86+ u32 crop_h;
87+ u8 ccdc_inpfmt;
88+ u8 ccdc_outfmt;
89+ u8 vpout_en;
90+ u8 wen;
91+ u8 exwen;
92+ u8 refmt_en;
93+ u8 ccdcslave;
94+ u8 syncif_ipmod;
95+ u8 obclamp_en;
96+ u8 pm_state;
97+ u8 lsc_enable;
98+ int lsc_state;
99+ struct mutex mutexlock; /* For checking/modifying ccdc_inuse */
100+ u32 wenlog;
101+} ispccdc_obj;
102+
103+static struct ispccdc_lsc_config lsc_config;
104+static u8 *lsc_gain_table;
105+static unsigned long lsc_ispmmu_addr;
106+static int lsc_initialized;
107+static u8 *lsc_gain_table_tmp;
108+
109+/* Structure for saving/restoring CCDC module registers*/
110+static struct isp_reg ispccdc_reg_list[] = {
111+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, 0},
112+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HD_VD_WID, 0},
113+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PIX_LINES, 0},
114+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO, 0},
115+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START, 0},
116+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES, 0},
117+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING, 0},
118+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF, 0},
119+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, 0},
120+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR, 0},
121+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, 0},
122+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB, 0},
123+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN, 0},
124+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP, 0},
125+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, 0},
126+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR, 0},
127+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT, 0},
128+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, 0},
129+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, 0},
130+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, 0},
131+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, 0},
132+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ, 0},
133+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT, 0},
134+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0, 0},
135+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1, 0},
136+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2, 0},
137+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3, 0},
138+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4, 0},
139+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5, 0},
140+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6, 0},
141+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7, 0},
142+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0, 0},
143+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1, 0},
144+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0, 0},
145+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1, 0},
146+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT, 0},
147+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0},
148+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL, 0},
149+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE, 0},
150+ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET, 0},
151+ {0, ISP_TOK_TERM, 0}
152+};
153+
154+/**
155+ * omap34xx_isp_ccdc_config - Sets CCDC configuration from userspace
156+ * @userspace_add: Structure containing CCDC configuration sent from userspace.
157+ *
158+ * Returns 0 if successful, -EINVAL if the pointer to the configuration
159+ * structure is null, or the copy_from_user function fails to copy user space
160+ * memory to kernel space memory.
161+ **/
162+int omap34xx_isp_ccdc_config(void *userspace_add)
163+{
164+ struct ispccdc_bclamp bclamp_t;
165+ struct ispccdc_blcomp blcomp_t;
166+ struct ispccdc_fpc fpc_t;
167+ struct ispccdc_culling cull_t;
168+ struct ispccdc_update_config *ccdc_struct;
169+
170+ if (userspace_add == NULL)
171+ return -EINVAL;
172+
173+ ccdc_struct = userspace_add;
174+
175+ if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) {
176+ if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
177+ ispccdc_config_alaw(ccdc_struct->alawip);
178+ ispccdc_enable_alaw(1);
179+ } else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update)
180+ ispccdc_enable_alaw(0);
181+
182+ if (ISP_ABS_CCDC_LPF & ccdc_struct->flag)
183+ ispccdc_enable_lpf(1);
184+ else
185+ ispccdc_enable_lpf(0);
186+
187+ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) {
188+ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
189+ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
190+ ccdc_struct->bclamp,
191+ sizeof(struct ispccdc_bclamp)))
192+ goto copy_from_user_err;
193+
194+ ispccdc_enable_black_clamp(1);
195+ ispccdc_config_black_clamp(bclamp_t);
196+ } else
197+ ispccdc_enable_black_clamp(1);
198+ } else {
199+ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) {
200+ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *)
201+ ccdc_struct->bclamp,
202+ sizeof(struct ispccdc_bclamp)))
203+ goto copy_from_user_err;
204+
205+ ispccdc_enable_black_clamp(0);
206+ ispccdc_config_black_clamp(bclamp_t);
207+ }
208+ }
209+
210+ if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) {
211+ if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *)
212+ ccdc_struct->blcomp,
213+ sizeof(blcomp_t)))
214+ goto copy_from_user_err;
215+
216+ ispccdc_config_black_comp(blcomp_t);
217+ }
218+
219+ if (ISP_ABS_CCDC_FPC & ccdc_struct->flag) {
220+ if (ISP_ABS_CCDC_FPC & ccdc_struct->update) {
221+ if (copy_from_user(&fpc_t, (struct ispccdc_fpc *)
222+ ccdc_struct->fpc,
223+ sizeof(fpc_t)))
224+ goto copy_from_user_err;
225+ fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4,
226+ GFP_KERNEL | GFP_DMA);
227+ if (!fpc_table_add) {
228+ printk(KERN_ERR "Cannot allocate memory for"
229+ " FPC table");
230+ return -ENOMEM;
231+ }
232+ while (((unsigned long)fpc_table_add & 0xFFFFFFC0)
233+ != (unsigned long)fpc_table_add)
234+ fpc_table_add++;
235+
236+ fpc_table_add_m = ispmmu_kmap(virt_to_phys
237+ (fpc_table_add),
238+ fpc_t.fpnum * 4);
239+
240+ if (copy_from_user(fpc_table_add, (u32 *)fpc_t.fpcaddr,
241+ fpc_t.fpnum * 4))
242+ goto copy_from_user_err;
243+
244+ fpc_t.fpcaddr = fpc_table_add_m;
245+ ispccdc_config_fpc(fpc_t);
246+ }
247+ ispccdc_enable_fpc(1);
248+ } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update)
249+ ispccdc_enable_fpc(0);
250+
251+ if (ISP_ABS_CCDC_CULL & ccdc_struct->update) {
252+ if (copy_from_user(&cull_t, (struct ispccdc_culling *)
253+ ccdc_struct->cull,
254+ sizeof(cull_t)))
255+ goto copy_from_user_err;
256+ ispccdc_config_culling(cull_t);
257+ }
258+
259+ if (is_isplsc_activated()) {
260+ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) {
261+ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
262+ if (copy_from_user(
263+ &lsc_config,
264+ (struct ispccdc_lsc_config *)
265+ ccdc_struct->lsc_cfg,
266+ sizeof(struct ispccdc_lsc_config)))
267+ goto copy_from_user_err;
268+ ispccdc_config_lsc(&lsc_config);
269+ }
270+ ispccdc_enable_lsc(1);
271+ } else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) {
272+ ispccdc_enable_lsc(0);
273+ }
274+ if (ISP_ABS_TBL_LSC & ccdc_struct->update) {
275+ if (copy_from_user(lsc_gain_table,
276+ ccdc_struct->lsc, lsc_config.size))
277+ goto copy_from_user_err;
278+ ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
279+ }
280+ }
281+
282+ if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update)
283+ ispccdc_config_imgattr(ccdc_struct->colptn);
284+
285+ return 0;
286+
287+copy_from_user_err:
288+ printk(KERN_ERR "CCDC Config:Copy From User Error");
289+ return -EINVAL ;
290+}
291+EXPORT_SYMBOL(omap34xx_isp_ccdc_config);
292+
293+/**
294+ * Set the value to be used for CCDC_CFG.WENLOG.
295+ * w - Value of wenlog.
296+ */
297+void ispccdc_set_wenlog(u32 wenlog)
298+{
299+ ispccdc_obj.wenlog = wenlog;
300+}
301+EXPORT_SYMBOL(ispccdc_set_wenlog);
302+
303+/**
304+ * ispccdc_request - Reserves the CCDC module.
305+ *
306+ * Reserves the CCDC module and assures that is used only once at a time.
307+ *
308+ * Returns 0 if successful, or -EBUSY if CCDC module is busy.
309+ **/
310+int ispccdc_request(void)
311+{
312+ mutex_lock(&ispccdc_obj.mutexlock);
313+ if (ispccdc_obj.ccdc_inuse) {
314+ mutex_unlock(&ispccdc_obj.mutexlock);
315+ DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy\n");
316+ return -EBUSY;
317+ }
318+
319+ ispccdc_obj.ccdc_inuse = 1;
320+ mutex_unlock(&ispccdc_obj.mutexlock);
321+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_CCDC_RAM_EN |
322+ ISPCTRL_CCDC_CLK_EN |
323+ ISPCTRL_SBL_WR1_RAM_EN);
324+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
325+ return 0;
326+}
327+EXPORT_SYMBOL(ispccdc_request);
328+
329+/**
330+ * ispccdc_free - Frees the CCDC module.
331+ *
332+ * Frees the CCDC module so it can be used by another process.
333+ *
334+ * Returns 0 if successful, or -EINVAL if module has been already freed.
335+ **/
336+int ispccdc_free(void)
337+{
338+ mutex_lock(&ispccdc_obj.mutexlock);
339+ if (!ispccdc_obj.ccdc_inuse) {
340+ mutex_unlock(&ispccdc_obj.mutexlock);
341+ DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n");
342+ return -EINVAL;
343+ }
344+
345+ ispccdc_obj.ccdc_inuse = 0;
346+ mutex_unlock(&ispccdc_obj.mutexlock);
347+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
348+ ~(ISPCTRL_CCDC_CLK_EN |
349+ ISPCTRL_CCDC_RAM_EN |
350+ ISPCTRL_SBL_WR1_RAM_EN));
351+ return 0;
352+}
353+EXPORT_SYMBOL(ispccdc_free);
354+
355+/**
356+ * ispccdc_free_lsc - Frees Lens Shading Compensation table
357+ *
358+ * Always returns 0.
359+ **/
360+static int ispccdc_free_lsc(void)
361+{
362+ if (!lsc_ispmmu_addr)
363+ return 0;
364+
365+ ispccdc_enable_lsc(0);
366+ lsc_initialized = 0;
367+ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
368+ ispmmu_kunmap(lsc_ispmmu_addr);
369+ kfree(lsc_gain_table);
370+ return 0;
371+}
372+
373+/**
374+ * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table
375+ * @table_size: LSC gain table size.
376+ *
377+ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
378+ * table_size is zero.
379+ **/
380+static int ispccdc_allocate_lsc(u32 table_size)
381+{
382+ if (table_size == 0)
383+ return -EINVAL;
384+
385+ if ((lsc_config.size >= table_size) && lsc_gain_table)
386+ return 0;
387+
388+ ispccdc_free_lsc();
389+
390+ lsc_gain_table = kmalloc(table_size, GFP_KERNEL | GFP_DMA);
391+
392+ if (!lsc_gain_table) {
393+ printk(KERN_ERR "Cannot allocate memory for gain tables \n");
394+ return -ENOMEM;
395+ }
396+
397+ lsc_ispmmu_addr = ispmmu_kmap(virt_to_phys(lsc_gain_table), table_size);
398+ if (lsc_ispmmu_addr <= 0) {
399+ printk(KERN_ERR "Cannot map memory for gain tables \n");
400+ kfree(lsc_gain_table);
401+ return -ENOMEM;
402+ }
403+
404+ return 0;
405+}
406+
407+/**
408+ * ispccdc_program_lsc - Program Lens Shading Compensation table.
409+ * @table_size: LSC gain table size.
410+ *
411+ * Returns 0 if successful, or -EINVAL if there's no mapped address for the
412+ * table yet.
413+ **/
414+static int ispccdc_program_lsc(void)
415+{
416+ if (!lsc_ispmmu_addr)
417+ return -EINVAL;
418+
419+ if (lsc_initialized)
420+ return 0;
421+
422+ isp_reg_writel(lsc_ispmmu_addr, OMAP3_ISP_IOMEM_CCDC,
423+ ISPCCDC_LSC_TABLE_BASE);
424+ lsc_initialized = 1;
425+ return 0;
426+}
427+
428+/**
429+ * ispccdc_load_lsc - Load Lens Shading Compensation table.
430+ * @table_addr: LSC gain table MMU Mapped address.
431+ * @table_size: LSC gain table size.
432+ *
433+ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if
434+ * table_size is zero.
435+ **/
436+int ispccdc_load_lsc(u8 *table_addr, u32 table_size)
437+{
438+ int ret;
439+
440+ if (!is_isplsc_activated())
441+ return 0;
442+
443+ if (!table_addr)
444+ return -EINVAL;
445+
446+ ret = ispccdc_allocate_lsc(table_size);
447+ if (ret)
448+ return ret;
449+
450+ if (table_addr != lsc_gain_table)
451+ memcpy(lsc_gain_table, table_addr, table_size);
452+ ret = ispccdc_program_lsc();
453+ if (ret)
454+ return ret;
455+ return 0;
456+}
457+EXPORT_SYMBOL(ispccdc_load_lsc);
458+
459+/**
460+ * ispccdc_config_lsc - Configures the lens shading compensation module
461+ * @lsc_cfg: LSC configuration structure
462+ **/
463+void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg)
464+{
465+ int reg;
466+
467+ if (!is_isplsc_activated())
468+ return;
469+
470+ ispccdc_enable_lsc(0);
471+ isp_reg_writel(lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC,
472+ ISPCCDC_LSC_TABLE_OFFSET);
473+
474+ reg = 0;
475+ reg |= lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
476+ reg |= lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
477+ reg |= lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
478+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
479+
480+ reg = 0;
481+ reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
482+ reg |= lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
483+ reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
484+ reg |= lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
485+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL);
486+}
487+EXPORT_SYMBOL(ispccdc_config_lsc);
488+
489+int __ispccdc_enable_lsc(u8 enable)
490+{
491+ if (!is_isplsc_activated())
492+ return -ENODEV;
493+
494+ if (enable) {
495+ if (!ispccdc_busy()) {
496+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
497+ ISPCTRL_SBL_SHARED_RPORTB
498+ | ISPCTRL_SBL_RD_RAM_EN);
499+
500+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC,
501+ ISPCCDC_LSC_CONFIG, 0x1);
502+
503+ ispccdc_obj.lsc_state = 1;
504+ } else {
505+ /* Postpone enabling LSC */
506+ ispccdc_obj.lsc_enable = 1;
507+ return -EBUSY;
508+ }
509+ } else {
510+ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0xFFFE);
511+ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0;
512+ }
513+
514+ return 0;
515+}
516+
517+/**
518+ * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module.
519+ * @enable: 0 Disables LSC, 1 Enables LSC.
520+ **/
521+void ispccdc_enable_lsc(u8 enable)
522+{
523+ if (__ispccdc_enable_lsc(enable)) {
524+ if (enable)
525+ ispccdc_obj.lsc_state = 1;
526+ else
527+ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0;
528+ }
529+}
530+EXPORT_SYMBOL(ispccdc_enable_lsc);
531+
532+void ispccdc_lsc_error_handler(void)
533+{
534+ int lsc_enable = ispccdc_obj.lsc_state;
535+
536+ ispccdc_enable_lsc(0);
537+
538+ ispccdc_obj.lsc_enable = lsc_enable;
539+}
540+
541+/**
542+ * ispccdc_config_crop - Configures crop parameters for the ISP CCDC.
543+ * @left: Left offset of the crop area.
544+ * @top: Top offset of the crop area.
545+ * @height: Height of the crop area.
546+ * @width: Width of the crop area.
547+ *
548+ * The following restrictions are applied for the crop settings. If incoming
549+ * values do not follow these restrictions then we map the settings to the
550+ * closest acceptable crop value.
551+ * 1) Left offset is always odd. This can be avoided if we enable byte swap
552+ * option for incoming data into CCDC.
553+ * 2) Top offset is always even.
554+ * 3) Crop height is always even.
555+ * 4) Crop width is always a multiple of 16 pixels
556+ **/
557+void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width)
558+{
559+ ispccdc_obj.ccdcin_woffset = left + (left % 2);
560+ ispccdc_obj.ccdcin_hoffset = top + (top % 2);
561+
562+ ispccdc_obj.crop_w = width - (width % 16);
563+ ispccdc_obj.crop_h = height + (height % 2);
564+
565+ DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n",
566+ ispccdc_obj.ccdcin_woffset,
567+ ispccdc_obj.ccdcin_hoffset,
568+ ispccdc_obj.crop_w,
569+ ispccdc_obj.crop_h);
570+}
571+
572+/**
573+ * ispccdc_config_datapath - Specifies the input and output modules for CCDC.
574+ * @input: Indicates the module that inputs the image to the CCDC.
575+ * @output: Indicates the module to which the CCDC outputs the image.
576+ *
577+ * Configures the default configuration for the CCDC to work with.
578+ *
579+ * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1),
580+ * CCDC_YUV_BT (2), and CCDC_OTHERS (3).
581+ *
582+ * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1),
583+ * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4).
584+ *
585+ * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input
586+ * or output values.
587+ **/
588+int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output)
589+{
590+ u32 syn_mode = 0;
591+ struct ispccdc_vp vpcfg;
592+ struct ispccdc_syncif syncif;
593+ struct ispccdc_bclamp blkcfg;
594+
595+ u32 colptn = ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
596+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
597+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
598+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
599+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
600+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
601+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
602+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
603+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
604+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
605+ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
606+ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
607+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
608+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
609+ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
610+ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
611+
612+ /* CCDC does not convert the image format */
613+ if ((input == CCDC_RAW || input == CCDC_OTHERS) &&
614+ output == CCDC_YUV_RSZ) {
615+ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC I/O Combination\n");
616+ return -EINVAL;
617+ }
618+
619+ syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
620+
621+ switch (output) {
622+ case CCDC_YUV_RSZ:
623+ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
624+ syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
625+ break;
626+
627+ case CCDC_YUV_MEM_RSZ:
628+ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
629+ ispccdc_obj.wen = 1;
630+ syn_mode |= ISPCCDC_SYN_MODE_WEN;
631+ break;
632+
633+ case CCDC_OTHERS_VP:
634+ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
635+ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
636+ syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
637+ vpcfg.bitshift_sel = BIT9_0;
638+ vpcfg.freq_sel = PIXCLKBY2;
639+ ispccdc_config_vp(vpcfg);
640+ ispccdc_enable_vp(1);
641+ break;
642+
643+ case CCDC_OTHERS_MEM:
644+ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
645+ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
646+ syn_mode |= ISPCCDC_SYN_MODE_WEN;
647+ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
648+ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
649+ ~ISPCCDC_CFG_WENLOG);
650+ vpcfg.bitshift_sel = BIT11_2;
651+ vpcfg.freq_sel = PIXCLKBY2;
652+ ispccdc_config_vp(vpcfg);
653+ ispccdc_enable_vp(0);
654+ break;
655+
656+ case CCDC_OTHERS_VP_MEM:
657+ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
658+ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
659+ syn_mode |= ISPCCDC_SYN_MODE_WEN;
660+ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN;
661+
662+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
663+ ~ISPCCDC_CFG_WENLOG,
664+ ispccdc_obj.wenlog);
665+ vpcfg.bitshift_sel = BIT9_0;
666+ vpcfg.freq_sel = PIXCLKBY2;
667+ ispccdc_config_vp(vpcfg);
668+ ispccdc_enable_vp(1);
669+ break;
670+ default:
671+ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n");
672+ return -EINVAL;
673+ };
674+
675+ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
676+
677+ switch (input) {
678+ case CCDC_RAW:
679+ syncif.ccdc_mastermode = 0;
680+ syncif.datapol = 0;
681+ syncif.datsz = DAT10;
682+ syncif.fldmode = 0;
683+ syncif.fldout = 0;
684+ syncif.fldpol = 0;
685+ syncif.fldstat = 0;
686+ syncif.hdpol = 0;
687+ syncif.ipmod = RAW;
688+ syncif.vdpol = 0;
689+ ispccdc_config_sync_if(syncif);
690+ ispccdc_config_imgattr(colptn);
691+ blkcfg.dcsubval = 64;
692+ ispccdc_config_black_clamp(blkcfg);
693+ if (is_isplsc_activated()) {
694+ ispccdc_config_lsc(&lsc_config);
695+ ispccdc_load_lsc(lsc_gain_table_tmp,
696+ LSC_TABLE_INIT_SIZE);
697+ }
698+
699+ break;
700+ case CCDC_YUV_SYNC:
701+ syncif.ccdc_mastermode = 0;
702+ syncif.datapol = 0;
703+ syncif.datsz = DAT8;
704+ syncif.fldmode = 0;
705+ syncif.fldout = 0;
706+ syncif.fldpol = 0;
707+ syncif.fldstat = 0;
708+ syncif.hdpol = 0;
709+ syncif.ipmod = YUV16;
710+ syncif.vdpol = 1;
711+ ispccdc_config_imgattr(0);
712+ ispccdc_config_sync_if(syncif);
713+ blkcfg.dcsubval = 0;
714+ ispccdc_config_black_clamp(blkcfg);
715+ break;
716+ case CCDC_YUV_BT:
717+ break;
718+ case CCDC_OTHERS:
719+ break;
720+ default:
721+ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n");
722+ return -EINVAL;
723+ }
724+
725+ ispccdc_obj.ccdc_inpfmt = input;
726+ ispccdc_obj.ccdc_outfmt = output;
727+ ispccdc_print_status();
728+ isp_print_status();
729+ return 0;
730+}
731+EXPORT_SYMBOL(ispccdc_config_datapath);
732+
733+/**
734+ * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC.
735+ * @syncif: Structure containing the sync parameters like field state, CCDC in
736+ * master/slave mode, raw/yuv data, polarity of data, field, hs, vs
737+ * signals.
738+ **/
739+void ispccdc_config_sync_if(struct ispccdc_syncif syncif)
740+{
741+ u32 syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
742+
743+ syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
744+
745+ if (syncif.fldstat)
746+ syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
747+ else
748+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
749+
750+ syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK;
751+ ispccdc_obj.syncif_ipmod = syncif.ipmod;
752+
753+ switch (syncif.ipmod) {
754+ case RAW:
755+ break;
756+ case YUV16:
757+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
758+ break;
759+ case YUV8:
760+ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8;
761+ break;
762+ };
763+
764+ syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK;
765+ switch (syncif.datsz) {
766+ case DAT8:
767+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
768+ break;
769+ case DAT10:
770+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
771+ break;
772+ case DAT11:
773+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
774+ break;
775+ case DAT12:
776+ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
777+ break;
778+ };
779+
780+ if (syncif.fldmode)
781+ syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
782+ else
783+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
784+
785+ if (syncif.datapol)
786+ syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
787+ else
788+ syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
789+
790+ if (syncif.fldpol)
791+ syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
792+ else
793+ syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
794+
795+ if (syncif.hdpol)
796+ syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
797+ else
798+ syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
799+
800+ if (syncif.vdpol)
801+ syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
802+ else
803+ syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
804+
805+ if (syncif.ccdc_mastermode) {
806+ syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
807+ isp_reg_writel(syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
808+ | syncif.vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
809+ OMAP3_ISP_IOMEM_CCDC,
810+ ISPCCDC_HD_VD_WID);
811+
812+ isp_reg_writel(syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
813+ | syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
814+ OMAP3_ISP_IOMEM_CCDC,
815+ ISPCCDC_PIX_LINES);
816+ } else
817+ syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
818+ ISPCCDC_SYN_MODE_VDHDOUT);
819+
820+ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
821+
822+ if (!(syncif.bt_r656_en)) {
823+ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
824+ ~ISPCCDC_REC656IF_R656ON);
825+ }
826+}
827+EXPORT_SYMBOL(ispccdc_config_sync_if);
828+
829+/**
830+ * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC.
831+ * @bclamp: Structure containing the optical black average gain, optical black
832+ * sample length, sample lines, and the start pixel position of the
833+ * samples w.r.t the HS pulse.
834+ * Configures the clamp parameters in CCDC. Either if its being used the
835+ * optical black clamp, or the digital clamp. If its a digital clamp, then
836+ * assures to put a valid DC substraction level.
837+ *
838+ * Returns always 0 when completed.
839+ **/
840+int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp)
841+{
842+ u32 bclamp_val = 0;
843+
844+ if (ispccdc_obj.obclamp_en) {
845+ bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
846+ bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
847+ bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
848+ bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
849+ isp_reg_writel(bclamp_val, OMAP3_ISP_IOMEM_CCDC,
850+ ISPCCDC_CLAMP);
851+ } else {
852+ if (omap_rev() < OMAP3430_REV_ES2_0)
853+ if (ispccdc_obj.syncif_ipmod == YUV16 ||
854+ ispccdc_obj.syncif_ipmod == YUV8 ||
855+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
856+ ISPCCDC_REC656IF) &
857+ ISPCCDC_REC656IF_R656ON)
858+ bclamp.dcsubval = 0;
859+ isp_reg_writel(bclamp.dcsubval, OMAP3_ISP_IOMEM_CCDC,
860+ ISPCCDC_DCSUB);
861+ }
862+ return 0;
863+}
864+EXPORT_SYMBOL(ispccdc_config_black_clamp);
865+
866+/**
867+ * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp.
868+ * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp.
869+ *
870+ * Enables or disables the optical black clamp. When disabled, the digital
871+ * clamp operates.
872+ **/
873+void ispccdc_enable_black_clamp(u8 enable)
874+{
875+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
876+ ~ISPCCDC_CLAMP_CLAMPEN,
877+ enable ? ISPCCDC_CLAMP_CLAMPEN : 0);
878+ ispccdc_obj.obclamp_en = enable;
879+}
880+EXPORT_SYMBOL(ispccdc_enable_black_clamp);
881+
882+/**
883+ * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters.
884+ * @fpc: Structure containing the number of faulty pixels corrected in the
885+ * frame, address of the FPC table.
886+ *
887+ * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte
888+ * boundary.
889+ **/
890+int ispccdc_config_fpc(struct ispccdc_fpc fpc)
891+{
892+ u32 fpc_val = 0;
893+
894+ fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
895+
896+ if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) {
897+ isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN),
898+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
899+ isp_reg_writel(fpc.fpcaddr,
900+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR);
901+ } else {
902+ DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n");
903+ return -EINVAL;
904+ }
905+ isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
906+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
907+ return 0;
908+}
909+EXPORT_SYMBOL(ispccdc_config_fpc);
910+
911+/**
912+ * ispccdc_enable_fpc - Enables the Faulty Pixel Correction.
913+ * @enable: 0 Disables FPC, 1 Enables FPC.
914+ **/
915+void ispccdc_enable_fpc(u8 enable)
916+{
917+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC,
918+ ~ISPCCDC_FPC_FPCEN,
919+ enable ? ISPCCDC_FPC_FPCEN : 0);
920+}
921+EXPORT_SYMBOL(ispccdc_enable_fpc);
922+
923+/**
924+ * ispccdc_config_black_comp - Configures Black Level Compensation parameters.
925+ * @blcomp: Structure containing the black level compensation value for RGrGbB
926+ * pixels. in 2's complement.
927+ **/
928+void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp)
929+{
930+ u32 blcomp_val = 0;
931+
932+ blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
933+ blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
934+ blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
935+ blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
936+
937+ isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
938+}
939+EXPORT_SYMBOL(ispccdc_config_black_comp);
940+
941+/**
942+ * ispccdc_config_vp - Configures the Video Port Configuration parameters.
943+ * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit
944+ * format.
945+ **/
946+void ispccdc_config_vp(struct ispccdc_vp vpcfg)
947+{
948+ u32 fmtcfg_vp = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
949+
950+ fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCF_VPIF_FRQ_MASK;
951+
952+ switch (vpcfg.bitshift_sel) {
953+ case BIT9_0:
954+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
955+ break;
956+ case BIT10_1:
957+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
958+ break;
959+ case BIT11_2:
960+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
961+ break;
962+ case BIT12_3:
963+ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
964+ break;
965+ };
966+ switch (vpcfg.freq_sel) {
967+ case PIXCLKBY2:
968+ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY2;
969+ break;
970+ case PIXCLKBY3_5:
971+ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY3;
972+ break;
973+ case PIXCLKBY4_5:
974+ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY4;
975+ break;
976+ case PIXCLKBY5_5:
977+ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY5;
978+ break;
979+ case PIXCLKBY6_5:
980+ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY6;
981+ break;
982+ };
983+ isp_reg_writel(fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
984+}
985+EXPORT_SYMBOL(ispccdc_config_vp);
986+
987+/**
988+ * ispccdc_enable_vp - Enables the Video Port.
989+ * @enable: 0 Disables VP, 1 Enables VP
990+ **/
991+void ispccdc_enable_vp(u8 enable)
992+{
993+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
994+ ~ISPCCDC_FMTCFG_VPEN,
995+ enable ? ISPCCDC_FMTCFG_VPEN : 0);
996+}
997+EXPORT_SYMBOL(ispccdc_enable_vp);
998+
999+/**
1000+ * ispccdc_config_reformatter - Configures the Reformatter.
1001+ * @refmt: Structure containing the memory address to format and the bit fields
1002+ * for the reformatter registers.
1003+ *
1004+ * Configures the Reformatter register values if line alternating is disabled.
1005+ * Else, just enabling line alternating is enough.
1006+ **/
1007+void ispccdc_config_reformatter(struct ispccdc_refmt refmt)
1008+{
1009+ u32 fmtcfg_val = 0;
1010+
1011+ fmtcfg_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
1012+
1013+ if (refmt.lnalt)
1014+ fmtcfg_val |= ISPCCDC_FMTCFG_LNALT;
1015+ else {
1016+ fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT;
1017+ fmtcfg_val &= 0xFFFFF003;
1018+ fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT;
1019+ fmtcfg_val |= refmt.plen_even <<
1020+ ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT;
1021+ fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT;
1022+
1023+ isp_reg_writel(refmt.prgeven0, OMAP3_ISP_IOMEM_CCDC,
1024+ ISPCCDC_PRGEVEN0);
1025+ isp_reg_writel(refmt.prgeven1, OMAP3_ISP_IOMEM_CCDC,
1026+ ISPCCDC_PRGEVEN1);
1027+ isp_reg_writel(refmt.prgodd0, OMAP3_ISP_IOMEM_CCDC,
1028+ ISPCCDC_PRGODD0);
1029+ isp_reg_writel(refmt.prgodd1, OMAP3_ISP_IOMEM_CCDC,
1030+ ISPCCDC_PRGODD1);
1031+ isp_reg_writel(refmt.fmtaddr0, OMAP3_ISP_IOMEM_CCDC,
1032+ ISPCCDC_FMT_ADDR0);
1033+ isp_reg_writel(refmt.fmtaddr1, OMAP3_ISP_IOMEM_CCDC,
1034+ ISPCCDC_FMT_ADDR1);
1035+ isp_reg_writel(refmt.fmtaddr2, OMAP3_ISP_IOMEM_CCDC,
1036+ ISPCCDC_FMT_ADDR2);
1037+ isp_reg_writel(refmt.fmtaddr3, OMAP3_ISP_IOMEM_CCDC,
1038+ ISPCCDC_FMT_ADDR3);
1039+ isp_reg_writel(refmt.fmtaddr4, OMAP3_ISP_IOMEM_CCDC,
1040+ ISPCCDC_FMT_ADDR4);
1041+ isp_reg_writel(refmt.fmtaddr5, OMAP3_ISP_IOMEM_CCDC,
1042+ ISPCCDC_FMT_ADDR5);
1043+ isp_reg_writel(refmt.fmtaddr6, OMAP3_ISP_IOMEM_CCDC,
1044+ ISPCCDC_FMT_ADDR6);
1045+ isp_reg_writel(refmt.fmtaddr7, OMAP3_ISP_IOMEM_CCDC,
1046+ ISPCCDC_FMT_ADDR7);
1047+ }
1048+ isp_reg_writel(fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
1049+}
1050+EXPORT_SYMBOL(ispccdc_config_reformatter);
1051+
1052+/**
1053+ * ispccdc_enable_reformatter - Enables the Reformatter.
1054+ * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter
1055+ **/
1056+void ispccdc_enable_reformatter(u8 enable)
1057+{
1058+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
1059+ ~ISPCCDC_FMTCFG_FMTEN,
1060+ enable ? ISPCCDC_FMTCFG_FMTEN : 0);
1061+ ispccdc_obj.refmt_en = enable;
1062+}
1063+EXPORT_SYMBOL(ispccdc_enable_reformatter);
1064+
1065+/**
1066+ * ispccdc_config_culling - Configures the culling parameters.
1067+ * @cull: Structure containing the vertical culling pattern, and horizontal
1068+ * culling pattern for odd and even lines.
1069+ **/
1070+void ispccdc_config_culling(struct ispccdc_culling cull)
1071+{
1072+ u32 culling_val = 0;
1073+
1074+ culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT;
1075+ culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT;
1076+ culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT;
1077+
1078+ isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING);
1079+}
1080+EXPORT_SYMBOL(ispccdc_config_culling);
1081+
1082+/**
1083+ * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF).
1084+ * @enable: 0 Disables LPF, 1 Enables LPF
1085+ **/
1086+void ispccdc_enable_lpf(u8 enable)
1087+{
1088+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
1089+ ~ISPCCDC_SYN_MODE_LPF,
1090+ enable ? ISPCCDC_SYN_MODE_LPF : 0);
1091+}
1092+EXPORT_SYMBOL(ispccdc_enable_lpf);
1093+
1094+/**
1095+ * ispccdc_config_alaw - Configures the input width for A-law.
1096+ * @ipwidth: Input width for A-law
1097+ **/
1098+void ispccdc_config_alaw(enum alaw_ipwidth ipwidth)
1099+{
1100+ isp_reg_writel(ipwidth << ISPCCDC_ALAW_GWDI_SHIFT,
1101+ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
1102+}
1103+EXPORT_SYMBOL(ispccdc_config_alaw);
1104+
1105+/**
1106+ * ispccdc_enable_alaw - Enables the A-law compression.
1107+ * @enable: 0 - Disables A-law, 1 - Enables A-law
1108+ **/
1109+void ispccdc_enable_alaw(u8 enable)
1110+{
1111+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW,
1112+ ~ISPCCDC_ALAW_CCDTBL,
1113+ enable ? ISPCCDC_ALAW_CCDTBL : 0);
1114+}
1115+EXPORT_SYMBOL(ispccdc_enable_alaw);
1116+
1117+/**
1118+ * ispccdc_config_imgattr - Configures the sensor image specific attributes.
1119+ * @colptn: Color pattern of the sensor.
1120+ **/
1121+void ispccdc_config_imgattr(u32 colptn)
1122+{
1123+ isp_reg_writel(colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
1124+}
1125+EXPORT_SYMBOL(ispccdc_config_imgattr);
1126+
1127+void ispccdc_config_shadow_registers(void)
1128+{
1129+ if (ispccdc_obj.lsc_enable) {
1130+ ispccdc_enable_lsc(1);
1131+ ispccdc_obj.lsc_enable = 0;
1132+ }
1133+}
1134+
1135+/**
1136+ * ispccdc_try_size - Checks if requested Input/output dimensions are valid
1137+ * @input_w: input width for the CCDC in number of pixels per line
1138+ * @input_h: input height for the CCDC in number of lines
1139+ * @output_w: output width from the CCDC in number of pixels per line
1140+ * @output_h: output height for the CCDC in number of lines
1141+ *
1142+ * Calculates the number of pixels cropped if the reformater is disabled,
1143+ * Fills up the output width and height variables in the isp_ccdc structure.
1144+ *
1145+ * Returns 0 if successful, or -EINVAL if the input width is less than 2 pixels
1146+ **/
1147+int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
1148+{
1149+ if (input_w < 32 || input_h < 32) {
1150+ DPRINTK_ISPCCDC("ISP_ERR: CCDC cannot handle input width less"
1151+ " than 32 pixels or height less than 32\n");
1152+ return -EINVAL;
1153+ }
1154+
1155+ if (ispccdc_obj.crop_w)
1156+ *output_w = ispccdc_obj.crop_w;
1157+ else
1158+ *output_w = input_w;
1159+
1160+ if (ispccdc_obj.crop_h)
1161+ *output_h = ispccdc_obj.crop_h;
1162+ else
1163+ *output_h = input_h;
1164+
1165+ if (!ispccdc_obj.refmt_en
1166+ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_MEM
1167+ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_VP_MEM)
1168+ *output_h -= 1;
1169+
1170+ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM
1171+ || ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
1172+ if (*output_w % 16) {
1173+ *output_w -= (*output_w % 16);
1174+ *output_w += 16;
1175+ }
1176+ }
1177+
1178+ ispccdc_obj.ccdcout_w = *output_w;
1179+ ispccdc_obj.ccdcout_h = *output_h;
1180+ ispccdc_obj.ccdcin_w = input_w;
1181+ ispccdc_obj.ccdcin_h = input_h;
1182+
1183+ DPRINTK_ISPCCDC("try size: ccdcin_w=%u,ccdcin_h=%u,ccdcout_w=%u,"
1184+ " ccdcout_h=%u\n",
1185+ ispccdc_obj.ccdcin_w,
1186+ ispccdc_obj.ccdcin_h,
1187+ ispccdc_obj.ccdcout_w,
1188+ ispccdc_obj.ccdcout_h);
1189+
1190+ return 0;
1191+}
1192+EXPORT_SYMBOL(ispccdc_try_size);
1193+
1194+/**
1195+ * ispccdc_config_size - Configure the dimensions of the CCDC input/output
1196+ * @input_w: input width for the CCDC in number of pixels per line
1197+ * @input_h: input height for the CCDC in number of lines
1198+ * @output_w: output width from the CCDC in number of pixels per line
1199+ * @output_h: output height for the CCDC in number of lines
1200+ *
1201+ * Configures the appropriate values stored in the isp_ccdc structure to
1202+ * HORZ/VERT_INFO registers and the VP_OUT depending on whether the image
1203+ * is stored in memory or given to the another module in the ISP pipeline.
1204+ *
1205+ * Returns 0 if successful, or -EINVAL if try_size was not called before to
1206+ * validate the requested dimensions.
1207+ **/
1208+int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
1209+{
1210+ DPRINTK_ISPCCDC("config size: input_w=%u, input_h=%u, output_w=%u,"
1211+ " output_h=%u\n",
1212+ input_w, input_h,
1213+ output_w, output_h);
1214+ if (output_w != ispccdc_obj.ccdcout_w
1215+ || output_h != ispccdc_obj.ccdcout_h) {
1216+ DPRINTK_ISPCCDC("ISP_ERR : ispccdc_try_size should"
1217+ " be called before config size\n");
1218+ return -EINVAL;
1219+ }
1220+
1221+ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP) {
1222+ isp_reg_writel((ispccdc_obj.ccdcin_woffset <<
1223+ ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
1224+ (ispccdc_obj.ccdcin_w <<
1225+ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
1226+ OMAP3_ISP_IOMEM_CCDC,
1227+ ISPCCDC_FMT_HORZ);
1228+ isp_reg_writel((ispccdc_obj.ccdcin_hoffset <<
1229+ ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
1230+ (ispccdc_obj.ccdcin_h <<
1231+ ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
1232+ OMAP3_ISP_IOMEM_CCDC,
1233+ ISPCCDC_FMT_VERT);
1234+ isp_reg_writel((ispccdc_obj.ccdcout_w <<
1235+ ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
1236+ (ispccdc_obj.ccdcout_h - 1) <<
1237+ ISPCCDC_VP_OUT_VERT_NUM_SHIFT,
1238+ OMAP3_ISP_IOMEM_CCDC,
1239+ ISPCCDC_VP_OUT);
1240+ isp_reg_writel((((ispccdc_obj.ccdcout_h - 25) &
1241+ ISPCCDC_VDINT_0_MASK) <<
1242+ ISPCCDC_VDINT_0_SHIFT) |
1243+ ((50 & ISPCCDC_VDINT_1_MASK) <<
1244+ ISPCCDC_VDINT_1_SHIFT),
1245+ OMAP3_ISP_IOMEM_CCDC,
1246+ ISPCCDC_VDINT);
1247+
1248+ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) {
1249+ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
1250+ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
1251+ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
1252+ | ((ispccdc_obj.ccdcout_w - 1)
1253+ << ISPCCDC_HORZ_INFO_NPH_SHIFT),
1254+ OMAP3_ISP_IOMEM_CCDC,
1255+ ISPCCDC_HORZ_INFO);
1256+ } else {
1257+ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT
1258+ | ((ispccdc_obj.ccdcout_w - 1)
1259+ << ISPCCDC_HORZ_INFO_NPH_SHIFT),
1260+ OMAP3_ISP_IOMEM_CCDC,
1261+ ISPCCDC_HORZ_INFO);
1262+ }
1263+ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
1264+ OMAP3_ISP_IOMEM_CCDC,
1265+ ISPCCDC_VERT_START);
1266+ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
1267+ ISPCCDC_VERT_LINES_NLV_SHIFT,
1268+ OMAP3_ISP_IOMEM_CCDC,
1269+ ISPCCDC_VERT_LINES);
1270+
1271+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
1272+ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
1273+ ISPCCDC_VDINT_0_MASK) <<
1274+ ISPCCDC_VDINT_0_SHIFT) |
1275+ ((100 & ISPCCDC_VDINT_1_MASK) <<
1276+ ISPCCDC_VDINT_1_SHIFT),
1277+ OMAP3_ISP_IOMEM_CCDC,
1278+ ISPCCDC_VDINT);
1279+ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) {
1280+ isp_reg_writel((0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
1281+ (ispccdc_obj.ccdcin_w <<
1282+ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
1283+ OMAP3_ISP_IOMEM_CCDC,
1284+ ISPCCDC_FMT_HORZ);
1285+ isp_reg_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
1286+ ((ispccdc_obj.ccdcin_h) <<
1287+ ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
1288+ OMAP3_ISP_IOMEM_CCDC,
1289+ ISPCCDC_FMT_VERT);
1290+ isp_reg_writel((ispccdc_obj.ccdcout_w
1291+ << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
1292+ ((ispccdc_obj.ccdcout_h - 1) <<
1293+ ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
1294+ OMAP3_ISP_IOMEM_CCDC,
1295+ ISPCCDC_VP_OUT);
1296+ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT |
1297+ ((ispccdc_obj.ccdcout_w - 1) <<
1298+ ISPCCDC_HORZ_INFO_NPH_SHIFT),
1299+ OMAP3_ISP_IOMEM_CCDC,
1300+ ISPCCDC_HORZ_INFO);
1301+ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT,
1302+ OMAP3_ISP_IOMEM_CCDC,
1303+ ISPCCDC_VERT_START);
1304+ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) <<
1305+ ISPCCDC_VERT_LINES_NLV_SHIFT,
1306+ OMAP3_ISP_IOMEM_CCDC,
1307+ ISPCCDC_VERT_LINES);
1308+ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0);
1309+ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) &
1310+ ISPCCDC_VDINT_0_MASK) <<
1311+ ISPCCDC_VDINT_0_SHIFT) |
1312+ ((100 & ISPCCDC_VDINT_1_MASK) <<
1313+ ISPCCDC_VDINT_1_SHIFT),
1314+ OMAP3_ISP_IOMEM_CCDC,
1315+ ISPCCDC_VDINT);
1316+ }
1317+
1318+ if (is_isplsc_activated()) {
1319+ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) {
1320+ ispccdc_config_lsc(&lsc_config);
1321+ ispccdc_load_lsc(lsc_gain_table, lsc_config.size);
1322+ }
1323+ }
1324+
1325+ return 0;
1326+}
1327+EXPORT_SYMBOL(ispccdc_config_size);
1328+
1329+/**
1330+ * ispccdc_config_outlineoffset - Configures the output line offset
1331+ * @offset: Must be twice the Output width and aligned on 32 byte boundary
1332+ * @oddeven: Specifies the odd/even line pattern to be chosen to store the
1333+ * output.
1334+ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
1335+ *
1336+ * - Configures the output line offset when stored in memory
1337+ * - Sets the odd/even line pattern to store the output
1338+ * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
1339+ * - Configures the number of even and odd line fields in case of rearranging
1340+ * the lines.
1341+ *
1342+ * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte
1343+ * boundary.
1344+ **/
1345+int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines)
1346+{
1347+ if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
1348+ isp_reg_writel((offset & 0xFFFF), OMAP3_ISP_IOMEM_CCDC,
1349+ ISPCCDC_HSIZE_OFF);
1350+ } else {
1351+ DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte"
1352+ " boundary\n");
1353+ return -EINVAL;
1354+ }
1355+
1356+ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1357+ ~ISPCCDC_SDOFST_FINV);
1358+
1359+ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1360+ ~ISPCCDC_SDOFST_FOFST_4L);
1361+
1362+ switch (oddeven) {
1363+ case EVENEVEN:
1364+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1365+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
1366+ break;
1367+ case ODDEVEN:
1368+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1369+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
1370+ break;
1371+ case EVENODD:
1372+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1373+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
1374+ break;
1375+ case ODDODD:
1376+ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
1377+ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
1378+ break;
1379+ default:
1380+ break;
1381+ }
1382+ return 0;
1383+}
1384+EXPORT_SYMBOL(ispccdc_config_outlineoffset);
1385+
1386+/**
1387+ * ispccdc_set_outaddr - Sets the memory address where the output will be saved
1388+ * @addr: 32-bit memory address aligned on 32 byte boundary.
1389+ *
1390+ * Sets the memory address where the output will be saved.
1391+ *
1392+ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
1393+ * boundary.
1394+ **/
1395+int ispccdc_set_outaddr(u32 addr)
1396+{
1397+ if ((addr & ISP_32B_BOUNDARY_BUF) == addr) {
1398+ isp_reg_writel(addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
1399+ return 0;
1400+ } else {
1401+ DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte"
1402+ " boundary\n");
1403+ return -EINVAL;
1404+ }
1405+
1406+}
1407+EXPORT_SYMBOL(ispccdc_set_outaddr);
1408+
1409+void __ispccdc_enable(u8 enable)
1410+{
1411+ if (enable) {
1412+ if (ispccdc_obj.lsc_enable
1413+ && ispccdc_obj.ccdc_inpfmt == CCDC_RAW)
1414+ ispccdc_enable_lsc(1);
1415+
1416+ } else {
1417+ ispccdc_obj.lsc_enable = ispccdc_obj.lsc_state;
1418+ }
1419+
1420+ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR, ~ISPCCDC_PCR_EN,
1421+ enable ? ISPCCDC_PCR_EN : 0);
1422+}
1423+
1424+/**
1425+ * ispccdc_enable - Enables the CCDC module.
1426+ * @enable: 0 Disables CCDC, 1 Enables CCDC
1427+ *
1428+ * Client should configure all the sub modules in CCDC before this.
1429+ **/
1430+void ispccdc_enable(u8 enable)
1431+{
1432+ __ispccdc_enable(enable);
1433+ ispccdc_obj.pm_state = enable;
1434+}
1435+EXPORT_SYMBOL(ispccdc_enable);
1436+
1437+/**
1438+ * ispccdc_suspend - Suspend the CCDC module.
1439+ **/
1440+void ispccdc_suspend(void)
1441+{
1442+ if (ispccdc_obj.pm_state) {
1443+ if (ispccdc_obj.lsc_state)
1444+ __ispccdc_enable_lsc(0);
1445+ else if (ispccdc_obj.lsc_enable) {
1446+ ispccdc_obj.lsc_state = 1;
1447+ ispccdc_obj.lsc_enable = 0;
1448+ }
1449+ __ispccdc_enable(0);
1450+ }
1451+}
1452+EXPORT_SYMBOL(ispccdc_suspend);
1453+
1454+/**
1455+ * ispccdc_resume - Resume the CCDC module.
1456+ **/
1457+void ispccdc_resume(void)
1458+{
1459+ if (ispccdc_obj.pm_state) {
1460+ if (ispccdc_obj.lsc_state)
1461+ __ispccdc_enable_lsc(1);
1462+ __ispccdc_enable(1);
1463+ }
1464+}
1465+EXPORT_SYMBOL(ispccdc_resume);
1466+
1467+/*
1468+ * Returns zero if the CCDC is idle and the image has been written to
1469+ * memory, too.
1470+ */
1471+int ispccdc_sbl_busy(void)
1472+{
1473+ return ispccdc_busy()
1474+ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
1475+ ISPSBL_CCDC_WR_0_DATA_READY)
1476+ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
1477+ ISPSBL_CCDC_WR_0_DATA_READY)
1478+ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
1479+ ISPSBL_CCDC_WR_0_DATA_READY)
1480+ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
1481+ ISPSBL_CCDC_WR_0_DATA_READY);
1482+}
1483+EXPORT_SYMBOL(ispccdc_sbl_busy);
1484+
1485+/**
1486+ * ispccdc_busy - Gets busy state of the CCDC.
1487+ **/
1488+int ispccdc_busy(void)
1489+{
1490+ return isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
1491+ ISPCCDC_PCR_BUSY;
1492+}
1493+EXPORT_SYMBOL(ispccdc_busy);
1494+
1495+/**
1496+ * ispccdc_save_context - Saves the values of the CCDC module registers
1497+ **/
1498+void ispccdc_save_context(void)
1499+{
1500+ DPRINTK_ISPCCDC("Saving context\n");
1501+ isp_save_context(ispccdc_reg_list);
1502+}
1503+EXPORT_SYMBOL(ispccdc_save_context);
1504+
1505+/**
1506+ * ispccdc_restore_context - Restores the values of the CCDC module registers
1507+ **/
1508+void ispccdc_restore_context(void)
1509+{
1510+ DPRINTK_ISPCCDC("Restoring context\n");
1511+ isp_restore_context(ispccdc_reg_list);
1512+}
1513+EXPORT_SYMBOL(ispccdc_restore_context);
1514+
1515+/**
1516+ * ispccdc_print_status - Prints the values of the CCDC Module registers
1517+ *
1518+ * Also prints other debug information stored in the CCDC module.
1519+ **/
1520+void ispccdc_print_status(void)
1521+{
1522+ if (!is_ispccdc_debug_enabled())
1523+ return;
1524+
1525+ DPRINTK_ISPCCDC("Module in use =%d\n", ispccdc_obj.ccdc_inuse);
1526+ DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n",
1527+ ispccdc_obj.ccdcin_w,
1528+ ispccdc_obj.ccdcin_h);
1529+ DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n",
1530+ ispccdc_obj.ccdcout_w,
1531+ ispccdc_obj.ccdcout_h);
1532+ DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n",
1533+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR));
1534+ DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n",
1535+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
1536+ switch (ispccdc_obj.ccdc_inpfmt) {
1537+ case CCDC_RAW:
1538+ DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n");
1539+ break;
1540+ case CCDC_YUV_SYNC:
1541+ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n");
1542+ break;
1543+ case CCDC_YUV_BT:
1544+ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n");
1545+ break;
1546+ }
1547+
1548+ switch (ispccdc_obj.ccdc_outfmt) {
1549+ case CCDC_OTHERS_VP:
1550+ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n");
1551+ break;
1552+ case CCDC_OTHERS_MEM:
1553+ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n");
1554+ break;
1555+ case CCDC_YUV_RSZ:
1556+ DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n");
1557+ break;
1558+ }
1559+
1560+ DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n",
1561+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
1562+ DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n",
1563+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
1564+ DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n",
1565+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
1566+ DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n",
1567+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
1568+ DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n",
1569+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
1570+ DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n",
1571+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1572+ ISPCCDC_VERT_START));
1573+ DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n",
1574+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1575+ ISPCCDC_VERT_LINES));
1576+ DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n",
1577+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING));
1578+ DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n",
1579+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
1580+ DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n",
1581+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST));
1582+ DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n",
1583+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
1584+ DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n",
1585+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP));
1586+ DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n",
1587+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN));
1588+ DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n",
1589+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
1590+ DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n",
1591+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT));
1592+ DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n",
1593+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
1594+ DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n",
1595+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
1596+ DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n",
1597+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ));
1598+ DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n",
1599+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT));
1600+ DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n",
1601+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1602+ ISPCCDC_LSC_CONFIG));
1603+ DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n",
1604+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1605+ ISPCCDC_LSC_INITIAL));
1606+ DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n",
1607+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1608+ ISPCCDC_LSC_TABLE_BASE));
1609+ DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n",
1610+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
1611+ ISPCCDC_LSC_TABLE_OFFSET));
1612+}
1613+EXPORT_SYMBOL(ispccdc_print_status);
1614+
1615+/**
1616+ * isp_ccdc_init - CCDC module initialization.
1617+ *
1618+ * Always returns 0
1619+ **/
1620+int __init isp_ccdc_init(void)
1621+{
1622+ ispccdc_obj.ccdc_inuse = 0;
1623+ ispccdc_config_crop(0, 0, 0, 0);
1624+ mutex_init(&ispccdc_obj.mutexlock);
1625+
1626+ if (is_isplsc_activated()) {
1627+ lsc_gain_table_tmp = kmalloc(LSC_TABLE_INIT_SIZE, GFP_KERNEL |
1628+ GFP_DMA);
1629+ memset(lsc_gain_table_tmp, 0x40, LSC_TABLE_INIT_SIZE);
1630+ lsc_config.initial_x = 0;
1631+ lsc_config.initial_y = 0;
1632+ lsc_config.gain_mode_n = 0x6;
1633+ lsc_config.gain_mode_m = 0x6;
1634+ lsc_config.gain_format = 0x4;
1635+ lsc_config.offset = 0x60;
1636+ lsc_config.size = LSC_TABLE_INIT_SIZE;
1637+ ispccdc_obj.lsc_enable = 1;
1638+ }
1639+
1640+ return 0;
1641+}
1642+
1643+/**
1644+ * isp_ccdc_cleanup - CCDC module cleanup.
1645+ **/
1646+void isp_ccdc_cleanup(void)
1647+{
1648+ if (is_isplsc_activated()) {
1649+ ispccdc_free_lsc();
1650+ kfree(lsc_gain_table_tmp);
1651+ }
1652+
1653+ if (fpc_table_add_m != 0) {
1654+ ispmmu_kunmap(fpc_table_add_m);
1655+ kfree(fpc_table_add);
1656+ }
1657+}
1658diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h
1659new file mode 100644
1660index 0000000..4ef40a6
1661--- /dev/null
1662+++ b/drivers/media/video/isp/ispccdc.h
1663@@ -0,0 +1,209 @@
1664+/*
1665+ * ispccdc.h
1666+ *
1667+ * Driver header file for CCDC module in TI's OMAP3 Camera ISP
1668+ *
1669+ * Copyright (C) 2009 Texas Instruments, Inc.
1670+ *
1671+ * Contributors:
1672+ * Senthilvadivu Guruswamy <svadivu@ti.com>
1673+ * Pallavi Kulkarni <p-kulkarni@ti.com>
1674+ * Sergio Aguirre <saaguirre@ti.com>
1675+ *
1676+ * This package is free software; you can redistribute it and/or modify
1677+ * it under the terms of the GNU General Public License version 2 as
1678+ * published by the Free Software Foundation.
1679+ *
1680+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1681+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1682+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1683+ */
1684+
1685+#ifndef OMAP_ISP_CCDC_H
1686+#define OMAP_ISP_CCDC_H
1687+
1688+#include <mach/isp_user.h>
1689+
1690+#define is_isplsc_activated() 1
1691+
1692+/* Enumeration constants for CCDC input output format */
1693+enum ccdc_input {
1694+ CCDC_RAW,
1695+ CCDC_YUV_SYNC,
1696+ CCDC_YUV_BT,
1697+ CCDC_OTHERS
1698+};
1699+
1700+enum ccdc_output {
1701+ CCDC_YUV_RSZ,
1702+ CCDC_YUV_MEM_RSZ,
1703+ CCDC_OTHERS_VP,
1704+ CCDC_OTHERS_MEM,
1705+ CCDC_OTHERS_VP_MEM
1706+};
1707+
1708+/* Enumeration constants for the sync interface parameters */
1709+enum inpmode {
1710+ RAW,
1711+ YUV16,
1712+ YUV8
1713+};
1714+enum datasize {
1715+ DAT8,
1716+ DAT10,
1717+ DAT11,
1718+ DAT12
1719+};
1720+
1721+
1722+/**
1723+ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
1724+ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
1725+ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
1726+ * @ipmod: Input mode.
1727+ * @datsz: Data size.
1728+ * @fldmode: 0 - Progressive, 1 - Interlaced.
1729+ * @datapol: 0 - Positive, 1 - Negative.
1730+ * @fldpol: 0 - Positive, 1 - Negative.
1731+ * @hdpol: 0 - Positive, 1 - Negative.
1732+ * @vdpol: 0 - Positive, 1 - Negative.
1733+ * @fldout: 0 - Input, 1 - Output.
1734+ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
1735+ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
1736+ * @ppln: Number of pixels per line, used for HS/VS Output.
1737+ * @hlprf: Number of half lines per frame, used for HS/VS Output.
1738+ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
1739+ */
1740+struct ispccdc_syncif {
1741+ u8 ccdc_mastermode;
1742+ u8 fldstat;
1743+ enum inpmode ipmod;
1744+ enum datasize datsz;
1745+ u8 fldmode;
1746+ u8 datapol;
1747+ u8 fldpol;
1748+ u8 hdpol;
1749+ u8 vdpol;
1750+ u8 fldout;
1751+ u8 hs_width;
1752+ u8 vs_width;
1753+ u8 ppln;
1754+ u8 hlprf;
1755+ u8 bt_r656_en;
1756+};
1757+
1758+/**
1759+ * ispccdc_refmt - Structure for Reformatter parameters
1760+ * @lnalt: Line alternating mode enable. 0 - Enable, 1 - Disable.
1761+ * @lnum: Number of output lines from 1 input line. 1 to 4 lines.
1762+ * @plen_even: Number of program entries in even line minus 1.
1763+ * @plen_odd: Number of program entries in odd line minus 1.
1764+ * @prgeven0: Program entries 0-7 for even lines register
1765+ * @prgeven1: Program entries 8-15 for even lines register
1766+ * @prgodd0: Program entries 0-7 for odd lines register
1767+ * @prgodd1: Program entries 8-15 for odd lines register
1768+ * @fmtaddr0: Output line in which the original pixel is to be placed
1769+ * @fmtaddr1: Output line in which the original pixel is to be placed
1770+ * @fmtaddr2: Output line in which the original pixel is to be placed
1771+ * @fmtaddr3: Output line in which the original pixel is to be placed
1772+ * @fmtaddr4: Output line in which the original pixel is to be placed
1773+ * @fmtaddr5: Output line in which the original pixel is to be placed
1774+ * @fmtaddr6: Output line in which the original pixel is to be placed
1775+ * @fmtaddr7: Output line in which the original pixel is to be placed
1776+ */
1777+struct ispccdc_refmt {
1778+ u8 lnalt;
1779+ u8 lnum;
1780+ u8 plen_even;
1781+ u8 plen_odd;
1782+ u32 prgeven0;
1783+ u32 prgeven1;
1784+ u32 prgodd0;
1785+ u32 prgodd1;
1786+ u32 fmtaddr0;
1787+ u32 fmtaddr1;
1788+ u32 fmtaddr2;
1789+ u32 fmtaddr3;
1790+ u32 fmtaddr4;
1791+ u32 fmtaddr5;
1792+ u32 fmtaddr6;
1793+ u32 fmtaddr7;
1794+};
1795+
1796+int ispccdc_request(void);
1797+
1798+int ispccdc_free(void);
1799+
1800+int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output);
1801+
1802+void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width);
1803+
1804+void ispccdc_config_sync_if(struct ispccdc_syncif syncif);
1805+
1806+int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp);
1807+
1808+void ispccdc_enable_black_clamp(u8 enable);
1809+
1810+int ispccdc_config_fpc(struct ispccdc_fpc fpc);
1811+
1812+void ispccdc_enable_fpc(u8 enable);
1813+
1814+void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp);
1815+
1816+void ispccdc_config_vp(struct ispccdc_vp vp);
1817+
1818+void ispccdc_enable_vp(u8 enable);
1819+
1820+void ispccdc_config_reformatter(struct ispccdc_refmt refmt);
1821+
1822+void ispccdc_enable_reformatter(u8 enable);
1823+
1824+void ispccdc_config_culling(struct ispccdc_culling culling);
1825+
1826+void ispccdc_enable_lpf(u8 enable);
1827+
1828+void ispccdc_config_alaw(enum alaw_ipwidth ipwidth);
1829+
1830+void ispccdc_enable_alaw(u8 enable);
1831+
1832+int ispccdc_load_lsc(u8 *table_addr, u32 table_size);
1833+
1834+void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg);
1835+
1836+void ispccdc_enable_lsc(u8 enable);
1837+
1838+void ispccdc_lsc_error_handler(void);
1839+
1840+void ispccdc_config_imgattr(u32 colptn);
1841+
1842+void ispccdc_config_shadow_registers(void);
1843+
1844+int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h);
1845+
1846+int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h);
1847+
1848+int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines);
1849+
1850+int ispccdc_set_outaddr(u32 addr);
1851+
1852+void ispccdc_enable(u8 enable);
1853+
1854+void ispccdc_suspend(void);
1855+
1856+void ispccdc_resume(void);
1857+
1858+int ispccdc_sbl_busy(void);
1859+
1860+int ispccdc_busy(void);
1861+
1862+void ispccdc_save_context(void);
1863+
1864+void ispccdc_restore_context(void);
1865+
1866+void ispccdc_print_status(void);
1867+
1868+int omap34xx_isp_ccdc_config(void *userspace_add);
1869+
1870+void ispccdc_set_wenlog(u32 wenlog);
1871+
1872+#endif /* OMAP_ISP_CCDC_H */
1873--
18741.5.6.5
1875
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch
new file mode 100644
index 0000000000..c549eadc88
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0005-omap3isp-Add-ISP-backend-PRV-and-RSZ.patch
@@ -0,0 +1,3413 @@
1From 926b51afea146826c8076e5fb305eaa0332399b4 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add ISP backend (PRV and RSZ)
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 drivers/media/video/isp/isppreview.c | 1929 ++++++++++++++++++++++++++++++++++
9 drivers/media/video/isp/isppreview.h | 354 +++++++
10 drivers/media/video/isp/ispresizer.c | 928 ++++++++++++++++
11 drivers/media/video/isp/ispresizer.h | 158 +++
12 4 files changed, 3369 insertions(+), 0 deletions(-)
13 create mode 100644 drivers/media/video/isp/isppreview.c
14 create mode 100644 drivers/media/video/isp/isppreview.h
15 create mode 100644 drivers/media/video/isp/ispresizer.c
16 create mode 100644 drivers/media/video/isp/ispresizer.h
17
18diff --git a/drivers/media/video/isp/isppreview.c b/drivers/media/video/isp/isppreview.c
19new file mode 100644
20index 0000000..17f1abc
21--- /dev/null
22+++ b/drivers/media/video/isp/isppreview.c
23@@ -0,0 +1,1929 @@
24+/*
25+ * isppreview.c
26+ *
27+ * Driver Library for Preview module in TI's OMAP3 Camera ISP
28+ *
29+ * Copyright (C) 2009 Texas Instruments, Inc.
30+ *
31+ * Contributors:
32+ * Senthilvadivu Guruswamy <svadivu@ti.com>
33+ * Pallavi Kulkarni <p-kulkarni@ti.com>
34+ * Sergio Aguirre <saaguirre@ti.com>
35+ *
36+ * This package is free software; you can redistribute it and/or modify
37+ * it under the terms of the GNU General Public License version 2 as
38+ * published by the Free Software Foundation.
39+ *
40+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
41+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
42+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43+ */
44+
45+#include <linux/mutex.h>
46+#include <linux/module.h>
47+#include <linux/uaccess.h>
48+
49+#include "isp.h"
50+#include "ispreg.h"
51+#include "isppreview.h"
52+
53+static struct ispprev_nf prev_nf_t;
54+static struct prev_params *params;
55+static int rg_update, gg_update, bg_update, nf_enable, nf_update;
56+
57+/* Structure for saving/restoring preview module registers */
58+static struct isp_reg ispprev_reg_list[] = {
59+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO, 0x0000},
60+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO, 0x0000},
61+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR, 0x0000},
62+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET, 0x0000},
63+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR, 0x0000},
64+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_DRKF_OFFSET, 0x0000},
65+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR, 0x0000},
66+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET, 0x0000},
67+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE, 0x0000},
68+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED, 0x0000},
69+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_NF, 0x0000},
70+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN, 0x0000},
71+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN, 0x0000},
72+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL, 0x0000},
73+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA, 0x0000},
74+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF, 0x0000},
75+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1, 0x0000},
76+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2, 0x0000},
77+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3, 0x0000},
78+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4, 0x0000},
79+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5, 0x0000},
80+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1, 0x0000},
81+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2, 0x0000},
82+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0, 0x0000},
83+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1, 0x0000},
84+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2, 0x0000},
85+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET, 0x0000},
86+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 0x0000},
87+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP, 0x0000},
88+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC, 0x0000},
89+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0, 0x0000},
90+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1, 0x0000},
91+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2, 0x0000},
92+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3, 0x0000},
93+ {OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 0x0000},
94+ {0, ISP_TOK_TERM, 0x0000}
95+};
96+
97+
98+/* Default values in Office Flourescent Light for RGBtoRGB Blending */
99+static struct ispprev_rgbtorgb flr_rgb2rgb = {
100+ { /* RGB-RGB Matrix */
101+ {0x01E2, 0x0F30, 0x0FEE},
102+ {0x0F9B, 0x01AC, 0x0FB9},
103+ {0x0FE0, 0x0EC0, 0x0260}
104+ }, /* RGB Offset */
105+ {0x0000, 0x0000, 0x0000}
106+};
107+
108+/* Default values in Office Flourescent Light for RGB to YUV Conversion*/
109+static struct ispprev_csc flr_prev_csc[] = {
110+ {
111+ { /* CSC Coef Matrix */
112+ {66, 129, 25},
113+ {-38, -75, 112},
114+ {112, -94 , -18}
115+ }, /* CSC Offset */
116+ {0x0, 0x0, 0x0}
117+ },
118+ {
119+ { /* CSC Coef Matrix BW */
120+ {66, 129, 25},
121+ {0, 0, 0},
122+ {0, 0, 0}
123+ }, /* CSC Offset */
124+ {0x0, 0x0, 0x0}
125+ },
126+ {
127+ { /* CSC Coef Matrix Sepia */
128+ {19, 38, 7},
129+ {0, 0, 0},
130+ {0, 0, 0}
131+ }, /* CSC Offset */
132+ {0x0, 0xE7, 0x14}
133+ }
134+};
135+
136+
137+/* Default values in Office Flourescent Light for CFA Gradient*/
138+#define FLR_CFA_GRADTHRS_HORZ 0x28
139+#define FLR_CFA_GRADTHRS_VERT 0x28
140+
141+/* Default values in Office Flourescent Light for Chroma Suppression*/
142+#define FLR_CSUP_GAIN 0x0D
143+#define FLR_CSUP_THRES 0xEB
144+
145+/* Default values in Office Flourescent Light for Noise Filter*/
146+#define FLR_NF_STRGTH 0x03
147+
148+/* Default values in Office Flourescent Light for White Balance*/
149+#define FLR_WBAL_DGAIN 0x100
150+#define FLR_WBAL_COEF0 0x20
151+#define FLR_WBAL_COEF1 0x29
152+#define FLR_WBAL_COEF2 0x2d
153+#define FLR_WBAL_COEF3 0x20
154+
155+#define FLR_WBAL_COEF0_ES1 0x20
156+#define FLR_WBAL_COEF1_ES1 0x23
157+#define FLR_WBAL_COEF2_ES1 0x39
158+#define FLR_WBAL_COEF3_ES1 0x20
159+
160+/* Default values in Office Flourescent Light for Black Adjustment*/
161+#define FLR_BLKADJ_BLUE 0x0
162+#define FLR_BLKADJ_GREEN 0x0
163+#define FLR_BLKADJ_RED 0x0
164+
165+static int update_color_matrix;
166+
167+/**
168+ * struct isp_prev - Structure for storing ISP Preview module information
169+ * @prev_inuse: Flag to determine if CCDC has been reserved or not (0 or 1).
170+ * @prevout_w: Preview output width.
171+ * @prevout_h: Preview output height.
172+ * @previn_w: Preview input width.
173+ * @previn_h: Preview input height.
174+ * @prev_inpfmt: Preview input format.
175+ * @prev_outfmt: Preview output format.
176+ * @hmed_en: Horizontal median filter enable.
177+ * @nf_en: Noise filter enable.
178+ * @dcor_en: Defect correction enable.
179+ * @cfa_en: Color Filter Array (CFA) interpolation enable.
180+ * @csup_en: Chrominance suppression enable.
181+ * @yenh_en: Luma enhancement enable.
182+ * @fmtavg: Number of horizontal pixels to average in input formatter. The
183+ * input width should be a multiple of this number.
184+ * @brightness: Brightness in preview module.
185+ * @contrast: Contrast in preview module.
186+ * @color: Color effect in preview module.
187+ * @cfafmt: Color Filter Array (CFA) Format.
188+ * @ispprev_mutex: Mutex for isp preview.
189+ *
190+ * This structure is used to store the OMAP ISP Preview module Information.
191+ */
192+static struct isp_prev {
193+ int pm_state;
194+ u8 prev_inuse;
195+ u32 prevout_w;
196+ u32 prevout_h;
197+ u32 previn_w;
198+ u32 previn_h;
199+ enum preview_input prev_inpfmt;
200+ enum preview_output prev_outfmt;
201+ u8 hmed_en;
202+ u8 nf_en;
203+ u8 dcor_en;
204+ u8 cfa_en;
205+ u8 csup_en;
206+ u8 yenh_en;
207+ u8 fmtavg;
208+ u8 brightness;
209+ u8 contrast;
210+ enum v4l2_colorfx color;
211+ enum cfa_fmt cfafmt;
212+ struct mutex ispprev_mutex; /* For checking/modifying prev_inuse */
213+ u32 sph;
214+ u32 slv;
215+} ispprev_obj;
216+
217+/* Saved parameters */
218+static struct prev_params *prev_config_params;
219+
220+/*
221+ * Coeficient Tables for the submodules in Preview.
222+ * Array is initialised with the values from.the tables text file.
223+ */
224+
225+/*
226+ * CFA Filter Coefficient Table
227+ *
228+ */
229+static u32 cfa_coef_table[] = {
230+#include "cfa_coef_table.h"
231+};
232+
233+/*
234+ * Gamma Correction Table - Red
235+ */
236+static u32 redgamma_table[] = {
237+#include "redgamma_table.h"
238+};
239+
240+/*
241+ * Gamma Correction Table - Green
242+ */
243+static u32 greengamma_table[] = {
244+#include "greengamma_table.h"
245+};
246+
247+/*
248+ * Gamma Correction Table - Blue
249+ */
250+static u32 bluegamma_table[] = {
251+#include "bluegamma_table.h"
252+};
253+
254+/*
255+ * Noise Filter Threshold table
256+ */
257+static u32 noise_filter_table[] = {
258+#include "noise_filter_table.h"
259+};
260+
261+/*
262+ * Luminance Enhancement Table
263+ */
264+static u32 luma_enhance_table[] = {
265+#include "luma_enhance_table.h"
266+};
267+
268+/**
269+ * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
270+ * @userspace_add: Pointer from Userspace to structure with flags and data to
271+ * update.
272+ **/
273+int omap34xx_isp_preview_config(void *userspace_add)
274+{
275+ struct ispprev_hmed prev_hmed_t;
276+ struct ispprev_cfa prev_cfa_t;
277+ struct ispprev_csup csup_t;
278+ struct ispprev_wbal prev_wbal_t;
279+ struct ispprev_blkadj prev_blkadj_t;
280+ struct ispprev_rgbtorgb rgb2rgb_t;
281+ struct ispprev_csc prev_csc_t;
282+ struct ispprev_yclimit yclimit_t;
283+ struct ispprev_dcor prev_dcor_t;
284+ struct ispprv_update_config *preview_struct;
285+ struct isptables_update isp_table_update;
286+ int yen_t[ISPPRV_YENH_TBL_SIZE];
287+
288+ if (userspace_add == NULL)
289+ return -EINVAL;
290+
291+ preview_struct = userspace_add;
292+
293+ if (ISP_ABS_PREV_LUMAENH & preview_struct->flag) {
294+ if (ISP_ABS_PREV_LUMAENH & preview_struct->update) {
295+ if (copy_from_user(yen_t, preview_struct->yen,
296+ sizeof(yen_t)))
297+ goto err_copy_from_user;
298+ isppreview_config_luma_enhancement(yen_t);
299+ }
300+ params->features |= PREV_LUMA_ENHANCE;
301+ } else if (ISP_ABS_PREV_LUMAENH & preview_struct->update)
302+ params->features &= ~PREV_LUMA_ENHANCE;
303+
304+ if (ISP_ABS_PREV_INVALAW & preview_struct->flag) {
305+ isppreview_enable_invalaw(1);
306+ params->features |= PREV_INVERSE_ALAW;
307+ } else {
308+ isppreview_enable_invalaw(0);
309+ params->features &= ~PREV_INVERSE_ALAW;
310+ }
311+
312+ if (ISP_ABS_PREV_HRZ_MED & preview_struct->flag) {
313+ if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
314+ if (copy_from_user(&prev_hmed_t,
315+ (struct ispprev_hmed *)
316+ preview_struct->prev_hmed,
317+ sizeof(struct ispprev_hmed)))
318+ goto err_copy_from_user;
319+ isppreview_config_hmed(prev_hmed_t);
320+ }
321+ isppreview_enable_hmed(1);
322+ params->features |= PREV_HORZ_MEDIAN_FILTER;
323+ } else if (ISP_ABS_PREV_HRZ_MED & preview_struct->update) {
324+ isppreview_enable_hmed(0);
325+ params->features &= ~PREV_HORZ_MEDIAN_FILTER;
326+ }
327+
328+ if (ISP_ABS_PREV_CFA & preview_struct->flag) {
329+ if (ISP_ABS_PREV_CFA & preview_struct->update) {
330+ if (copy_from_user(&prev_cfa_t,
331+ (struct ispprev_cfa *)
332+ preview_struct->prev_cfa,
333+ sizeof(struct ispprev_cfa)))
334+ goto err_copy_from_user;
335+
336+ isppreview_config_cfa(prev_cfa_t);
337+ }
338+ isppreview_enable_cfa(1);
339+ params->features |= PREV_CFA;
340+ } else if (ISP_ABS_PREV_CFA & preview_struct->update) {
341+ isppreview_enable_cfa(0);
342+ params->features &= ~PREV_CFA;
343+ }
344+
345+ if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->flag) {
346+ if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
347+ if (copy_from_user(&csup_t,
348+ (struct ispprev_csup *)
349+ preview_struct->csup,
350+ sizeof(struct ispprev_csup)))
351+ goto err_copy_from_user;
352+ isppreview_config_chroma_suppression(csup_t);
353+ }
354+ isppreview_enable_chroma_suppression(1);
355+ params->features |= PREV_CHROMA_SUPPRESS;
356+ } else if (ISP_ABS_PREV_CHROMA_SUPP & preview_struct->update) {
357+ isppreview_enable_chroma_suppression(0);
358+ params->features &= ~PREV_CHROMA_SUPPRESS;
359+ }
360+
361+ if (ISP_ABS_PREV_WB & preview_struct->update) {
362+ if (copy_from_user(&prev_wbal_t, (struct ispprev_wbal *)
363+ preview_struct->prev_wbal,
364+ sizeof(struct ispprev_wbal)))
365+ goto err_copy_from_user;
366+ isppreview_config_whitebalance(prev_wbal_t);
367+ }
368+
369+ if (ISP_ABS_PREV_BLKADJ & preview_struct->update) {
370+ if (copy_from_user(&prev_blkadj_t, (struct ispprev_blkadjl *)
371+ preview_struct->prev_blkadj,
372+ sizeof(struct ispprev_blkadj)))
373+ goto err_copy_from_user;
374+ isppreview_config_blkadj(prev_blkadj_t);
375+ }
376+
377+ if (ISP_ABS_PREV_RGB2RGB & preview_struct->update) {
378+ if (copy_from_user(&rgb2rgb_t, (struct ispprev_rgbtorgb *)
379+ preview_struct->rgb2rgb,
380+ sizeof(struct ispprev_rgbtorgb)))
381+ goto err_copy_from_user;
382+ isppreview_config_rgb_blending(rgb2rgb_t);
383+ }
384+
385+ if (ISP_ABS_PREV_COLOR_CONV & preview_struct->update) {
386+ if (copy_from_user(&prev_csc_t, (struct ispprev_csc *)
387+ preview_struct->prev_csc,
388+ sizeof(struct ispprev_csc)))
389+ goto err_copy_from_user;
390+ isppreview_config_rgb_to_ycbcr(prev_csc_t);
391+ }
392+
393+ if (ISP_ABS_PREV_YC_LIMIT & preview_struct->update) {
394+ if (copy_from_user(&yclimit_t, (struct ispprev_yclimit *)
395+ preview_struct->yclimit,
396+ sizeof(struct ispprev_yclimit)))
397+ goto err_copy_from_user;
398+ isppreview_config_yc_range(yclimit_t);
399+ }
400+
401+ if (ISP_ABS_PREV_DEFECT_COR & preview_struct->flag) {
402+ if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
403+ if (copy_from_user(&prev_dcor_t,
404+ (struct ispprev_dcor *)
405+ preview_struct->prev_dcor,
406+ sizeof(struct ispprev_dcor)))
407+ goto err_copy_from_user;
408+ isppreview_config_dcor(prev_dcor_t);
409+ }
410+ isppreview_enable_dcor(1);
411+ params->features |= PREV_DEFECT_COR;
412+ } else if (ISP_ABS_PREV_DEFECT_COR & preview_struct->update) {
413+ isppreview_enable_dcor(0);
414+ params->features &= ~PREV_DEFECT_COR;
415+ }
416+
417+ if (ISP_ABS_PREV_GAMMABYPASS & preview_struct->flag) {
418+ isppreview_enable_gammabypass(1);
419+ params->features |= PREV_GAMMA_BYPASS;
420+ } else {
421+ isppreview_enable_gammabypass(0);
422+ params->features &= ~PREV_GAMMA_BYPASS;
423+ }
424+
425+ isp_table_update.update = preview_struct->update;
426+ isp_table_update.flag = preview_struct->flag;
427+ isp_table_update.prev_nf = preview_struct->prev_nf;
428+ isp_table_update.red_gamma = preview_struct->red_gamma;
429+ isp_table_update.green_gamma = preview_struct->green_gamma;
430+ isp_table_update.blue_gamma = preview_struct->blue_gamma;
431+
432+ if (omap34xx_isp_tables_update(&isp_table_update))
433+ goto err_copy_from_user;
434+
435+ return 0;
436+
437+err_copy_from_user:
438+ printk(KERN_ERR "Preview Config: Copy From User Error\n");
439+ return -EFAULT;
440+}
441+EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
442+
443+/**
444+ * omap34xx_isp_tables_update - Abstraction layer Tables update.
445+ * @isptables_struct: Pointer from Userspace to structure with flags and table
446+ * data to update.
447+ **/
448+int omap34xx_isp_tables_update(struct isptables_update *isptables_struct)
449+{
450+
451+ if (ISP_ABS_TBL_NF & isptables_struct->flag) {
452+ nf_enable = 1;
453+ params->features |= PREV_NOISE_FILTER;
454+ if (ISP_ABS_TBL_NF & isptables_struct->update) {
455+ if (copy_from_user(&prev_nf_t, (struct ispprev_nf *)
456+ isptables_struct->prev_nf,
457+ sizeof(struct ispprev_nf)))
458+ goto err_copy_from_user;
459+
460+ nf_update = 1;
461+ } else
462+ nf_update = 0;
463+ } else {
464+ nf_enable = 0;
465+ params->features &= ~PREV_NOISE_FILTER;
466+ if (ISP_ABS_TBL_NF & isptables_struct->update)
467+ nf_update = 1;
468+ else
469+ nf_update = 0;
470+ }
471+
472+ if (ISP_ABS_TBL_REDGAMMA & isptables_struct->update) {
473+ if (copy_from_user(redgamma_table, isptables_struct->red_gamma,
474+ sizeof(redgamma_table))) {
475+ goto err_copy_from_user;
476+ }
477+ rg_update = 1;
478+ } else
479+ rg_update = 0;
480+
481+ if (ISP_ABS_TBL_GREENGAMMA & isptables_struct->update) {
482+ if (copy_from_user(greengamma_table,
483+ isptables_struct->green_gamma,
484+ sizeof(greengamma_table)))
485+ goto err_copy_from_user;
486+ gg_update = 1;
487+ } else
488+ gg_update = 0;
489+
490+ if (ISP_ABS_TBL_BLUEGAMMA & isptables_struct->update) {
491+ if (copy_from_user(bluegamma_table,
492+ isptables_struct->blue_gamma,
493+ sizeof(bluegamma_table))) {
494+ goto err_copy_from_user;
495+ }
496+ bg_update = 1;
497+ } else
498+ bg_update = 0;
499+
500+ return 0;
501+
502+err_copy_from_user:
503+ printk(KERN_ERR "Preview Tables:Copy From User Error\n");
504+ return -EFAULT;
505+}
506+
507+/**
508+ * isppreview_config_shadow_registers - Program shadow registers for preview.
509+ *
510+ * Allows user to program shadow registers associated with preview module.
511+ **/
512+void isppreview_config_shadow_registers()
513+{
514+ u8 current_brightness_contrast;
515+ int ctr, prv_disabled;
516+
517+ isppreview_query_brightness(&current_brightness_contrast);
518+ if (current_brightness_contrast !=
519+ (ispprev_obj.brightness * ISPPRV_BRIGHT_UNITS)) {
520+ DPRINTK_ISPPREV(" Changing Brightness level to %d\n",
521+ ispprev_obj.brightness);
522+ isppreview_config_brightness(ispprev_obj.brightness *
523+ ISPPRV_BRIGHT_UNITS);
524+ }
525+
526+ isppreview_query_contrast(&current_brightness_contrast);
527+ if (current_brightness_contrast !=
528+ (ispprev_obj.contrast * ISPPRV_CONTRAST_UNITS)) {
529+ DPRINTK_ISPPREV(" Changing Contrast level to %d\n",
530+ ispprev_obj.contrast);
531+ isppreview_config_contrast(ispprev_obj.contrast *
532+ ISPPRV_CONTRAST_UNITS);
533+ }
534+ if (update_color_matrix) {
535+ isppreview_config_rgb_to_ycbcr(flr_prev_csc[ispprev_obj.color]);
536+ update_color_matrix = 0;
537+ }
538+ if (gg_update || rg_update || bg_update || nf_update) {
539+ isppreview_enable(0);
540+ prv_disabled = 1;
541+ }
542+
543+ if (gg_update) {
544+ isp_reg_writel(ISPPRV_TBL_ADDR_GREEN_G_START,
545+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
546+
547+ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
548+ isp_reg_writel(greengamma_table[ctr],
549+ OMAP3_ISP_IOMEM_PREV,
550+ ISPPRV_SET_TBL_DATA);
551+ }
552+ gg_update = 0;
553+ }
554+
555+ if (rg_update) {
556+ isp_reg_writel(ISPPRV_TBL_ADDR_RED_G_START,
557+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
558+
559+ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
560+ isp_reg_writel(redgamma_table[ctr],
561+ OMAP3_ISP_IOMEM_PREV,
562+ ISPPRV_SET_TBL_DATA);
563+ }
564+ rg_update = 0;
565+ }
566+
567+ if (bg_update) {
568+ isp_reg_writel(ISPPRV_TBL_ADDR_BLUE_G_START,
569+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
570+
571+ for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
572+ isp_reg_writel(bluegamma_table[ctr],
573+ OMAP3_ISP_IOMEM_PREV,
574+ ISPPRV_SET_TBL_DATA);
575+ }
576+ bg_update = 0;
577+ }
578+
579+ if (nf_update && nf_enable) {
580+ isp_reg_writel(0xC00,
581+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
582+ isp_reg_writel(prev_nf_t.spread,
583+ OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
584+ for (ctr = 0; ctr < ISPPRV_NF_TBL_SIZE; ctr++) {
585+ isp_reg_writel(prev_nf_t.table[ctr],
586+ OMAP3_ISP_IOMEM_PREV,
587+ ISPPRV_SET_TBL_DATA);
588+ }
589+ isppreview_enable_noisefilter(1);
590+ nf_update = 0;
591+ }
592+
593+ if (~nf_update && nf_enable)
594+ isppreview_enable_noisefilter(1);
595+
596+ if (nf_update && ~nf_enable)
597+ isppreview_enable_noisefilter(0);
598+
599+ if (prv_disabled) {
600+ isppreview_enable(1);
601+ prv_disabled = 0;
602+ }
603+}
604+EXPORT_SYMBOL_GPL(isppreview_config_shadow_registers);
605+
606+/**
607+ * isppreview_request - Reserves the preview module.
608+ *
609+ * Returns 0 if successful, or -EBUSY if the module was already reserved.
610+ **/
611+int isppreview_request()
612+{
613+ mutex_lock(&ispprev_obj.ispprev_mutex);
614+ if (ispprev_obj.prev_inuse) {
615+ mutex_unlock(&ispprev_obj.ispprev_mutex);
616+ printk(KERN_ERR "ISP_ERR : Preview Module Busy\n");
617+ return -EBUSY;
618+ }
619+ ispprev_obj.prev_inuse = 1;
620+ mutex_unlock(&ispprev_obj.ispprev_mutex);
621+ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_PREV_RAM_EN |
622+ ISPCTRL_PREV_CLK_EN |
623+ ISPCTRL_SBL_WR1_RAM_EN);
624+ return 0;
625+}
626+EXPORT_SYMBOL_GPL(isppreview_request);
627+
628+/**
629+ * isppreview_free - Frees the preview module.
630+ *
631+ * Returns 0 if successful, or -EINVAL if the module was already freed.
632+ **/
633+int isppreview_free()
634+{
635+ mutex_lock(&ispprev_obj.ispprev_mutex);
636+ if (ispprev_obj.prev_inuse) {
637+ ispprev_obj.prev_inuse = 0;
638+ mutex_unlock(&ispprev_obj.ispprev_mutex);
639+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
640+ ~(ISPCTRL_PREV_CLK_EN |
641+ ISPCTRL_PREV_RAM_EN |
642+ ISPCTRL_SBL_WR1_RAM_EN));
643+ return 0;
644+ } else {
645+ mutex_unlock(&ispprev_obj.ispprev_mutex);
646+ DPRINTK_ISPPREV("ISP_ERR : Preview Module already freed\n");
647+ return -EINVAL;
648+ }
649+
650+}
651+EXPORT_SYMBOL_GPL(isppreview_free);
652+
653+/** isppreview_config_datapath - Specifies input and output modules for Preview
654+ * @input: Indicates the module that gives the image to preview.
655+ * @output: Indicates the module to which the preview outputs to.
656+ *
657+ * Configures the default configuration for the CCDC to work with.
658+ *
659+ * The valid values for the input are PRV_RAW_CCDC (0), PRV_RAW_MEM (1),
660+ * PRV_RGBBAYERCFA (2), PRV_COMPCFA (3), PRV_CCDC_DRKF (4), PRV_OTHERS (5).
661+ *
662+ * The valid values for the output are PREVIEW_RSZ (0), PREVIEW_MEM (1).
663+ *
664+ * Returns 0 if successful, or -EINVAL if wrong input or output values are
665+ * specified.
666+ **/
667+int isppreview_config_datapath(enum preview_input input,
668+ enum preview_output output)
669+{
670+ u32 pcr = 0;
671+ u8 enable = 0;
672+ struct prev_params *params = prev_config_params;
673+ struct ispprev_yclimit yclimit;
674+
675+ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
676+
677+ switch (input) {
678+ case PRV_RAW_CCDC:
679+ pcr &= ~ISPPRV_PCR_SOURCE;
680+ pcr &= ~ISPPRV_PCR_ONESHOT;
681+ ispprev_obj.prev_inpfmt = PRV_RAW_CCDC;
682+ break;
683+ case PRV_RAW_MEM:
684+ pcr |= ISPPRV_PCR_SOURCE;
685+ pcr |= ISPPRV_PCR_ONESHOT;
686+ ispprev_obj.prev_inpfmt = PRV_RAW_MEM;
687+ break;
688+ case PRV_CCDC_DRKF:
689+ pcr |= ISPPRV_PCR_DRKFCAP;
690+ pcr |= ISPPRV_PCR_ONESHOT;
691+ ispprev_obj.prev_inpfmt = PRV_CCDC_DRKF;
692+ break;
693+ case PRV_COMPCFA:
694+ ispprev_obj.prev_inpfmt = PRV_COMPCFA;
695+ break;
696+ case PRV_OTHERS:
697+ ispprev_obj.prev_inpfmt = PRV_OTHERS;
698+ break;
699+ case PRV_RGBBAYERCFA:
700+ ispprev_obj.prev_inpfmt = PRV_RGBBAYERCFA;
701+ break;
702+ default:
703+ printk(KERN_ERR "ISP_ERR : Wrong Input\n");
704+ return -EINVAL;
705+ };
706+
707+ switch (output) {
708+ case PREVIEW_RSZ:
709+ pcr |= ISPPRV_PCR_RSZPORT;
710+ pcr &= ~ISPPRV_PCR_SDRPORT;
711+ break;
712+ case PREVIEW_MEM:
713+ pcr &= ~ISPPRV_PCR_RSZPORT;
714+ pcr |= ISPPRV_PCR_SDRPORT;
715+ break;
716+ default:
717+ printk(KERN_ERR "ISP_ERR : Wrong Output\n");
718+ return -EINVAL;
719+ }
720+ ispprev_obj.prev_outfmt = output;
721+
722+ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
723+
724+ isppreview_config_ycpos(params->pix_fmt);
725+
726+ if (params->cfa.cfa_table != NULL)
727+ isppreview_config_cfa(params->cfa);
728+ if (params->csup.hypf_en == 1)
729+ isppreview_config_chroma_suppression(params->csup);
730+ if (params->ytable != NULL)
731+ isppreview_config_luma_enhancement(params->ytable);
732+
733+ if (params->gtable.redtable != NULL)
734+ isppreview_config_gammacorrn(params->gtable);
735+
736+ enable = (params->features & PREV_CFA) ? 1 : 0;
737+ isppreview_enable_cfa(enable);
738+
739+ enable = (params->features & PREV_CHROMA_SUPPRESS) ? 1 : 0;
740+ isppreview_enable_chroma_suppression(enable);
741+
742+ enable = (params->features & PREV_LUMA_ENHANCE) ? 1 : 0;
743+ isppreview_enable_luma_enhancement(enable);
744+
745+ enable = (params->features & PREV_NOISE_FILTER) ? 1 : 0;
746+ if (enable)
747+ isppreview_config_noisefilter(params->nf);
748+ isppreview_enable_noisefilter(enable);
749+
750+ enable = (params->features & PREV_DEFECT_COR) ? 1 : 0;
751+ if (enable)
752+ isppreview_config_dcor(params->dcor);
753+ isppreview_enable_dcor(enable);
754+
755+ enable = (params->features & PREV_GAMMA_BYPASS) ? 1 : 0;
756+ isppreview_enable_gammabypass(enable);
757+
758+ isppreview_config_whitebalance(params->wbal);
759+ isppreview_config_blkadj(params->blk_adj);
760+ isppreview_config_rgb_blending(params->rgb2rgb);
761+ isppreview_config_rgb_to_ycbcr(params->rgb2ycbcr);
762+
763+ isppreview_config_contrast(params->contrast * ISPPRV_CONTRAST_UNITS);
764+ isppreview_config_brightness(params->brightness * ISPPRV_BRIGHT_UNITS);
765+
766+ yclimit.minC = ISPPRV_YC_MIN;
767+ yclimit.maxC = ISPPRV_YC_MAX;
768+ yclimit.minY = ISPPRV_YC_MIN;
769+ yclimit.maxY = ISPPRV_YC_MAX;
770+ isppreview_config_yc_range(yclimit);
771+
772+ return 0;
773+}
774+EXPORT_SYMBOL_GPL(isppreview_config_datapath);
775+
776+/**
777+ * isppreview_set_skip - Set the number of rows/columns that should be skipped.
778+ * h - Start Pixel Horizontal.
779+ * v - Start Line Vertical.
780+ **/
781+void isppreview_set_skip(u32 h, u32 v)
782+{
783+ ispprev_obj.sph = h;
784+ ispprev_obj.slv = v;
785+}
786+EXPORT_SYMBOL_GPL(isppreview_set_skip);
787+
788+/**
789+ * isppreview_config_ycpos - Configure byte layout of YUV image.
790+ * @mode: Indicates the required byte layout.
791+ **/
792+void isppreview_config_ycpos(enum preview_ycpos_mode mode)
793+{
794+ u32 pcr = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
795+ pcr &= ~ISPPRV_PCR_YCPOS_CrYCbY;
796+ pcr |= (mode << ISPPRV_PCR_YCPOS_SHIFT);
797+ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
798+}
799+EXPORT_SYMBOL_GPL(isppreview_config_ycpos);
800+
801+/**
802+ * isppreview_config_averager - Enable / disable / configure averager
803+ * @average: Average value to be configured.
804+ **/
805+void isppreview_config_averager(u8 average)
806+{
807+ int reg = 0;
808+
809+ reg = AVE_ODD_PIXEL_DIST | AVE_EVEN_PIXEL_DIST | average;
810+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
811+}
812+EXPORT_SYMBOL_GPL(isppreview_config_averager);
813+
814+/**
815+ * isppreview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
816+ * @enable: 1 - Reverse the A-Law done in CCDC.
817+ **/
818+void isppreview_enable_invalaw(u8 enable)
819+{
820+ u32 pcr_val = 0;
821+ pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
822+
823+ if (enable) {
824+ isp_reg_writel(pcr_val | ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW,
825+ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
826+ } else {
827+ isp_reg_writel(pcr_val &
828+ ~(ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW),
829+ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
830+ }
831+}
832+EXPORT_SYMBOL_GPL(isppreview_enable_invalaw);
833+
834+/**
835+ * isppreview_enable_drkframe - Enable/Disable of the darkframe subtract.
836+ * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
837+ * subtracted with the pixels in the current frame.
838+ *
839+ * The proccess is applied for each captured frame.
840+ **/
841+void isppreview_enable_drkframe(u8 enable)
842+{
843+ if (enable)
844+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DRKFEN);
845+ else {
846+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
847+ ~ISPPRV_PCR_DRKFEN);
848+ }
849+}
850+EXPORT_SYMBOL_GPL(isppreview_enable_drkframe);
851+
852+/**
853+ * isppreview_enable_shadcomp - Enables/Disables the shading compensation.
854+ * @enable: 1 - Enables the shading compensation.
855+ *
856+ * If dark frame subtract won't be used, then enable this shading
857+ * compensation.
858+ **/
859+void isppreview_enable_shadcomp(u8 enable)
860+{
861+
862+ if (enable) {
863+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
864+ ISPPRV_PCR_SCOMP_EN);
865+ isppreview_enable_drkframe(1);
866+ } else {
867+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
868+ ~ISPPRV_PCR_SCOMP_EN);
869+ }
870+}
871+EXPORT_SYMBOL_GPL(isppreview_enable_shadcomp);
872+
873+/**
874+ * isppreview_config_drkf_shadcomp - Configures shift value in shading comp.
875+ * @scomp_shtval: 3bit value of shift used in shading compensation.
876+ **/
877+void isppreview_config_drkf_shadcomp(u8 scomp_shtval)
878+{
879+ u32 pcr_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
880+
881+ pcr_val &= ISPPRV_PCR_SCOMP_SFT_MASK;
882+ isp_reg_writel(pcr_val | (scomp_shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT),
883+ OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
884+}
885+EXPORT_SYMBOL_GPL(isppreview_config_drkf_shadcomp);
886+
887+/**
888+ * isppreview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
889+ * @enable: 1 - Enables Horizontal Median Filter.
890+ **/
891+void isppreview_enable_hmed(u8 enable)
892+{
893+ if (enable)
894+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_HMEDEN);
895+ else {
896+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
897+ ~ISPPRV_PCR_HMEDEN);
898+ }
899+ ispprev_obj.hmed_en = enable ? 1 : 0;
900+}
901+EXPORT_SYMBOL_GPL(isppreview_enable_hmed);
902+
903+/**
904+ * isppreview_config_hmed - Configures the Horizontal Median Filter.
905+ * @prev_hmed: Structure containing the odd and even distance between the
906+ * pixels in the image along with the filter threshold.
907+ **/
908+void isppreview_config_hmed(struct ispprev_hmed prev_hmed)
909+{
910+
911+ u32 odddist = 0;
912+ u32 evendist = 0;
913+
914+ if (prev_hmed.odddist == 1)
915+ odddist = ~ISPPRV_HMED_ODDDIST;
916+ else
917+ odddist = ISPPRV_HMED_ODDDIST;
918+
919+ if (prev_hmed.evendist == 1)
920+ evendist = ~ISPPRV_HMED_EVENDIST;
921+ else
922+ evendist = ISPPRV_HMED_EVENDIST;
923+
924+ isp_reg_writel(odddist | evendist | (prev_hmed.thres <<
925+ ISPPRV_HMED_THRESHOLD_SHIFT),
926+ OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
927+
928+}
929+EXPORT_SYMBOL_GPL(isppreview_config_hmed);
930+
931+/**
932+ * isppreview_config_noisefilter - Configures the Noise Filter.
933+ * @prev_nf: Structure containing the noisefilter table, strength to be used
934+ * for the noise filter and the defect correction enable flag.
935+ **/
936+void isppreview_config_noisefilter(struct ispprev_nf prev_nf)
937+{
938+ int i = 0;
939+
940+ isp_reg_writel(prev_nf.spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
941+ isp_reg_writel(ISPPRV_NF_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
942+ ISPPRV_SET_TBL_ADDR);
943+ for (i = 0; i < ISPPRV_NF_TBL_SIZE; i++) {
944+ isp_reg_writel(prev_nf.table[i], OMAP3_ISP_IOMEM_PREV,
945+ ISPPRV_SET_TBL_DATA);
946+ }
947+}
948+EXPORT_SYMBOL_GPL(isppreview_config_noisefilter);
949+
950+/**
951+ * isppreview_config_dcor - Configures the defect correction
952+ * @prev_nf: Structure containing the defect correction structure
953+ **/
954+void isppreview_config_dcor(struct ispprev_dcor prev_dcor)
955+{
956+ if (prev_dcor.couplet_mode_en) {
957+ isp_reg_writel(prev_dcor.detect_correct[0],
958+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
959+ isp_reg_writel(prev_dcor.detect_correct[1],
960+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
961+ isp_reg_writel(prev_dcor.detect_correct[2],
962+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
963+ isp_reg_writel(prev_dcor.detect_correct[3],
964+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
965+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCCOUP);
966+ } else {
967+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
968+ ~ISPPRV_PCR_DCCOUP);
969+ }
970+}
971+EXPORT_SYMBOL_GPL(isppreview_config_dcor);
972+
973+/**
974+ * isppreview_config_cfa - Configures the CFA Interpolation parameters.
975+ * @prev_cfa: Structure containing the CFA interpolation table, CFA format
976+ * in the image, vertical and horizontal gradient threshold.
977+ **/
978+void isppreview_config_cfa(struct ispprev_cfa prev_cfa)
979+{
980+ int i = 0;
981+
982+ ispprev_obj.cfafmt = prev_cfa.cfafmt;
983+
984+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
985+ (prev_cfa.cfafmt << ISPPRV_PCR_CFAFMT_SHIFT));
986+
987+ isp_reg_writel(
988+ (prev_cfa.cfa_gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
989+ (prev_cfa.cfa_gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
990+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
991+
992+ isp_reg_writel(ISPPRV_CFA_TABLE_ADDR, OMAP3_ISP_IOMEM_PREV,
993+ ISPPRV_SET_TBL_ADDR);
994+
995+ for (i = 0; i < ISPPRV_CFA_TBL_SIZE; i++) {
996+ isp_reg_writel(prev_cfa.cfa_table[i],
997+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
998+ }
999+}
1000+EXPORT_SYMBOL_GPL(isppreview_config_cfa);
1001+
1002+/**
1003+ * isppreview_config_gammacorrn - Configures the Gamma Correction table values
1004+ * @gtable: Structure containing the table for red, blue, green gamma table.
1005+ **/
1006+void isppreview_config_gammacorrn(struct ispprev_gtable gtable)
1007+{
1008+ int i = 0;
1009+
1010+ isp_reg_writel(ISPPRV_REDGAMMA_TABLE_ADDR,
1011+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
1012+ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
1013+ isp_reg_writel(gtable.redtable[i],
1014+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
1015+ }
1016+
1017+ isp_reg_writel(ISPPRV_GREENGAMMA_TABLE_ADDR,
1018+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
1019+ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
1020+ isp_reg_writel(gtable.greentable[i],
1021+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
1022+ }
1023+
1024+ isp_reg_writel(ISPPRV_BLUEGAMMA_TABLE_ADDR,
1025+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
1026+ for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
1027+ isp_reg_writel(gtable.bluetable[i],
1028+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
1029+ }
1030+}
1031+EXPORT_SYMBOL_GPL(isppreview_config_gammacorrn);
1032+
1033+/**
1034+ * isppreview_config_luma_enhancement - Sets the Luminance Enhancement table.
1035+ * @ytable: Structure containing the table for Luminance Enhancement table.
1036+ **/
1037+void isppreview_config_luma_enhancement(u32 *ytable)
1038+{
1039+ int i = 0;
1040+
1041+ isp_reg_writel(ISPPRV_YENH_TABLE_ADDR,
1042+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
1043+ for (i = 0; i < ISPPRV_YENH_TBL_SIZE; i++) {
1044+ isp_reg_writel(ytable[i],
1045+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
1046+ }
1047+}
1048+EXPORT_SYMBOL_GPL(isppreview_config_luma_enhancement);
1049+
1050+/**
1051+ * isppreview_config_chroma_suppression - Configures the Chroma Suppression.
1052+ * @csup: Structure containing the threshold value for suppression
1053+ * and the hypass filter enable flag.
1054+ **/
1055+void isppreview_config_chroma_suppression(struct ispprev_csup csup)
1056+{
1057+ isp_reg_writel(csup.gain | (csup.thres << ISPPRV_CSUP_THRES_SHIFT) |
1058+ (csup.hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
1059+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
1060+}
1061+EXPORT_SYMBOL_GPL(isppreview_config_chroma_suppression);
1062+
1063+/**
1064+ * isppreview_enable_noisefilter - Enables/Disables the Noise Filter.
1065+ * @enable: 1 - Enables the Noise Filter.
1066+ **/
1067+void isppreview_enable_noisefilter(u8 enable)
1068+{
1069+ if (enable)
1070+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_NFEN);
1071+ else
1072+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_NFEN);
1073+ ispprev_obj.nf_en = enable ? 1 : 0;
1074+}
1075+EXPORT_SYMBOL_GPL(isppreview_enable_noisefilter);
1076+
1077+/**
1078+ * isppreview_enable_dcor - Enables/Disables the defect correction.
1079+ * @enable: 1 - Enables the defect correction.
1080+ **/
1081+void isppreview_enable_dcor(u8 enable)
1082+{
1083+ if (enable)
1084+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DCOREN);
1085+ else {
1086+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1087+ ~ISPPRV_PCR_DCOREN);
1088+ }
1089+ ispprev_obj.dcor_en = enable ? 1 : 0;
1090+}
1091+EXPORT_SYMBOL_GPL(isppreview_enable_dcor);
1092+
1093+/**
1094+ * isppreview_enable_cfa - Enable/Disable the CFA Interpolation.
1095+ * @enable: 1 - Enables the CFA.
1096+ **/
1097+void isppreview_enable_cfa(u8 enable)
1098+{
1099+ if (enable)
1100+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
1101+ else {
1102+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1103+ ~ISPPRV_PCR_CFAEN);
1104+ }
1105+ ispprev_obj.cfa_en = enable ? 1 : 0;
1106+}
1107+EXPORT_SYMBOL_GPL(isppreview_enable_cfa);
1108+
1109+/**
1110+ * isppreview_enable_gammabypass - Enables/Disables the GammaByPass
1111+ * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
1112+ * 0 - Goes through Gamma Correction. input and output is 10bit.
1113+ **/
1114+void isppreview_enable_gammabypass(u8 enable)
1115+{
1116+ if (enable) {
1117+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1118+ ISPPRV_PCR_GAMMA_BYPASS);
1119+ } else {
1120+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1121+ ~ISPPRV_PCR_GAMMA_BYPASS);
1122+ }
1123+}
1124+EXPORT_SYMBOL_GPL(isppreview_enable_gammabypass);
1125+
1126+/**
1127+ * isppreview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
1128+ * @enable: 1 - Enable the Luminance Enhancement.
1129+ **/
1130+void isppreview_enable_luma_enhancement(u8 enable)
1131+{
1132+ if (enable) {
1133+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1134+ ISPPRV_PCR_YNENHEN);
1135+ } else {
1136+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1137+ ~ISPPRV_PCR_YNENHEN);
1138+ }
1139+ ispprev_obj.yenh_en = enable ? 1 : 0;
1140+}
1141+EXPORT_SYMBOL_GPL(isppreview_enable_luma_enhancement);
1142+
1143+/**
1144+ * isppreview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
1145+ * @enable: 1 - Enable the Chrominance Suppression.
1146+ **/
1147+void isppreview_enable_chroma_suppression(u8 enable)
1148+{
1149+ if (enable)
1150+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_SUPEN);
1151+ else {
1152+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1153+ ~ISPPRV_PCR_SUPEN);
1154+ }
1155+ ispprev_obj.csup_en = enable ? 1 : 0;
1156+}
1157+EXPORT_SYMBOL_GPL(isppreview_enable_chroma_suppression);
1158+
1159+/**
1160+ * isppreview_config_whitebalance - Configures the White Balance parameters.
1161+ * @prev_wbal: Structure containing the digital gain and white balance
1162+ * coefficient.
1163+ *
1164+ * Coefficient matrix always with default values.
1165+ **/
1166+void isppreview_config_whitebalance(struct ispprev_wbal prev_wbal)
1167+{
1168+ u32 val;
1169+
1170+ isp_reg_writel(prev_wbal.dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
1171+
1172+ val = prev_wbal.coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
1173+ val |= prev_wbal.coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
1174+ val |= prev_wbal.coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
1175+ val |= prev_wbal.coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
1176+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
1177+
1178+ isp_reg_writel(ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
1179+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
1180+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
1181+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
1182+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
1183+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
1184+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
1185+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
1186+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
1187+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
1188+ ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
1189+ ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
1190+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
1191+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
1192+ ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
1193+ ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
1194+ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
1195+}
1196+EXPORT_SYMBOL_GPL(isppreview_config_whitebalance);
1197+
1198+/**
1199+ * isppreview_config_whitebalance2 - Configures the White Balance parameters.
1200+ * @prev_wbal: Structure containing the digital gain and white balance
1201+ * coefficient.
1202+ *
1203+ * Coefficient matrix can be changed.
1204+ **/
1205+void isppreview_config_whitebalance2(struct prev_white_balance prev_wbal)
1206+{
1207+ isp_reg_writel(prev_wbal.wb_dgain,
1208+ OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
1209+ isp_reg_writel(prev_wbal.wb_gain[0] |
1210+ prev_wbal.wb_gain[1] << ISPPRV_WBGAIN_COEF1_SHIFT |
1211+ prev_wbal.wb_gain[2] << ISPPRV_WBGAIN_COEF2_SHIFT |
1212+ prev_wbal.wb_gain[3] << ISPPRV_WBGAIN_COEF3_SHIFT,
1213+ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
1214+
1215+ isp_reg_writel(
1216+ prev_wbal.wb_coefmatrix[0][0] << ISPPRV_WBSEL_N0_0_SHIFT |
1217+ prev_wbal.wb_coefmatrix[0][1] << ISPPRV_WBSEL_N0_1_SHIFT |
1218+ prev_wbal.wb_coefmatrix[0][2] << ISPPRV_WBSEL_N0_2_SHIFT |
1219+ prev_wbal.wb_coefmatrix[0][3] << ISPPRV_WBSEL_N0_3_SHIFT |
1220+ prev_wbal.wb_coefmatrix[1][0] << ISPPRV_WBSEL_N1_0_SHIFT |
1221+ prev_wbal.wb_coefmatrix[1][1] << ISPPRV_WBSEL_N1_1_SHIFT |
1222+ prev_wbal.wb_coefmatrix[1][2] << ISPPRV_WBSEL_N1_2_SHIFT |
1223+ prev_wbal.wb_coefmatrix[1][3] << ISPPRV_WBSEL_N1_3_SHIFT |
1224+ prev_wbal.wb_coefmatrix[2][0] << ISPPRV_WBSEL_N2_0_SHIFT |
1225+ prev_wbal.wb_coefmatrix[2][1] << ISPPRV_WBSEL_N2_1_SHIFT |
1226+ prev_wbal.wb_coefmatrix[2][2] << ISPPRV_WBSEL_N2_2_SHIFT |
1227+ prev_wbal.wb_coefmatrix[2][3] << ISPPRV_WBSEL_N2_3_SHIFT |
1228+ prev_wbal.wb_coefmatrix[3][0] << ISPPRV_WBSEL_N3_0_SHIFT |
1229+ prev_wbal.wb_coefmatrix[3][1] << ISPPRV_WBSEL_N3_1_SHIFT |
1230+ prev_wbal.wb_coefmatrix[3][2] << ISPPRV_WBSEL_N3_2_SHIFT |
1231+ prev_wbal.wb_coefmatrix[3][3] << ISPPRV_WBSEL_N3_3_SHIFT,
1232+ OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
1233+}
1234+EXPORT_SYMBOL_GPL(isppreview_config_whitebalance2);
1235+
1236+/**
1237+ * isppreview_config_blkadj - Configures the Black Adjustment parameters.
1238+ * @prev_blkadj: Structure containing the black adjustment towards red, green,
1239+ * blue.
1240+ **/
1241+void isppreview_config_blkadj(struct ispprev_blkadj prev_blkadj)
1242+{
1243+ isp_reg_writel(prev_blkadj.blue |
1244+ (prev_blkadj.green << ISPPRV_BLKADJOFF_G_SHIFT) |
1245+ (prev_blkadj.red << ISPPRV_BLKADJOFF_R_SHIFT),
1246+ OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
1247+}
1248+EXPORT_SYMBOL_GPL(isppreview_config_blkadj);
1249+
1250+/**
1251+ * isppreview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
1252+ * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
1253+ * offset.
1254+ **/
1255+void isppreview_config_rgb_blending(struct ispprev_rgbtorgb rgb2rgb)
1256+{
1257+ u32 val = 0;
1258+
1259+ val = (rgb2rgb.matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
1260+ val |= (rgb2rgb.matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
1261+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
1262+
1263+ val = (rgb2rgb.matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
1264+ val |= (rgb2rgb.matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
1265+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
1266+
1267+ val = (rgb2rgb.matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
1268+ val |= (rgb2rgb.matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
1269+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
1270+
1271+ val = (rgb2rgb.matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
1272+ val |= (rgb2rgb.matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
1273+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
1274+
1275+ val = (rgb2rgb.matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
1276+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
1277+
1278+ val = (rgb2rgb.offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
1279+ val |= (rgb2rgb.offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
1280+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
1281+
1282+ val = (rgb2rgb.offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
1283+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
1284+}
1285+EXPORT_SYMBOL_GPL(isppreview_config_rgb_blending);
1286+
1287+/**
1288+ * Configures the RGB-YCbYCr conversion matrix
1289+ * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
1290+ * YCbCr offset.
1291+ **/
1292+void isppreview_config_rgb_to_ycbcr(struct ispprev_csc prev_csc)
1293+{
1294+ u32 val = 0;
1295+
1296+ val = (prev_csc.matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
1297+ val |= (prev_csc.matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
1298+ val |= (prev_csc.matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
1299+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
1300+
1301+ val = (prev_csc.matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
1302+ val |= (prev_csc.matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
1303+ val |= (prev_csc.matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
1304+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
1305+
1306+ val = (prev_csc.matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
1307+ val |= (prev_csc.matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
1308+ val |= (prev_csc.matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
1309+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
1310+
1311+ val = (prev_csc.offset[0] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
1312+ val |= (prev_csc.offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
1313+ val |= (prev_csc.offset[2] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
1314+ isp_reg_writel(val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
1315+}
1316+EXPORT_SYMBOL_GPL(isppreview_config_rgb_to_ycbcr);
1317+
1318+/**
1319+ * isppreview_query_contrast - Query the contrast.
1320+ * @contrast: Pointer to hold the current programmed contrast value.
1321+ **/
1322+void isppreview_query_contrast(u8 *contrast)
1323+{
1324+ u32 brt_cnt_val = 0;
1325+
1326+ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1327+ *contrast = (brt_cnt_val >> ISPPRV_CNT_BRT_CNT_SHIFT) & 0xff;
1328+ DPRINTK_ISPPREV(" Current brt cnt value in hw is %x\n", brt_cnt_val);
1329+}
1330+EXPORT_SYMBOL_GPL(isppreview_query_contrast);
1331+
1332+/**
1333+ * isppreview_update_contrast - Updates the contrast.
1334+ * @contrast: Pointer to hold the current programmed contrast value.
1335+ *
1336+ * Value should be programmed before enabling the module.
1337+ **/
1338+void isppreview_update_contrast(u8 *contrast)
1339+{
1340+ ispprev_obj.contrast = *contrast;
1341+}
1342+EXPORT_SYMBOL_GPL(isppreview_update_contrast);
1343+
1344+/**
1345+ * isppreview_config_contrast - Configures the Contrast.
1346+ * @contrast: 8 bit value in U8Q4 format.
1347+ *
1348+ * Value should be programmed before enabling the module.
1349+ **/
1350+void isppreview_config_contrast(u8 contrast)
1351+{
1352+ u32 brt_cnt_val = 0;
1353+
1354+ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1355+ brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_CNT_SHIFT);
1356+ contrast &= 0xff;
1357+ isp_reg_writel(brt_cnt_val | contrast << ISPPRV_CNT_BRT_CNT_SHIFT,
1358+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1359+}
1360+EXPORT_SYMBOL_GPL(isppreview_config_contrast);
1361+
1362+/**
1363+ * isppreview_get_contrast_range - Gets the range contrast value.
1364+ * @min_contrast: Pointer to hold the minimum Contrast value.
1365+ * @max_contrast: Pointer to hold the maximum Contrast value.
1366+ **/
1367+void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast)
1368+{
1369+ *min_contrast = ISPPRV_CONTRAST_MIN;
1370+ *max_contrast = ISPPRV_CONTRAST_MAX;
1371+}
1372+EXPORT_SYMBOL_GPL(isppreview_get_contrast_range);
1373+
1374+/**
1375+ * isppreview_update_brightness - Updates the brightness in preview module.
1376+ * @brightness: Pointer to hold the current programmed brightness value.
1377+ *
1378+ **/
1379+void isppreview_update_brightness(u8 *brightness)
1380+{
1381+ ispprev_obj.brightness = *brightness;
1382+}
1383+EXPORT_SYMBOL_GPL(isppreview_update_brightness);
1384+
1385+/**
1386+ * isppreview_config_brightness - Configures the brightness.
1387+ * @contrast: 8bitvalue in U8Q0 format.
1388+ **/
1389+void isppreview_config_brightness(u8 brightness)
1390+{
1391+ u32 brt_cnt_val = 0;
1392+
1393+ DPRINTK_ISPPREV("\tConfiguring brightness in ISP: %d\n", brightness);
1394+ brt_cnt_val = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1395+ brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_BRT_SHIFT);
1396+ brightness &= 0xff;
1397+ isp_reg_writel(brt_cnt_val | brightness << ISPPRV_CNT_BRT_BRT_SHIFT,
1398+ OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1399+}
1400+EXPORT_SYMBOL_GPL(isppreview_config_brightness);
1401+
1402+/**
1403+ * isppreview_query_brightness - Query the brightness.
1404+ * @brightness: Pointer to hold the current programmed brightness value.
1405+ **/
1406+void isppreview_query_brightness(u8 *brightness)
1407+{
1408+ *brightness = isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1409+}
1410+EXPORT_SYMBOL_GPL(isppreview_query_brightness);
1411+
1412+/**
1413+ * isppreview_get_brightness_range - Gets the range brightness value
1414+ * @min_brightness: Pointer to hold the minimum brightness value
1415+ * @max_brightness: Pointer to hold the maximum brightness value
1416+ **/
1417+void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness)
1418+{
1419+ *min_brightness = ISPPRV_BRIGHT_MIN;
1420+ *max_brightness = ISPPRV_BRIGHT_MAX;
1421+}
1422+EXPORT_SYMBOL_GPL(isppreview_get_brightness_range);
1423+
1424+/**
1425+ * isppreview_set_color - Sets the color effect.
1426+ * @mode: Indicates the required color effect.
1427+ **/
1428+void isppreview_set_color(u8 *mode)
1429+{
1430+ ispprev_obj.color = *mode;
1431+ update_color_matrix = 1;
1432+}
1433+EXPORT_SYMBOL_GPL(isppreview_set_color);
1434+
1435+/**
1436+ * isppreview_get_color - Gets the current color effect.
1437+ * @mode: Indicates the current color effect.
1438+ **/
1439+void isppreview_get_color(u8 *mode)
1440+{
1441+ *mode = ispprev_obj.color;
1442+}
1443+EXPORT_SYMBOL_GPL(isppreview_get_color);
1444+
1445+/**
1446+ * isppreview_config_yc_range - Configures the max and min Y and C values.
1447+ * @yclimit: Structure containing the range of Y and C values.
1448+ **/
1449+void isppreview_config_yc_range(struct ispprev_yclimit yclimit)
1450+{
1451+ isp_reg_writel(yclimit.maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
1452+ yclimit.maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
1453+ yclimit.minC << ISPPRV_SETUP_YC_MINC_SHIFT |
1454+ yclimit.minY << ISPPRV_SETUP_YC_MINY_SHIFT,
1455+ OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
1456+}
1457+EXPORT_SYMBOL_GPL(isppreview_config_yc_range);
1458+
1459+/**
1460+ * isppreview_try_size - Calculates output dimensions with the modules enabled.
1461+ * @input_w: input width for the preview in number of pixels per line
1462+ * @input_h: input height for the preview in number of lines
1463+ * @output_w: output width from the preview in number of pixels per line
1464+ * @output_h: output height for the preview in number of lines
1465+ *
1466+ * Calculates the number of pixels cropped in the submodules that are enabled,
1467+ * Fills up the output width height variables in the isp_prev structure.
1468+ **/
1469+int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h)
1470+{
1471+ u32 prevout_w = input_w;
1472+ u32 prevout_h = input_h;
1473+ u32 div = 0;
1474+ int max_out;
1475+
1476+ ispprev_obj.previn_w = input_w;
1477+ ispprev_obj.previn_h = input_h;
1478+
1479+ if (input_w < 32 || input_h < 32) {
1480+ printk(KERN_ERR "ISP_ERR : preview does not support "
1481+ "width < 16 or height < 32 \n");
1482+ return -EINVAL;
1483+ }
1484+ if (omap_rev() == OMAP3430_REV_ES1_0)
1485+ max_out = ISPPRV_MAXOUTPUT_WIDTH;
1486+ else
1487+ max_out = ISPPRV_MAXOUTPUT_WIDTH_ES2;
1488+
1489+ ispprev_obj.fmtavg = 0;
1490+
1491+ if (input_w > max_out) {
1492+ div = (input_w/max_out);
1493+ if (div >= 2 && div < 4) {
1494+ ispprev_obj.fmtavg = 1;
1495+ prevout_w /= 2;
1496+ } else if (div >= 4 && div < 8) {
1497+ ispprev_obj.fmtavg = 2;
1498+ prevout_w /= 4;
1499+ } else if (div >= 8) {
1500+ ispprev_obj.fmtavg = 3;
1501+ prevout_w /= 8;
1502+ }
1503+ }
1504+
1505+ if (ispprev_obj.hmed_en)
1506+ prevout_w -= 4;
1507+ if (ispprev_obj.nf_en) {
1508+ prevout_w -= 4;
1509+ prevout_h -= 4;
1510+ }
1511+ if (ispprev_obj.cfa_en) {
1512+ switch (ispprev_obj.cfafmt) {
1513+ case CFAFMT_BAYER:
1514+ case CFAFMT_SONYVGA:
1515+ prevout_w -= 4;
1516+ prevout_h -= 4;
1517+ break;
1518+ case CFAFMT_RGBFOVEON:
1519+ case CFAFMT_RRGGBBFOVEON:
1520+ case CFAFMT_DNSPL:
1521+ case CFAFMT_HONEYCOMB:
1522+ prevout_h -= 2;
1523+ break;
1524+ };
1525+ }
1526+ if (ispprev_obj.yenh_en || ispprev_obj.csup_en)
1527+ prevout_w -= 2;
1528+
1529+ /* Start at the correct row/column by skipping
1530+ * a Sensor specific amount.
1531+ */
1532+ prevout_w -= ispprev_obj.sph;
1533+ prevout_h -= ispprev_obj.slv;
1534+
1535+
1536+ if (prevout_w % 2)
1537+ prevout_w -= 1;
1538+
1539+ if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
1540+ if (((prevout_w * 2) & ISP_32B_BOUNDARY_OFFSET) !=
1541+ (prevout_w * 2)) {
1542+ prevout_w = ((prevout_w * 2) &
1543+ ISP_32B_BOUNDARY_OFFSET) / 2;
1544+ }
1545+ }
1546+ *output_w = prevout_w;
1547+ ispprev_obj.prevout_w = prevout_w;
1548+ *output_h = prevout_h;
1549+ ispprev_obj.prevout_h = prevout_h;
1550+ return 0;
1551+}
1552+EXPORT_SYMBOL_GPL(isppreview_try_size);
1553+
1554+/**
1555+ * isppreview_config_size - Sets the size of ISP preview output.
1556+ * @input_w: input width for the preview in number of pixels per line
1557+ * @input_h: input height for the preview in number of lines
1558+ * @output_w: output width from the preview in number of pixels per line
1559+ * @output_h: output height for the preview in number of lines
1560+ *
1561+ * Configures the appropriate values stored in the isp_prev structure to
1562+ * HORZ/VERT_INFO. Configures PRV_AVE if needed for downsampling as calculated
1563+ * in trysize.
1564+ **/
1565+int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h)
1566+{
1567+ u32 prevsdroff;
1568+
1569+ if ((output_w != ispprev_obj.prevout_w) ||
1570+ (output_h != ispprev_obj.prevout_h)) {
1571+ printk(KERN_ERR "ISP_ERR : isppreview_try_size should "
1572+ "be called before config size\n");
1573+ return -EINVAL;
1574+ }
1575+
1576+ isp_reg_writel((ispprev_obj.sph << ISPPRV_HORZ_INFO_SPH_SHIFT) |
1577+ (ispprev_obj.previn_w - 1),
1578+ OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1579+ isp_reg_writel((ispprev_obj.slv << ISPPRV_VERT_INFO_SLV_SHIFT) |
1580+ (ispprev_obj.previn_h - 2),
1581+ OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1582+
1583+ if (ispprev_obj.cfafmt == CFAFMT_BAYER)
1584+ isp_reg_writel(ISPPRV_AVE_EVENDIST_2 <<
1585+ ISPPRV_AVE_EVENDIST_SHIFT |
1586+ ISPPRV_AVE_ODDDIST_2 <<
1587+ ISPPRV_AVE_ODDDIST_SHIFT |
1588+ ispprev_obj.fmtavg,
1589+ OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
1590+
1591+ if (ispprev_obj.prev_outfmt == PREVIEW_MEM) {
1592+ prevsdroff = ispprev_obj.prevout_w * 2;
1593+ if ((prevsdroff & ISP_32B_BOUNDARY_OFFSET) != prevsdroff) {
1594+ DPRINTK_ISPPREV("ISP_WARN: Preview output buffer line"
1595+ " size is truncated"
1596+ " to 32byte boundary\n");
1597+ prevsdroff &= ISP_32B_BOUNDARY_BUF ;
1598+ }
1599+ isppreview_config_outlineoffset(prevsdroff);
1600+ }
1601+ return 0;
1602+}
1603+EXPORT_SYMBOL_GPL(isppreview_config_size);
1604+
1605+/**
1606+ * isppreview_config_inlineoffset - Configures the Read address line offset.
1607+ * @offset: Line Offset for the input image.
1608+ **/
1609+int isppreview_config_inlineoffset(u32 offset)
1610+{
1611+ if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
1612+ isp_reg_writel(offset & 0xffff,
1613+ OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET);
1614+ } else {
1615+ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
1616+ "boundary\n");
1617+ return -EINVAL;
1618+ }
1619+ return 0;
1620+}
1621+EXPORT_SYMBOL_GPL(isppreview_config_inlineoffset);
1622+
1623+/**
1624+ * isppreview_set_inaddr - Sets memory address of input frame.
1625+ * @addr: 32bit memory address aligned on 32byte boundary.
1626+ *
1627+ * Configures the memory address from which the input frame is to be read.
1628+ **/
1629+int isppreview_set_inaddr(u32 addr)
1630+{
1631+ if ((addr & ISP_32B_BOUNDARY_BUF) == addr)
1632+ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1633+ else {
1634+ printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
1635+ "boundary\n");
1636+ return -EINVAL;
1637+ }
1638+ return 0;
1639+}
1640+EXPORT_SYMBOL_GPL(isppreview_set_inaddr);
1641+
1642+/**
1643+ * isppreview_config_outlineoffset - Configures the Write address line offset.
1644+ * @offset: Line Offset for the preview output.
1645+ **/
1646+int isppreview_config_outlineoffset(u32 offset)
1647+{
1648+ if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
1649+ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
1650+ "boundary\n");
1651+ return -EINVAL;
1652+ }
1653+ isp_reg_writel(offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1654+ ISPPRV_WADD_OFFSET);
1655+ return 0;
1656+}
1657+EXPORT_SYMBOL_GPL(isppreview_config_outlineoffset);
1658+
1659+/**
1660+ * isppreview_set_outaddr - Sets the memory address to store output frame
1661+ * @addr: 32bit memory address aligned on 32byte boundary.
1662+ *
1663+ * Configures the memory address to which the output frame is written.
1664+ **/
1665+int isppreview_set_outaddr(u32 addr)
1666+{
1667+ if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
1668+ printk(KERN_ERR "ISP_ERR: Address should be in 32 byte "
1669+ "boundary\n");
1670+ return -EINVAL;
1671+ }
1672+ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1673+ return 0;
1674+}
1675+EXPORT_SYMBOL_GPL(isppreview_set_outaddr);
1676+
1677+/**
1678+ * isppreview_config_darklineoffset - Sets the Dark frame address line offset.
1679+ * @offset: Line Offset for the Darkframe.
1680+ **/
1681+int isppreview_config_darklineoffset(u32 offset)
1682+{
1683+ if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
1684+ printk(KERN_ERR "ISP_ERR : Offset should be in 32 byte "
1685+ "boundary\n");
1686+ return -EINVAL;
1687+ }
1688+ isp_reg_writel(offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1689+ ISPPRV_DRKF_OFFSET);
1690+ return 0;
1691+}
1692+EXPORT_SYMBOL_GPL(isppreview_config_darklineoffset);
1693+
1694+/**
1695+ * isppreview_set_darkaddr - Sets the memory address to store Dark frame.
1696+ * @addr: 32bit memory address aligned on 32 bit boundary.
1697+ **/
1698+int isppreview_set_darkaddr(u32 addr)
1699+{
1700+ if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
1701+ printk(KERN_ERR "ISP_ERR : Address should be in 32 byte "
1702+ "boundary\n");
1703+ return -EINVAL;
1704+ }
1705+ isp_reg_writel(addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR);
1706+ return 0;
1707+}
1708+EXPORT_SYMBOL_GPL(isppreview_set_darkaddr);
1709+
1710+void __isppreview_enable(int enable)
1711+{
1712+ if (enable)
1713+ isp_reg_or(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_EN);
1714+ else
1715+ isp_reg_and(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ~ISPPRV_PCR_EN);
1716+}
1717+
1718+/**
1719+ * isppreview_enable - Enables the Preview module.
1720+ * @enable: 1 - Enables the preview module.
1721+ *
1722+ * Client should configure all the sub modules in Preview before this.
1723+ **/
1724+void isppreview_enable(int enable)
1725+{
1726+ __isppreview_enable(enable);
1727+ ispprev_obj.pm_state = enable;
1728+}
1729+EXPORT_SYMBOL_GPL(isppreview_enable);
1730+
1731+/**
1732+ * isppreview_suspend - Suspend Preview module.
1733+ **/
1734+void isppreview_suspend(void)
1735+{
1736+ if (ispprev_obj.pm_state)
1737+ __isppreview_enable(0);
1738+}
1739+EXPORT_SYMBOL_GPL(isppreview_suspend);
1740+
1741+/**
1742+ * isppreview_resume - Resume Preview module.
1743+ **/
1744+void isppreview_resume(void)
1745+{
1746+ if (ispprev_obj.pm_state)
1747+ __isppreview_enable(1);
1748+}
1749+EXPORT_SYMBOL_GPL(isppreview_resume);
1750+
1751+
1752+/**
1753+ * isppreview_busy - Gets busy state of preview module.
1754+ **/
1755+int isppreview_busy(void)
1756+{
1757+ return isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR) &
1758+ ISPPRV_PCR_BUSY;
1759+}
1760+EXPORT_SYMBOL_GPL(isppreview_busy);
1761+
1762+/**
1763+ * isppreview_get_config - Gets parameters of preview module.
1764+ **/
1765+struct prev_params *isppreview_get_config(void)
1766+{
1767+ return prev_config_params;
1768+}
1769+EXPORT_SYMBOL_GPL(isppreview_get_config);
1770+
1771+/**
1772+ * isppreview_save_context - Saves the values of the preview module registers.
1773+ **/
1774+void isppreview_save_context(void)
1775+{
1776+ DPRINTK_ISPPREV("Saving context\n");
1777+ isp_save_context(ispprev_reg_list);
1778+}
1779+EXPORT_SYMBOL_GPL(isppreview_save_context);
1780+
1781+/**
1782+ * isppreview_restore_context - Restores the values of preview module registers
1783+ **/
1784+void isppreview_restore_context(void)
1785+{
1786+ DPRINTK_ISPPREV("Restoring context\n");
1787+ isp_restore_context(ispprev_reg_list);
1788+}
1789+EXPORT_SYMBOL_GPL(isppreview_restore_context);
1790+
1791+/**
1792+ * isppreview_print_status - Prints the values of the Preview Module registers.
1793+ *
1794+ * Also prints other debug information stored in the preview moduel.
1795+ **/
1796+void isppreview_print_status(void)
1797+{
1798+ DPRINTK_ISPPREV("Module in use =%d\n", ispprev_obj.prev_inuse);
1799+ DPRINTK_ISPPREV("Preview Input format =%d, Output Format =%d\n",
1800+ ispprev_obj.prev_inpfmt,
1801+ ispprev_obj.prev_outfmt);
1802+ DPRINTK_ISPPREV("Accepted Preview Input (width = %d,Height = %d)\n",
1803+ ispprev_obj.previn_w,
1804+ ispprev_obj.previn_h);
1805+ DPRINTK_ISPPREV("Accepted Preview Output (width = %d,Height = %d)\n",
1806+ ispprev_obj.prevout_w,
1807+ ispprev_obj.prevout_h);
1808+ DPRINTK_ISPPREV("###ISP_CTRL in preview =0x%x\n",
1809+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
1810+ DPRINTK_ISPPREV("###ISP_IRQ0ENABLE in preview =0x%x\n",
1811+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
1812+ DPRINTK_ISPPREV("###ISP_IRQ0STATUS in preview =0x%x\n",
1813+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
1814+ DPRINTK_ISPPREV("###PRV PCR =0x%x\n",
1815+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR));
1816+ DPRINTK_ISPPREV("###PRV HORZ_INFO =0x%x\n",
1817+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO));
1818+ DPRINTK_ISPPREV("###PRV VERT_INFO =0x%x\n",
1819+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO));
1820+ DPRINTK_ISPPREV("###PRV WSDR_ADDR =0x%x\n",
1821+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR));
1822+ DPRINTK_ISPPREV("###PRV WADD_OFFSET =0x%x\n",
1823+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
1824+ ISPPRV_WADD_OFFSET));
1825+ DPRINTK_ISPPREV("###PRV AVE =0x%x\n",
1826+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE));
1827+ DPRINTK_ISPPREV("###PRV HMED =0x%x\n",
1828+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED));
1829+ DPRINTK_ISPPREV("###PRV NF =0x%x\n",
1830+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_NF));
1831+ DPRINTK_ISPPREV("###PRV WB_DGAIN =0x%x\n",
1832+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN));
1833+ DPRINTK_ISPPREV("###PRV WBGAIN =0x%x\n",
1834+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN));
1835+ DPRINTK_ISPPREV("###PRV WBSEL =0x%x\n",
1836+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL));
1837+ DPRINTK_ISPPREV("###PRV CFA =0x%x\n",
1838+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA));
1839+ DPRINTK_ISPPREV("###PRV BLKADJOFF =0x%x\n",
1840+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF));
1841+ DPRINTK_ISPPREV("###PRV RGB_MAT1 =0x%x\n",
1842+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1));
1843+ DPRINTK_ISPPREV("###PRV RGB_MAT2 =0x%x\n",
1844+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2));
1845+ DPRINTK_ISPPREV("###PRV RGB_MAT3 =0x%x\n",
1846+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3));
1847+ DPRINTK_ISPPREV("###PRV RGB_MAT4 =0x%x\n",
1848+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4));
1849+ DPRINTK_ISPPREV("###PRV RGB_MAT5 =0x%x\n",
1850+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5));
1851+ DPRINTK_ISPPREV("###PRV RGB_OFF1 =0x%x\n",
1852+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1));
1853+ DPRINTK_ISPPREV("###PRV RGB_OFF2 =0x%x\n",
1854+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2));
1855+ DPRINTK_ISPPREV("###PRV CSC0 =0x%x\n",
1856+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0));
1857+ DPRINTK_ISPPREV("###PRV CSC1 =0x%x\n",
1858+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1));
1859+ DPRINTK_ISPPREV("###PRV CSC2 =0x%x\n",
1860+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2));
1861+ DPRINTK_ISPPREV("###PRV CSC_OFFSET =0x%x\n",
1862+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET));
1863+ DPRINTK_ISPPREV("###PRV CNT_BRT =0x%x\n",
1864+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT));
1865+ DPRINTK_ISPPREV("###PRV CSUP =0x%x\n",
1866+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP));
1867+ DPRINTK_ISPPREV("###PRV SETUP_YC =0x%x\n",
1868+ isp_reg_readl(OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC));
1869+}
1870+EXPORT_SYMBOL_GPL(isppreview_print_status);
1871+
1872+/**
1873+ * isp_preview_init - Module Initialization.
1874+ **/
1875+int __init isp_preview_init(void)
1876+{
1877+ int i = 0;
1878+
1879+ prev_config_params = kmalloc(sizeof(*prev_config_params), GFP_KERNEL);
1880+ if (!prev_config_params) {
1881+ printk(KERN_ERR "Can't get memory for isp_preview params!\n");
1882+ return -ENOMEM;
1883+ }
1884+ params = prev_config_params;
1885+
1886+ ispprev_obj.prev_inuse = 0;
1887+ mutex_init(&ispprev_obj.ispprev_mutex);
1888+
1889+ /* Init values */
1890+ ispprev_obj.sph = 2;
1891+ ispprev_obj.slv = 0;
1892+ ispprev_obj.color = V4L2_COLORFX_NONE;
1893+ ispprev_obj.contrast = ISPPRV_CONTRAST_DEF;
1894+ params->contrast = ISPPRV_CONTRAST_DEF;
1895+ ispprev_obj.brightness = ISPPRV_BRIGHT_DEF;
1896+ params->brightness = ISPPRV_BRIGHT_DEF;
1897+ params->average = NO_AVE;
1898+ params->lens_shading_shift = 0;
1899+ params->pix_fmt = YCPOS_YCrYCb;
1900+ params->cfa.cfafmt = CFAFMT_BAYER;
1901+ params->cfa.cfa_table = cfa_coef_table;
1902+ params->cfa.cfa_gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1903+ params->cfa.cfa_gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1904+ params->csup.gain = FLR_CSUP_GAIN;
1905+ params->csup.thres = FLR_CSUP_THRES;
1906+ params->csup.hypf_en = 0;
1907+ params->ytable = luma_enhance_table;
1908+ params->nf.spread = FLR_NF_STRGTH;
1909+ memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1910+ params->dcor.couplet_mode_en = 1;
1911+ for (i = 0; i < 4; i++)
1912+ params->dcor.detect_correct[i] = 0xE;
1913+ params->gtable.bluetable = bluegamma_table;
1914+ params->gtable.greentable = greengamma_table;
1915+ params->gtable.redtable = redgamma_table;
1916+ params->wbal.dgain = FLR_WBAL_DGAIN;
1917+ if (omap_rev() > OMAP3430_REV_ES1_0) {
1918+ params->wbal.coef0 = FLR_WBAL_COEF0_ES1;
1919+ params->wbal.coef1 = FLR_WBAL_COEF1_ES1;
1920+ params->wbal.coef2 = FLR_WBAL_COEF2_ES1;
1921+ params->wbal.coef3 = FLR_WBAL_COEF3_ES1;
1922+ } else {
1923+ params->wbal.coef0 = FLR_WBAL_COEF0;
1924+ params->wbal.coef1 = FLR_WBAL_COEF1;
1925+ params->wbal.coef2 = FLR_WBAL_COEF2;
1926+ params->wbal.coef3 = FLR_WBAL_COEF3;
1927+ }
1928+ params->blk_adj.red = FLR_BLKADJ_RED;
1929+ params->blk_adj.green = FLR_BLKADJ_GREEN;
1930+ params->blk_adj.blue = FLR_BLKADJ_BLUE;
1931+ params->rgb2rgb = flr_rgb2rgb;
1932+ params->rgb2ycbcr = flr_prev_csc[ispprev_obj.color];
1933+
1934+ params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER;
1935+ params->features &= ~(PREV_AVERAGER | PREV_INVERSE_ALAW |
1936+ PREV_HORZ_MEDIAN_FILTER |
1937+ PREV_GAMMA_BYPASS |
1938+ PREV_DARK_FRAME_SUBTRACT |
1939+ PREV_LENS_SHADING |
1940+ PREV_DARK_FRAME_CAPTURE |
1941+ PREV_CHROMA_SUPPRESS |
1942+ PREV_LUMA_ENHANCE);
1943+ return 0;
1944+}
1945+
1946+/**
1947+ * isp_preview_cleanup - Module Cleanup.
1948+ **/
1949+void isp_preview_cleanup(void)
1950+{
1951+ kfree(prev_config_params);
1952+}
1953diff --git a/drivers/media/video/isp/isppreview.h b/drivers/media/video/isp/isppreview.h
1954new file mode 100644
1955index 0000000..e88c329
1956--- /dev/null
1957+++ b/drivers/media/video/isp/isppreview.h
1958@@ -0,0 +1,354 @@
1959+/*
1960+ * isppreview.h
1961+ *
1962+ * Driver header file for Preview module in TI's OMAP3 Camera ISP
1963+ *
1964+ * Copyright (C) 2009 Texas Instruments, Inc.
1965+ *
1966+ * Contributors:
1967+ * Senthilvadivu Guruswamy <svadivu@ti.com>
1968+ * Pallavi Kulkarni <p-kulkarni@ti.com>
1969+ * Sergio Aguirre <saaguirre@ti.com>
1970+ *
1971+ * This package is free software; you can redistribute it and/or modify
1972+ * it under the terms of the GNU General Public License version 2 as
1973+ * published by the Free Software Foundation.
1974+ *
1975+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1976+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1977+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1978+ */
1979+
1980+#ifndef OMAP_ISP_PREVIEW_H
1981+#define OMAP_ISP_PREVIEW_H
1982+
1983+#include <mach/isp_user.h>
1984+/* Isp query control structure */
1985+
1986+#define ISPPRV_BRIGHT_STEP 0x1
1987+#define ISPPRV_BRIGHT_DEF 0x0
1988+#define ISPPRV_BRIGHT_LOW 0x0
1989+#define ISPPRV_BRIGHT_HIGH 0xF
1990+#define ISPPRV_BRIGHT_UNITS 0x7
1991+
1992+#define ISPPRV_CONTRAST_STEP 0x1
1993+#define ISPPRV_CONTRAST_DEF 0x4
1994+#define ISPPRV_CONTRAST_LOW 0x0
1995+#define ISPPRV_CONTRAST_HIGH 0xF
1996+#define ISPPRV_CONTRAST_UNITS 0x4
1997+
1998+#define NO_AVE 0x0
1999+#define AVE_2_PIX 0x1
2000+#define AVE_4_PIX 0x2
2001+#define AVE_8_PIX 0x3
2002+#define AVE_ODD_PIXEL_DIST (1 << 4) /* For Bayer Sensors */
2003+#define AVE_EVEN_PIXEL_DIST (1 << 2)
2004+
2005+#define WB_GAIN_MAX 4
2006+
2007+/* Features list */
2008+#define PREV_AVERAGER (1 << 0)
2009+#define PREV_INVERSE_ALAW (1 << 1)
2010+#define PREV_HORZ_MEDIAN_FILTER (1 << 2)
2011+#define PREV_NOISE_FILTER (1 << 3)
2012+#define PREV_CFA (1 << 4)
2013+#define PREV_GAMMA_BYPASS (1 << 5)
2014+#define PREV_LUMA_ENHANCE (1 << 6)
2015+#define PREV_CHROMA_SUPPRESS (1 << 7)
2016+#define PREV_DARK_FRAME_SUBTRACT (1 << 8)
2017+#define PREV_LENS_SHADING (1 << 9)
2018+#define PREV_DARK_FRAME_CAPTURE (1 << 10)
2019+#define PREV_DEFECT_COR (1 << 11)
2020+
2021+
2022+#define ISP_NF_TABLE_SIZE (1 << 10)
2023+
2024+#define ISP_GAMMA_TABLE_SIZE (1 << 10)
2025+
2026+/* Table addresses */
2027+#define ISPPRV_TBL_ADDR_RED_G_START 0x00
2028+#define ISPPRV_TBL_ADDR_BLUE_G_START 0x800
2029+#define ISPPRV_TBL_ADDR_GREEN_G_START 0x400
2030+
2031+/*
2032+ *Enumeration Constants for input and output format
2033+ */
2034+enum preview_input {
2035+ PRV_RAW_CCDC,
2036+ PRV_RAW_MEM,
2037+ PRV_RGBBAYERCFA,
2038+ PRV_COMPCFA,
2039+ PRV_CCDC_DRKF,
2040+ PRV_OTHERS
2041+};
2042+enum preview_output {
2043+ PREVIEW_RSZ,
2044+ PREVIEW_MEM
2045+};
2046+/*
2047+ * Configure byte layout of YUV image
2048+ */
2049+enum preview_ycpos_mode {
2050+ YCPOS_YCrYCb = 0,
2051+ YCPOS_YCbYCr = 1,
2052+ YCPOS_CbYCrY = 2,
2053+ YCPOS_CrYCbY = 3
2054+};
2055+
2056+/**
2057+ * struct ispprev_gtable - Structure for Gamma Correction.
2058+ * @redtable: Pointer to the red gamma table.
2059+ * @greentable: Pointer to the green gamma table.
2060+ * @bluetable: Pointer to the blue gamma table.
2061+ */
2062+struct ispprev_gtable {
2063+ u32 *redtable;
2064+ u32 *greentable;
2065+ u32 *bluetable;
2066+};
2067+
2068+/**
2069+ * struct prev_white_balance - Structure for White Balance 2.
2070+ * @wb_dgain: White balance common gain.
2071+ * @wb_gain: Individual color gains.
2072+ * @wb_coefmatrix: Coefficient matrix
2073+ */
2074+struct prev_white_balance {
2075+ u16 wb_dgain; /* white balance common gain */
2076+ u8 wb_gain[WB_GAIN_MAX]; /* individual color gains */
2077+ u8 wb_coefmatrix[WB_GAIN_MAX][WB_GAIN_MAX];
2078+};
2079+
2080+/**
2081+ * struct prev_size_params - Structure for size parameters.
2082+ * @hstart: Starting pixel.
2083+ * @vstart: Starting line.
2084+ * @hsize: Width of input image.
2085+ * @vsize: Height of input image.
2086+ * @pixsize: Pixel size of the image in terms of bits.
2087+ * @in_pitch: Line offset of input image.
2088+ * @out_pitch: Line offset of output image.
2089+ */
2090+struct prev_size_params {
2091+ unsigned int hstart;
2092+ unsigned int vstart;
2093+ unsigned int hsize;
2094+ unsigned int vsize;
2095+ unsigned char pixsize;
2096+ unsigned short in_pitch;
2097+ unsigned short out_pitch;
2098+};
2099+
2100+/**
2101+ * struct prev_rgb2ycbcr_coeffs - Structure RGB2YCbCr parameters.
2102+ * @coeff: Color conversion gains in 3x3 matrix.
2103+ * @offset: Color conversion offsets.
2104+ */
2105+struct prev_rgb2ycbcr_coeffs {
2106+ short coeff[RGB_MAX][RGB_MAX];
2107+ short offset[RGB_MAX];
2108+};
2109+
2110+/**
2111+ * struct prev_darkfrm_params - Structure for Dark frame suppression.
2112+ * @addr: Memory start address.
2113+ * @offset: Line offset.
2114+ */
2115+struct prev_darkfrm_params {
2116+ u32 addr;
2117+ u32 offset;
2118+ };
2119+
2120+/**
2121+ * struct prev_params - Structure for all configuration
2122+ * @features: Set of features enabled.
2123+ * @pix_fmt: Output pixel format.
2124+ * @cfa: CFA coefficients.
2125+ * @csup: Chroma suppression coefficients.
2126+ * @ytable: Pointer to Luma enhancement coefficients.
2127+ * @nf: Noise filter coefficients.
2128+ * @dcor: Noise filter coefficients.
2129+ * @gtable: Gamma coefficients.
2130+ * @wbal: White Balance parameters.
2131+ * @blk_adj: Black adjustment parameters.
2132+ * @rgb2rgb: RGB blending parameters.
2133+ * @rgb2ycbcr: RGB to ycbcr parameters.
2134+ * @hmf_params: Horizontal median filter.
2135+ * @size_params: Size parameters.
2136+ * @drkf_params: Darkframe parameters.
2137+ * @lens_shading_shift:
2138+ * @average: Downsampling rate for averager.
2139+ * @contrast: Contrast.
2140+ * @brightness: Brightness.
2141+ */
2142+struct prev_params {
2143+ u16 features;
2144+ enum preview_ycpos_mode pix_fmt;
2145+ struct ispprev_cfa cfa;
2146+ struct ispprev_csup csup;
2147+ u32 *ytable;
2148+ struct ispprev_nf nf;
2149+ struct ispprev_dcor dcor;
2150+ struct ispprev_gtable gtable;
2151+ struct ispprev_wbal wbal;
2152+ struct ispprev_blkadj blk_adj;
2153+ struct ispprev_rgbtorgb rgb2rgb;
2154+ struct ispprev_csc rgb2ycbcr;
2155+ struct ispprev_hmed hmf_params;
2156+ struct prev_size_params size_params;
2157+ struct prev_darkfrm_params drkf_params;
2158+ u8 lens_shading_shift;
2159+ u8 average;
2160+ u8 contrast;
2161+ u8 brightness;
2162+};
2163+
2164+/**
2165+ * struct isptables_update - Structure for Table Configuration.
2166+ * @update: Specifies which tables should be updated.
2167+ * @flag: Specifies which tables should be enabled.
2168+ * @prev_nf: Pointer to structure for Noise Filter
2169+ * @lsc: Pointer to LSC gain table. (currently not used)
2170+ * @red_gamma: Pointer to red gamma correction table.
2171+ * @green_gamma: Pointer to green gamma correction table.
2172+ * @blue_gamma: Pointer to blue gamma correction table.
2173+ */
2174+struct isptables_update {
2175+ u16 update;
2176+ u16 flag;
2177+ struct ispprev_nf *prev_nf;
2178+ u32 *lsc;
2179+ u32 *red_gamma;
2180+ u32 *green_gamma;
2181+ u32 *blue_gamma;
2182+};
2183+
2184+void isppreview_config_shadow_registers(void);
2185+
2186+int isppreview_request(void);
2187+
2188+int isppreview_free(void);
2189+
2190+int isppreview_config_datapath(enum preview_input input,
2191+ enum preview_output output);
2192+
2193+void isppreview_config_ycpos(enum preview_ycpos_mode mode);
2194+
2195+void isppreview_config_averager(u8 average);
2196+
2197+void isppreview_enable_invalaw(u8 enable);
2198+
2199+void isppreview_enable_drkframe(u8 enable);
2200+
2201+void isppreview_enable_shadcomp(u8 enable);
2202+
2203+void isppreview_config_drkf_shadcomp(u8 scomp_shtval);
2204+
2205+void isppreview_enable_gammabypass(u8 enable);
2206+
2207+void isppreview_enable_hmed(u8 enable);
2208+
2209+void isppreview_config_hmed(struct ispprev_hmed);
2210+
2211+void isppreview_enable_noisefilter(u8 enable);
2212+
2213+void isppreview_config_noisefilter(struct ispprev_nf prev_nf);
2214+
2215+void isppreview_enable_dcor(u8 enable);
2216+
2217+void isppreview_config_dcor(struct ispprev_dcor prev_dcor);
2218+
2219+
2220+void isppreview_config_cfa(struct ispprev_cfa);
2221+
2222+void isppreview_config_gammacorrn(struct ispprev_gtable);
2223+
2224+void isppreview_config_chroma_suppression(struct ispprev_csup csup);
2225+
2226+void isppreview_enable_cfa(u8 enable);
2227+
2228+void isppreview_config_luma_enhancement(u32 *ytable);
2229+
2230+void isppreview_enable_luma_enhancement(u8 enable);
2231+
2232+void isppreview_enable_chroma_suppression(u8 enable);
2233+
2234+void isppreview_config_whitebalance(struct ispprev_wbal);
2235+
2236+void isppreview_config_blkadj(struct ispprev_blkadj);
2237+
2238+void isppreview_config_rgb_blending(struct ispprev_rgbtorgb);
2239+
2240+void isppreview_config_rgb_to_ycbcr(struct ispprev_csc);
2241+
2242+void isppreview_update_contrast(u8 *contrast);
2243+
2244+void isppreview_query_contrast(u8 *contrast);
2245+
2246+void isppreview_config_contrast(u8 contrast);
2247+
2248+void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast);
2249+
2250+void isppreview_update_brightness(u8 *brightness);
2251+
2252+void isppreview_config_brightness(u8 brightness);
2253+
2254+void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness);
2255+
2256+void isppreview_set_color(u8 *mode);
2257+
2258+void isppreview_get_color(u8 *mode);
2259+
2260+void isppreview_query_brightness(u8 *brightness);
2261+
2262+void isppreview_config_yc_range(struct ispprev_yclimit yclimit);
2263+
2264+int isppreview_try_size(u32 input_w, u32 input_h, u32 *output_w,
2265+ u32 *output_h);
2266+
2267+int isppreview_config_size(u32 input_w, u32 input_h, u32 output_w,
2268+ u32 output_h);
2269+
2270+int isppreview_config_inlineoffset(u32 offset);
2271+
2272+int isppreview_set_inaddr(u32 addr);
2273+
2274+int isppreview_config_outlineoffset(u32 offset);
2275+
2276+int isppreview_set_outaddr(u32 addr);
2277+
2278+int isppreview_config_darklineoffset(u32 offset);
2279+
2280+int isppreview_set_darkaddr(u32 addr);
2281+
2282+void isppreview_enable(int enable);
2283+
2284+void isppreview_suspend(void);
2285+
2286+void isppreview_resume(void);
2287+
2288+int isppreview_busy(void);
2289+
2290+struct prev_params *isppreview_get_config(void);
2291+
2292+void isppreview_print_status(void);
2293+
2294+#ifndef CONFIG_ARCH_OMAP3410
2295+void isppreview_save_context(void);
2296+#else
2297+static inline void isppreview_save_context(void) {}
2298+#endif
2299+
2300+#ifndef CONFIG_ARCH_OMAP3410
2301+void isppreview_restore_context(void);
2302+#else
2303+static inline void isppreview_restore_context(void) {}
2304+#endif
2305+
2306+int omap34xx_isp_preview_config(void *userspace_add);
2307+
2308+int omap34xx_isp_tables_update(struct isptables_update *isptables_struct);
2309+
2310+void isppreview_set_skip(u32 h, u32 v);
2311+
2312+#endif/* OMAP_ISP_PREVIEW_H */
2313diff --git a/drivers/media/video/isp/ispresizer.c b/drivers/media/video/isp/ispresizer.c
2314new file mode 100644
2315index 0000000..f78ddb3
2316--- /dev/null
2317+++ b/drivers/media/video/isp/ispresizer.c
2318@@ -0,0 +1,928 @@
2319+/*
2320+ * ispresizer.c
2321+ *
2322+ * Driver Library for Resizer module in TI's OMAP3 Camera ISP
2323+ *
2324+ * Copyright (C)2009 Texas Instruments, Inc.
2325+ *
2326+ * Contributors:
2327+ * Sameer Venkatraman <sameerv@ti.com>
2328+ * Mohit Jalori
2329+ * Sergio Aguirre <saaguirre@ti.com>
2330+ *
2331+ * This package is free software; you can redistribute it and/or modify
2332+ * it under the terms of the GNU General Public License version 2 as
2333+ * published by the Free Software Foundation.
2334+ *
2335+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2336+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2337+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2338+ */
2339+
2340+#include <linux/module.h>
2341+
2342+#include "isp.h"
2343+#include "ispreg.h"
2344+#include "ispresizer.h"
2345+
2346+/* Default configuration of resizer,filter coefficients,yenh for camera isp */
2347+static struct isprsz_yenh ispreszdefaultyenh = {0, 0, 0, 0};
2348+static struct isprsz_coef ispreszdefcoef = {
2349+ {
2350+ 0x0027, 0x00B2, 0x00B2, 0x0027,
2351+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2352+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2353+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2354+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2355+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2356+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2357+ 0x0027, 0x00B2, 0x0027, 0x00B2,
2358+ },
2359+ {
2360+ 0x0000, 0x0100, 0x0000, 0x0000,
2361+ 0x03FA, 0x00F6, 0x0010, 0x0000,
2362+ 0x03F9, 0x00DB, 0x002C, 0x0000,
2363+ 0x03FB, 0x00B3, 0x0053, 0x03FF,
2364+ 0x03FD, 0x0082, 0x0084, 0x03FD,
2365+ 0x03FF, 0x0053, 0x00B3, 0x03FB,
2366+ 0x0000, 0x002C, 0x00DB, 0x03F9,
2367+ 0x0000, 0x0010, 0x00F6, 0x03FA
2368+ },
2369+ {
2370+ 0x0004, 0x0023, 0x0023, 0x005A,
2371+ 0x005A, 0x0058, 0x0058, 0x0004,
2372+ 0x0023, 0x0023, 0x005A, 0x005A,
2373+ 0x0058, 0x0058, 0x0004, 0x0023,
2374+ 0x0023, 0x005A, 0x005A, 0x0058,
2375+ 0x0058, 0x0004, 0x0023, 0x0023,
2376+ 0x005A, 0x005A, 0x0058, 0x0058
2377+ },
2378+ {
2379+ 0x0004, 0x0023, 0x005A, 0x0058,
2380+ 0x0023, 0x0004, 0x0000, 0x0002,
2381+ 0x0018, 0x004d, 0x0060, 0x0031,
2382+ 0x0008, 0x0000, 0x0001, 0x000f,
2383+ 0x003f, 0x0062, 0x003f, 0x000f,
2384+ 0x0001, 0x0000, 0x0008, 0x0031,
2385+ 0x0060, 0x004d, 0x0018, 0x0002
2386+ }
2387+};
2388+
2389+/**
2390+ * struct isp_res - Structure for the resizer module to store its information.
2391+ * @res_inuse: Indicates if resizer module has been reserved. 1 - Reserved,
2392+ * 0 - Freed.
2393+ * @h_startphase: Horizontal starting phase.
2394+ * @v_startphase: Vertical starting phase.
2395+ * @h_resz: Horizontal resizing value.
2396+ * @v_resz: Vertical resizing value.
2397+ * @outputwidth: Output Image Width in pixels.
2398+ * @outputheight: Output Image Height in pixels.
2399+ * @inputwidth: Input Image Width in pixels.
2400+ * @inputheight: Input Image Height in pixels.
2401+ * @algo: Algorithm select. 0 - Disable, 1 - [-1 2 -1]/2 high-pass filter,
2402+ * 2 - [-1 -2 6 -2 -1]/4 high-pass filter.
2403+ * @ipht_crop: Vertical start line for cropping.
2404+ * @ipwd_crop: Horizontal start pixel for cropping.
2405+ * @cropwidth: Crop Width.
2406+ * @cropheight: Crop Height.
2407+ * @resinput: Resizer input.
2408+ * @coeflist: Register configuration for Resizer.
2409+ * @ispres_mutex: Mutex for isp resizer.
2410+ */
2411+static struct isp_res {
2412+ int pm_state;
2413+ u8 res_inuse;
2414+ u8 h_startphase;
2415+ u8 v_startphase;
2416+ u16 h_resz;
2417+ u16 v_resz;
2418+ u32 outputwidth;
2419+ u32 outputheight;
2420+ u32 inputwidth;
2421+ u32 inputheight;
2422+ u8 algo;
2423+ u32 ipht_crop;
2424+ u32 ipwd_crop;
2425+ u32 cropwidth;
2426+ u32 cropheight;
2427+ dma_addr_t tmp_buf;
2428+ enum ispresizer_input resinput;
2429+ struct isprsz_coef coeflist;
2430+ struct mutex ispres_mutex; /* For checking/modifying res_inuse */
2431+} ispres_obj;
2432+
2433+/* Structure for saving/restoring resizer module registers */
2434+static struct isp_reg isprsz_reg_list[] = {
2435+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, 0x0000},
2436+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE, 0x0000},
2437+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START, 0x0000},
2438+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE, 0x0000},
2439+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD, 0x0000},
2440+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF, 0x0000},
2441+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD, 0x0000},
2442+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF, 0x0000},
2443+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT10, 0x0000},
2444+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT32, 0x0000},
2445+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT54, 0x0000},
2446+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT76, 0x0000},
2447+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT98, 0x0000},
2448+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1110, 0x0000},
2449+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1312, 0x0000},
2450+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1514, 0x0000},
2451+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1716, 0x0000},
2452+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT1918, 0x0000},
2453+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2120, 0x0000},
2454+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2322, 0x0000},
2455+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2524, 0x0000},
2456+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2726, 0x0000},
2457+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT2928, 0x0000},
2458+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_HFILT3130, 0x0000},
2459+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT10, 0x0000},
2460+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT32, 0x0000},
2461+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT54, 0x0000},
2462+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT76, 0x0000},
2463+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT98, 0x0000},
2464+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1110, 0x0000},
2465+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1312, 0x0000},
2466+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1514, 0x0000},
2467+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1716, 0x0000},
2468+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT1918, 0x0000},
2469+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2120, 0x0000},
2470+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2322, 0x0000},
2471+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2524, 0x0000},
2472+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2726, 0x0000},
2473+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT2928, 0x0000},
2474+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_VFILT3130, 0x0000},
2475+ {OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH, 0x0000},
2476+ {0, ISP_TOK_TERM, 0x0000}
2477+};
2478+
2479+/**
2480+ * ispresizer_config_shadow_registers - Configure shadow registers.
2481+ **/
2482+void ispresizer_config_shadow_registers()
2483+{
2484+ return;
2485+}
2486+EXPORT_SYMBOL(ispresizer_config_shadow_registers);
2487+
2488+/**
2489+ * ispresizer_trycrop - Validate crop dimensions.
2490+ * @left: Left distance to start position of crop.
2491+ * @top: Top distance to start position of crop.
2492+ * @width: Width of input image.
2493+ * @height: Height of input image.
2494+ * @ow: Width of output image.
2495+ * @oh: Height of output image.
2496+ **/
2497+void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
2498+ u32 oh)
2499+{
2500+ ispres_obj.cropwidth = width + 6;
2501+ ispres_obj.cropheight = height + 6;
2502+ ispresizer_try_size(&ispres_obj.cropwidth, &ispres_obj.cropheight, &ow,
2503+ &oh);
2504+ ispres_obj.ipht_crop = top;
2505+ ispres_obj.ipwd_crop = left;
2506+}
2507+EXPORT_SYMBOL(ispresizer_trycrop);
2508+
2509+/**
2510+ * ispresizer_applycrop - Apply crop to input image.
2511+ **/
2512+void ispresizer_applycrop(void)
2513+{
2514+ ispresizer_config_size(ispres_obj.cropwidth, ispres_obj.cropheight,
2515+ ispres_obj.outputwidth,
2516+ ispres_obj.outputheight);
2517+ return;
2518+}
2519+EXPORT_SYMBOL(ispresizer_applycrop);
2520+
2521+/**
2522+ * ispresizer_request - Reserves the Resizer module.
2523+ *
2524+ * Allows only one user at a time.
2525+ *
2526+ * Returns 0 if successful, or -EBUSY if resizer module was already requested.
2527+ **/
2528+int ispresizer_request()
2529+{
2530+ mutex_lock(&ispres_obj.ispres_mutex);
2531+ if (!ispres_obj.res_inuse) {
2532+ ispres_obj.res_inuse = 1;
2533+ mutex_unlock(&ispres_obj.ispres_mutex);
2534+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL) |
2535+ ISPCTRL_SBL_WR0_RAM_EN |
2536+ ISPCTRL_RSZ_CLK_EN,
2537+ OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
2538+ return 0;
2539+ } else {
2540+ mutex_unlock(&ispres_obj.ispres_mutex);
2541+ printk(KERN_ERR "ISP_ERR : Resizer Module Busy\n");
2542+ return -EBUSY;
2543+ }
2544+}
2545+EXPORT_SYMBOL(ispresizer_request);
2546+
2547+/**
2548+ * ispresizer_free - Makes Resizer module free.
2549+ *
2550+ * Returns 0 if successful, or -EINVAL if resizer module was already freed.
2551+ **/
2552+int ispresizer_free()
2553+{
2554+ mutex_lock(&ispres_obj.ispres_mutex);
2555+ if (ispres_obj.res_inuse) {
2556+ ispres_obj.res_inuse = 0;
2557+ mutex_unlock(&ispres_obj.ispres_mutex);
2558+ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
2559+ ~(ISPCTRL_RSZ_CLK_EN | ISPCTRL_SBL_WR0_RAM_EN));
2560+ return 0;
2561+ } else {
2562+ mutex_unlock(&ispres_obj.ispres_mutex);
2563+ DPRINTK_ISPRESZ("ISP_ERR : Resizer Module already freed\n");
2564+ return -EINVAL;
2565+ }
2566+}
2567+EXPORT_SYMBOL(ispresizer_free);
2568+
2569+/**
2570+ * ispresizer_config_datapath - Specifies which input to use in resizer module
2571+ * @input: Indicates the module that gives the image to resizer.
2572+ *
2573+ * Sets up the default resizer configuration according to the arguments.
2574+ *
2575+ * Returns 0 if successful, or -EINVAL if an unsupported input was requested.
2576+ **/
2577+int ispresizer_config_datapath(enum ispresizer_input input)
2578+{
2579+ u32 cnt = 0;
2580+ DPRINTK_ISPRESZ("ispresizer_config_datapath()+\n");
2581+ ispres_obj.resinput = input;
2582+ switch (input) {
2583+ case RSZ_OTFLY_YUV:
2584+ cnt &= ~ISPRSZ_CNT_INPTYP;
2585+ cnt &= ~ISPRSZ_CNT_INPSRC;
2586+ ispresizer_set_inaddr(0);
2587+ ispresizer_config_inlineoffset(0);
2588+ break;
2589+ case RSZ_MEM_YUV:
2590+ cnt |= ISPRSZ_CNT_INPSRC;
2591+ cnt &= ~ISPRSZ_CNT_INPTYP;
2592+ break;
2593+ case RSZ_MEM_COL8:
2594+ cnt |= ISPRSZ_CNT_INPSRC;
2595+ cnt |= ISPRSZ_CNT_INPTYP;
2596+ break;
2597+ default:
2598+ printk(KERN_ERR "ISP_ERR : Wrong Input\n");
2599+ return -EINVAL;
2600+ }
2601+ isp_reg_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, cnt);
2602+ ispresizer_config_ycpos(0);
2603+ ispresizer_config_filter_coef(&ispreszdefcoef);
2604+ ispresizer_enable_cbilin(0);
2605+ ispresizer_config_luma_enhance(&ispreszdefaultyenh);
2606+ DPRINTK_ISPRESZ("ispresizer_config_datapath()-\n");
2607+ return 0;
2608+}
2609+EXPORT_SYMBOL(ispresizer_config_datapath);
2610+
2611+/**
2612+ * ispresizer_try_size - Validates input and output images size.
2613+ * @input_w: input width for the resizer in number of pixels per line
2614+ * @input_h: input height for the resizer in number of lines
2615+ * @output_w: output width from the resizer in number of pixels per line
2616+ * resizer when writing to memory needs this to be multiple of 16.
2617+ * @output_h: output height for the resizer in number of lines, must be even.
2618+ *
2619+ * Calculates the horizontal and vertical resize ratio, number of pixels to
2620+ * be cropped in the resizer module and checks the validity of various
2621+ * parameters. Formula used for calculation is:-
2622+ *
2623+ * 8-phase 4-tap mode :-
2624+ * inputwidth = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
2625+ * inputheight = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
2626+ * endpahse for width = ((32 * sph + (ow - 1) * hrsz + 16) >> 5) % 8
2627+ * endphase for height = ((32 * sph + (oh - 1) * hrsz + 16) >> 5) % 8
2628+ *
2629+ * 4-phase 7-tap mode :-
2630+ * inputwidth = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
2631+ * inputheight = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
2632+ * endpahse for width = ((64 * sph + (ow - 1) * hrsz + 32) >> 6) % 4
2633+ * endphase for height = ((64 * sph + (oh - 1) * hrsz + 32) >> 6) % 4
2634+ *
2635+ * Where:
2636+ * sph = Start phase horizontal
2637+ * spv = Start phase vertical
2638+ * ow = Output width
2639+ * oh = Output height
2640+ * hrsz = Horizontal resize value
2641+ * vrsz = Vertical resize value
2642+ *
2643+ * Fills up the output/input widht/height, horizontal/vertical resize ratio,
2644+ * horizontal/vertical crop variables in the isp_res structure.
2645+ **/
2646+int ispresizer_try_size(u32 *input_width, u32 *input_height, u32 *output_w,
2647+ u32 *output_h)
2648+{
2649+ u32 rsz, rsz_7, rsz_4;
2650+ u32 sph;
2651+ u32 input_w, input_h;
2652+ int max_in_otf, max_out_7tap;
2653+
2654+ input_w = *input_width;
2655+ input_h = *input_height;
2656+
2657+ if (input_w < 32 || input_h < 32) {
2658+ DPRINTK_ISPCCDC("ISP_ERR: RESIZER cannot handle input width"
2659+ " less than 32 pixels or height less than"
2660+ " 32\n");
2661+ return -EINVAL;
2662+ }
2663+ input_w -= 6;
2664+ input_h -= 6;
2665+
2666+ if (input_h > MAX_IN_HEIGHT)
2667+ return -EINVAL;
2668+
2669+ if (*output_w < 16)
2670+ *output_w = 16;
2671+
2672+ if (*output_h < 2)
2673+ *output_h = 2;
2674+
2675+ if (omap_rev() == OMAP3430_REV_ES1_0) {
2676+ max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE;
2677+ max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH;
2678+ } else {
2679+ max_in_otf = MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
2680+ max_out_7tap = MAX_7TAP_VRSZ_OUTWIDTH_ES2;
2681+ }
2682+
2683+ if (ispres_obj.resinput == RSZ_OTFLY_YUV) {
2684+ if (input_w > max_in_otf)
2685+ return -EINVAL;
2686+ } else {
2687+ if (input_w > MAX_IN_WIDTH_MEMORY_MODE)
2688+ return -EINVAL;
2689+ }
2690+
2691+ *output_h &= 0xfffffffe;
2692+ sph = DEFAULTSTPHASE;
2693+
2694+ rsz_7 = ((input_h - 7) * 256) / (*output_h - 1);
2695+ rsz_4 = ((input_h - 4) * 256) / (*output_h - 1);
2696+
2697+ rsz = (input_h * 256) / *output_h;
2698+
2699+ if (rsz <= MID_RESIZE_VALUE) {
2700+ rsz = rsz_4;
2701+ if (rsz < MINIMUM_RESIZE_VALUE) {
2702+ rsz = MINIMUM_RESIZE_VALUE;
2703+ *output_h = (((input_h - 4) * 256) / rsz) + 1;
2704+ printk(KERN_INFO "%s: using output_h %d instead\n",
2705+ __func__, *output_h);
2706+ }
2707+ } else {
2708+ rsz = rsz_7;
2709+ if (*output_w > max_out_7tap)
2710+ *output_w = max_out_7tap;
2711+ if (rsz > MAXIMUM_RESIZE_VALUE) {
2712+ rsz = MAXIMUM_RESIZE_VALUE;
2713+ *output_h = (((input_h - 7) * 256) / rsz) + 1;
2714+ printk(KERN_INFO "%s: using output_h %d instead\n",
2715+ __func__, *output_h);
2716+ }
2717+ }
2718+
2719+ if (rsz > MID_RESIZE_VALUE) {
2720+ input_h =
2721+ (((64 * sph) + ((*output_h - 1) * rsz) + 32) / 256) + 7;
2722+ } else {
2723+ input_h =
2724+ (((32 * sph) + ((*output_h - 1) * rsz) + 16) / 256) + 4;
2725+ }
2726+
2727+ ispres_obj.outputheight = *output_h;
2728+ ispres_obj.v_resz = rsz;
2729+ ispres_obj.inputheight = input_h;
2730+ ispres_obj.ipht_crop = DEFAULTSTPIXEL;
2731+ ispres_obj.v_startphase = sph;
2732+
2733+ *output_w &= 0xfffffff0;
2734+ sph = DEFAULTSTPHASE;
2735+
2736+ rsz_7 = ((input_w - 7) * 256) / (*output_w - 1);
2737+ rsz_4 = ((input_w - 4) * 256) / (*output_w - 1);
2738+
2739+ rsz = (input_w * 256) / *output_w;
2740+ if (rsz > MID_RESIZE_VALUE) {
2741+ rsz = rsz_7;
2742+ if (rsz > MAXIMUM_RESIZE_VALUE) {
2743+ rsz = MAXIMUM_RESIZE_VALUE;
2744+ *output_w = (((input_w - 7) * 256) / rsz) + 1;
2745+ *output_w = (*output_w + 0xf) & 0xfffffff0;
2746+ printk(KERN_INFO "%s: using output_w %d instead\n",
2747+ __func__, *output_w);
2748+ }
2749+ } else {
2750+ rsz = rsz_4;
2751+ if (rsz < MINIMUM_RESIZE_VALUE) {
2752+ rsz = MINIMUM_RESIZE_VALUE;
2753+ *output_w = (((input_w - 4) * 256) / rsz) + 1;
2754+ *output_w = (*output_w + 0xf) & 0xfffffff0;
2755+ printk(KERN_INFO "%s: using output_w %d instead\n",
2756+ __func__, *output_w);
2757+ }
2758+ }
2759+
2760+ /* Recalculate input based on TRM equations */
2761+ if (rsz > MID_RESIZE_VALUE) {
2762+ input_w =
2763+ (((64 * sph) + ((*output_w - 1) * rsz) + 32) / 256) + 7;
2764+ } else {
2765+ input_w =
2766+ (((32 * sph) + ((*output_w - 1) * rsz) + 16) / 256) + 7;
2767+ }
2768+
2769+ ispres_obj.outputwidth = *output_w;
2770+ ispres_obj.h_resz = rsz;
2771+ ispres_obj.inputwidth = input_w;
2772+ ispres_obj.ipwd_crop = DEFAULTSTPIXEL;
2773+ ispres_obj.h_startphase = sph;
2774+
2775+ *input_height = input_h;
2776+ *input_width = input_w;
2777+ return 0;
2778+}
2779+EXPORT_SYMBOL(ispresizer_try_size);
2780+
2781+/**
2782+ * ispresizer_config_size - Configures input and output image size.
2783+ * @input_w: input width for the resizer in number of pixels per line.
2784+ * @input_h: input height for the resizer in number of lines.
2785+ * @output_w: output width from the resizer in number of pixels per line.
2786+ * @output_h: output height for the resizer in number of lines.
2787+ *
2788+ * Configures the appropriate values stored in the isp_res structure in the
2789+ * resizer registers.
2790+ *
2791+ * Returns 0 if successful, or -EINVAL if passed values haven't been verified
2792+ * with ispresizer_try_size() previously.
2793+ **/
2794+int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
2795+ u32 output_h)
2796+{
2797+ int i, j;
2798+ u32 res;
2799+ DPRINTK_ISPRESZ("ispresizer_config_size()+, input_w = %d,input_h ="
2800+ " %d, output_w = %d, output_h"
2801+ " = %d,hresz = %d,vresz = %d,"
2802+ " hcrop = %d, vcrop = %d,"
2803+ " hstph = %d, vstph = %d\n",
2804+ ispres_obj.inputwidth,
2805+ ispres_obj.inputheight,
2806+ ispres_obj.outputwidth,
2807+ ispres_obj.outputheight,
2808+ ispres_obj.h_resz,
2809+ ispres_obj.v_resz,
2810+ ispres_obj.ipwd_crop,
2811+ ispres_obj.ipht_crop,
2812+ ispres_obj.h_startphase,
2813+ ispres_obj.v_startphase);
2814+ if ((output_w != ispres_obj.outputwidth)
2815+ || (output_h != ispres_obj.outputheight)) {
2816+ printk(KERN_ERR "Output parameters passed do not match the"
2817+ " values calculated by the"
2818+ " trysize passed w %d, h %d"
2819+ " \n", output_w , output_h);
2820+ return -EINVAL;
2821+ }
2822+
2823+ /* Set Resizer input address and offset adderss */
2824+ ispresizer_config_inlineoffset(isp_reg_readl(OMAP3_ISP_IOMEM_PREV,
2825+ ISPPRV_WADD_OFFSET));
2826+
2827+ res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
2828+ ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
2829+ isp_reg_writel(res |
2830+ (ispres_obj.h_startphase << ISPRSZ_CNT_HSTPH_SHIFT) |
2831+ (ispres_obj.v_startphase << ISPRSZ_CNT_VSTPH_SHIFT),
2832+ OMAP3_ISP_IOMEM_RESZ,
2833+ ISPRSZ_CNT);
2834+ /* Set start address for cropping */
2835+ isp_reg_writel(ispres_obj.tmp_buf + 2 *
2836+ (ispres_obj.ipht_crop * ispres_obj.inputwidth +
2837+ (ispres_obj.ipwd_crop & ~15)),
2838+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
2839+
2840+ isp_reg_writel(
2841+ ((ispres_obj.ipwd_crop & 15) << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
2842+ (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
2843+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
2844+
2845+ isp_reg_writel((0x00 << ISPRSZ_IN_START_HORZ_ST_SHIFT) |
2846+ (0x00 << ISPRSZ_IN_START_VERT_ST_SHIFT),
2847+ OMAP3_ISP_IOMEM_RESZ,
2848+ ISPRSZ_IN_START);
2849+
2850+ isp_reg_writel((ispres_obj.inputwidth << ISPRSZ_IN_SIZE_HORZ_SHIFT) |
2851+ (ispres_obj.inputheight <<
2852+ ISPRSZ_IN_SIZE_VERT_SHIFT),
2853+ OMAP3_ISP_IOMEM_RESZ,
2854+ ISPRSZ_IN_SIZE);
2855+ if (!ispres_obj.algo) {
2856+ isp_reg_writel((output_w << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
2857+ (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
2858+ OMAP3_ISP_IOMEM_RESZ,
2859+ ISPRSZ_OUT_SIZE);
2860+ } else {
2861+ isp_reg_writel(((output_w - 4) << ISPRSZ_OUT_SIZE_HORZ_SHIFT) |
2862+ (output_h << ISPRSZ_OUT_SIZE_VERT_SHIFT),
2863+ OMAP3_ISP_IOMEM_RESZ,
2864+ ISPRSZ_OUT_SIZE);
2865+ }
2866+
2867+ res = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
2868+ ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
2869+ isp_reg_writel(res |
2870+ ((ispres_obj.h_resz - 1) << ISPRSZ_CNT_HRSZ_SHIFT) |
2871+ ((ispres_obj.v_resz - 1) << ISPRSZ_CNT_VRSZ_SHIFT),
2872+ OMAP3_ISP_IOMEM_RESZ,
2873+ ISPRSZ_CNT);
2874+ if (ispres_obj.h_resz <= MID_RESIZE_VALUE) {
2875+ j = 0;
2876+ for (i = 0; i < 16; i++) {
2877+ isp_reg_writel(
2878+ (ispres_obj.coeflist.h_filter_coef_4tap[j]
2879+ << ISPRSZ_HFILT10_COEF0_SHIFT) |
2880+ (ispres_obj.coeflist.h_filter_coef_4tap[j + 1]
2881+ << ISPRSZ_HFILT10_COEF1_SHIFT),
2882+ OMAP3_ISP_IOMEM_RESZ,
2883+ ISPRSZ_HFILT10 + (i * 0x04));
2884+ j += 2;
2885+ }
2886+ } else {
2887+ j = 0;
2888+ for (i = 0; i < 16; i++) {
2889+ if ((i + 1) % 4 == 0) {
2890+ isp_reg_writel((ispres_obj.coeflist.
2891+ h_filter_coef_7tap[j] <<
2892+ ISPRSZ_HFILT10_COEF0_SHIFT),
2893+ OMAP3_ISP_IOMEM_RESZ,
2894+ ISPRSZ_HFILT10 + (i * 0x04));
2895+ j += 1;
2896+ } else {
2897+ isp_reg_writel((ispres_obj.coeflist.
2898+ h_filter_coef_7tap[j] <<
2899+ ISPRSZ_HFILT10_COEF0_SHIFT) |
2900+ (ispres_obj.coeflist.
2901+ h_filter_coef_7tap[j+1] <<
2902+ ISPRSZ_HFILT10_COEF1_SHIFT),
2903+ OMAP3_ISP_IOMEM_RESZ,
2904+ ISPRSZ_HFILT10 + (i * 0x04));
2905+ j += 2;
2906+ }
2907+ }
2908+ }
2909+ if (ispres_obj.v_resz <= MID_RESIZE_VALUE) {
2910+ j = 0;
2911+ for (i = 0; i < 16; i++) {
2912+ isp_reg_writel((ispres_obj.coeflist.
2913+ v_filter_coef_4tap[j] <<
2914+ ISPRSZ_VFILT10_COEF0_SHIFT) |
2915+ (ispres_obj.coeflist.
2916+ v_filter_coef_4tap[j + 1] <<
2917+ ISPRSZ_VFILT10_COEF1_SHIFT),
2918+ OMAP3_ISP_IOMEM_RESZ,
2919+ ISPRSZ_VFILT10 + (i * 0x04));
2920+ j += 2;
2921+ }
2922+ } else {
2923+ j = 0;
2924+ for (i = 0; i < 16; i++) {
2925+ if ((i + 1) % 4 == 0) {
2926+ isp_reg_writel((ispres_obj.coeflist.
2927+ v_filter_coef_7tap[j] <<
2928+ ISPRSZ_VFILT10_COEF0_SHIFT),
2929+ OMAP3_ISP_IOMEM_RESZ,
2930+ ISPRSZ_VFILT10 + (i * 0x04));
2931+ j += 1;
2932+ } else {
2933+ isp_reg_writel((ispres_obj.coeflist.
2934+ v_filter_coef_7tap[j] <<
2935+ ISPRSZ_VFILT10_COEF0_SHIFT) |
2936+ (ispres_obj.coeflist.
2937+ v_filter_coef_7tap[j+1] <<
2938+ ISPRSZ_VFILT10_COEF1_SHIFT),
2939+ OMAP3_ISP_IOMEM_RESZ,
2940+ ISPRSZ_VFILT10 + (i * 0x04));
2941+ j += 2;
2942+ }
2943+ }
2944+ }
2945+
2946+ ispresizer_config_outlineoffset(output_w*2);
2947+ DPRINTK_ISPRESZ("ispresizer_config_size()-\n");
2948+ return 0;
2949+}
2950+EXPORT_SYMBOL(ispresizer_config_size);
2951+
2952+void __ispresizer_enable(int enable)
2953+{
2954+ int val;
2955+ DPRINTK_ISPRESZ("+ispresizer_enable()+\n");
2956+ if (enable) {
2957+ val = (isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) & 0x2) |
2958+ ISPRSZ_PCR_ENABLE;
2959+ } else {
2960+ val = isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
2961+ ~ISPRSZ_PCR_ENABLE;
2962+ }
2963+ isp_reg_writel(val, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR);
2964+ DPRINTK_ISPRESZ("+ispresizer_enable()-\n");
2965+}
2966+
2967+/**
2968+ * ispresizer_enable - Enables the resizer module.
2969+ * @enable: 1 - Enable, 0 - Disable
2970+ *
2971+ * Client should configure all the sub modules in resizer before this.
2972+ **/
2973+void ispresizer_enable(int enable)
2974+{
2975+ __ispresizer_enable(enable);
2976+ ispres_obj.pm_state = enable;
2977+}
2978+EXPORT_SYMBOL(ispresizer_enable);
2979+
2980+/**
2981+ * ispresizer_suspend - Suspend resizer module.
2982+ **/
2983+void ispresizer_suspend(void)
2984+{
2985+ if (ispres_obj.pm_state)
2986+ __ispresizer_enable(0);
2987+}
2988+EXPORT_SYMBOL(ispresizer_suspend);
2989+
2990+/**
2991+ * ispresizer_resume - Resume resizer module.
2992+ **/
2993+void ispresizer_resume(void)
2994+{
2995+ if (ispres_obj.pm_state)
2996+ __ispresizer_enable(1);
2997+}
2998+EXPORT_SYMBOL(ispresizer_resume);
2999+
3000+/**
3001+ * ispresizer_busy - Checks if ISP resizer is busy.
3002+ *
3003+ * Returns busy field from ISPRSZ_PCR register.
3004+ **/
3005+int ispresizer_busy(void)
3006+{
3007+ return isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
3008+ ISPPRV_PCR_BUSY;
3009+}
3010+EXPORT_SYMBOL(ispresizer_busy);
3011+
3012+/**
3013+ * ispresizer_config_startphase - Sets the horizontal and vertical start phase.
3014+ * @hstartphase: horizontal start phase (0 - 7).
3015+ * @vstartphase: vertical startphase (0 - 7).
3016+ *
3017+ * This API just updates the isp_res struct. Actual register write happens in
3018+ * ispresizer_config_size.
3019+ **/
3020+void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase)
3021+{
3022+ DPRINTK_ISPRESZ("ispresizer_config_startphase()+\n");
3023+ ispres_obj.h_startphase = hstartphase;
3024+ ispres_obj.v_startphase = vstartphase;
3025+ DPRINTK_ISPRESZ("ispresizer_config_startphase()-\n");
3026+}
3027+EXPORT_SYMBOL(ispresizer_config_startphase);
3028+
3029+/**
3030+ * ispresizer_config_ycpos - Specifies if output should be in YC or CY format.
3031+ * @yc: 0 - YC format, 1 - CY format
3032+ **/
3033+void ispresizer_config_ycpos(u8 yc)
3034+{
3035+ DPRINTK_ISPRESZ("ispresizer_config_ycpos()+\n");
3036+ isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_YCPOS,
3037+ (yc ? ISPRSZ_CNT_YCPOS : 0));
3038+ DPRINTK_ISPRESZ("ispresizer_config_ycpos()-\n");
3039+}
3040+EXPORT_SYMBOL(ispresizer_config_ycpos);
3041+
3042+/**
3043+ * Sets the chrominance algorithm
3044+ * @cbilin: 0 - chrominance uses same processing as luminance,
3045+ * 1 - bilinear interpolation processing
3046+ **/
3047+void ispresizer_enable_cbilin(u8 enable)
3048+{
3049+ DPRINTK_ISPRESZ("ispresizer_enable_cbilin()+\n");
3050+ isp_reg_and_or(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT, ~ISPRSZ_CNT_CBILIN,
3051+ (enable ? ISPRSZ_CNT_CBILIN : 0));
3052+ DPRINTK_ISPRESZ("ispresizer_enable_cbilin()-\n");
3053+}
3054+EXPORT_SYMBOL(ispresizer_enable_cbilin);
3055+
3056+/**
3057+ * ispresizer_config_luma_enhance - Configures luminance enhancer parameters.
3058+ * @yenh: Pointer to structure containing desired values for core, slope, gain
3059+ * and algo parameters.
3060+ **/
3061+void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh)
3062+{
3063+ DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()+\n");
3064+ ispres_obj.algo = yenh->algo;
3065+ isp_reg_writel((yenh->algo << ISPRSZ_YENH_ALGO_SHIFT) |
3066+ (yenh->gain << ISPRSZ_YENH_GAIN_SHIFT) |
3067+ (yenh->slope << ISPRSZ_YENH_SLOP_SHIFT) |
3068+ (yenh->coreoffset << ISPRSZ_YENH_CORE_SHIFT),
3069+ OMAP3_ISP_IOMEM_RESZ,
3070+ ISPRSZ_YENH);
3071+ DPRINTK_ISPRESZ("ispresizer_config_luma_enhance()-\n");
3072+}
3073+EXPORT_SYMBOL(ispresizer_config_luma_enhance);
3074+
3075+/**
3076+ * ispresizer_config_filter_coef - Sets filter coefficients for 4 & 7-tap mode.
3077+ * This API just updates the isp_res struct.Actual register write happens in
3078+ * ispresizer_config_size.
3079+ * @coef: Structure containing horizontal and vertical filter coefficients for
3080+ * both 4-tap and 7-tap mode.
3081+ **/
3082+void ispresizer_config_filter_coef(struct isprsz_coef *coef)
3083+{
3084+ int i;
3085+ DPRINTK_ISPRESZ("ispresizer_config_filter_coef()+\n");
3086+ for (i = 0; i < 32; i++) {
3087+ ispres_obj.coeflist.h_filter_coef_4tap[i] =
3088+ coef->h_filter_coef_4tap[i];
3089+ ispres_obj.coeflist.v_filter_coef_4tap[i] =
3090+ coef->v_filter_coef_4tap[i];
3091+ }
3092+ for (i = 0; i < 28; i++) {
3093+ ispres_obj.coeflist.h_filter_coef_7tap[i] =
3094+ coef->h_filter_coef_7tap[i];
3095+ ispres_obj.coeflist.v_filter_coef_7tap[i] =
3096+ coef->v_filter_coef_7tap[i];
3097+ }
3098+ DPRINTK_ISPRESZ("ispresizer_config_filter_coef()-\n");
3099+}
3100+EXPORT_SYMBOL(ispresizer_config_filter_coef);
3101+
3102+/**
3103+ * ispresizer_config_inlineoffset - Configures the read address line offset.
3104+ * @offset: Line Offset for the input image.
3105+ *
3106+ * Returns 0 if successful, or -EINVAL if offset is not 32 bits aligned.
3107+ **/
3108+int ispresizer_config_inlineoffset(u32 offset)
3109+{
3110+ DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()+\n");
3111+ if (offset % 32)
3112+ return -EINVAL;
3113+ isp_reg_writel(offset << ISPRSZ_SDR_INOFF_OFFSET_SHIFT,
3114+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
3115+ DPRINTK_ISPRESZ("ispresizer_config_inlineoffset()-\n");
3116+ return 0;
3117+}
3118+EXPORT_SYMBOL(ispresizer_config_inlineoffset);
3119+
3120+/**
3121+ * ispresizer_set_inaddr - Sets the memory address of the input frame.
3122+ * @addr: 32bit memory address aligned on 32byte boundary.
3123+ *
3124+ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
3125+ **/
3126+int ispresizer_set_inaddr(u32 addr)
3127+{
3128+ DPRINTK_ISPRESZ("ispresizer_set_inaddr()+\n");
3129+ if (addr % 32)
3130+ return -EINVAL;
3131+ isp_reg_writel(addr << ISPRSZ_SDR_INADD_ADDR_SHIFT,
3132+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
3133+ ispres_obj.tmp_buf = addr;
3134+ DPRINTK_ISPRESZ("ispresizer_set_inaddr()-\n");
3135+ return 0;
3136+}
3137+EXPORT_SYMBOL(ispresizer_set_inaddr);
3138+
3139+/**
3140+ * ispresizer_config_outlineoffset - Configures the write address line offset.
3141+ * @offset: Line offset for the preview output.
3142+ *
3143+ * Returns 0 if successful, or -EINVAL if address is not 32 bits aligned.
3144+ **/
3145+int ispresizer_config_outlineoffset(u32 offset)
3146+{
3147+ DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()+\n");
3148+ if (offset % 32)
3149+ return -EINVAL;
3150+ isp_reg_writel(offset << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT,
3151+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
3152+ DPRINTK_ISPRESZ("ispresizer_config_outlineoffset()-\n");
3153+ return 0;
3154+}
3155+EXPORT_SYMBOL(ispresizer_config_outlineoffset);
3156+
3157+/**
3158+ * Configures the memory address to which the output frame is written.
3159+ * @addr: 32bit memory address aligned on 32byte boundary.
3160+ **/
3161+int ispresizer_set_outaddr(u32 addr)
3162+{
3163+ DPRINTK_ISPRESZ("ispresizer_set_outaddr()+\n");
3164+ if (addr % 32)
3165+ return -EINVAL;
3166+ isp_reg_writel(addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
3167+ OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
3168+ DPRINTK_ISPRESZ("ispresizer_set_outaddr()-\n");
3169+ return 0;
3170+}
3171+EXPORT_SYMBOL(ispresizer_set_outaddr);
3172+
3173+/**
3174+ * ispresizer_save_context - Saves the values of the resizer module registers.
3175+ **/
3176+void ispresizer_save_context(void)
3177+{
3178+ DPRINTK_ISPRESZ("Saving context\n");
3179+ isp_save_context(isprsz_reg_list);
3180+}
3181+EXPORT_SYMBOL(ispresizer_save_context);
3182+
3183+/**
3184+ * ispresizer_restore_context - Restores resizer module register values.
3185+ **/
3186+void ispresizer_restore_context(void)
3187+{
3188+ DPRINTK_ISPRESZ("Restoring context\n");
3189+ isp_restore_context(isprsz_reg_list);
3190+}
3191+EXPORT_SYMBOL(ispresizer_restore_context);
3192+
3193+/**
3194+ * ispresizer_print_status - Prints the values of the resizer module registers.
3195+ **/
3196+void ispresizer_print_status()
3197+{
3198+ if (!is_ispresz_debug_enabled())
3199+ return;
3200+ DPRINTK_ISPRESZ("###ISP_CTRL inresizer =0x%x\n",
3201+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
3202+ DPRINTK_ISPRESZ("###ISP_IRQ0ENABLE in resizer =0x%x\n",
3203+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE));
3204+ DPRINTK_ISPRESZ("###ISP_IRQ0STATUS in resizer =0x%x\n",
3205+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS));
3206+ DPRINTK_ISPRESZ("###RSZ PCR =0x%x\n",
3207+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR));
3208+ DPRINTK_ISPRESZ("###RSZ CNT =0x%x\n",
3209+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT));
3210+ DPRINTK_ISPRESZ("###RSZ OUT SIZE =0x%x\n",
3211+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE));
3212+ DPRINTK_ISPRESZ("###RSZ IN START =0x%x\n",
3213+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START));
3214+ DPRINTK_ISPRESZ("###RSZ IN SIZE =0x%x\n",
3215+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE));
3216+ DPRINTK_ISPRESZ("###RSZ SDR INADD =0x%x\n",
3217+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD));
3218+ DPRINTK_ISPRESZ("###RSZ SDR INOFF =0x%x\n",
3219+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF));
3220+ DPRINTK_ISPRESZ("###RSZ SDR OUTADD =0x%x\n",
3221+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD));
3222+ DPRINTK_ISPRESZ("###RSZ SDR OTOFF =0x%x\n",
3223+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF));
3224+ DPRINTK_ISPRESZ("###RSZ YENH =0x%x\n",
3225+ isp_reg_readl(OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH));
3226+}
3227+EXPORT_SYMBOL(ispresizer_print_status);
3228+
3229+/**
3230+ * isp_resizer_init - Module Initialisation.
3231+ *
3232+ * Always returns 0.
3233+ **/
3234+int __init isp_resizer_init(void)
3235+{
3236+ mutex_init(&ispres_obj.ispres_mutex);
3237+ ispres_obj.pm_state = 0;
3238+ return 0;
3239+}
3240+
3241+/**
3242+ * isp_resizer_cleanup - Module Cleanup.
3243+ **/
3244+void isp_resizer_cleanup(void)
3245+{
3246+}
3247diff --git a/drivers/media/video/isp/ispresizer.h b/drivers/media/video/isp/ispresizer.h
3248new file mode 100644
3249index 0000000..4e92225
3250--- /dev/null
3251+++ b/drivers/media/video/isp/ispresizer.h
3252@@ -0,0 +1,158 @@
3253+/*
3254+ * ispresizer.h
3255+ *
3256+ * Driver header file for Resizer module in TI's OMAP3 Camera ISP
3257+ *
3258+ * Copyright (C) 2009 Texas Instruments, Inc.
3259+ *
3260+ * Contributors:
3261+ * Sameer Venkatraman <sameerv@ti.com>
3262+ * Mohit Jalori
3263+ * Sergio Aguirre <saaguirre@ti.com>
3264+ *
3265+ * This package is free software; you can redistribute it and/or modify
3266+ * it under the terms of the GNU General Public License version 2 as
3267+ * published by the Free Software Foundation.
3268+ *
3269+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3270+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3271+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3272+ */
3273+
3274+#ifndef OMAP_ISP_RESIZER_H
3275+#define OMAP_ISP_RESIZER_H
3276+
3277+/*
3278+ * Resizer Constants
3279+ */
3280+#define MAX_IN_WIDTH_MEMORY_MODE 4095
3281+
3282+#define MAX_IN_WIDTH_ONTHEFLY_MODE 1280
3283+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2 4095
3284+#define MAX_IN_HEIGHT 4095
3285+#define MINIMUM_RESIZE_VALUE 64
3286+#define MAXIMUM_RESIZE_VALUE 1024
3287+#define MID_RESIZE_VALUE 512
3288+
3289+#define MAX_7TAP_HRSZ_OUTWIDTH 1280
3290+#define MAX_7TAP_VRSZ_OUTWIDTH 640
3291+
3292+#define MAX_7TAP_HRSZ_OUTWIDTH_ES2 3300
3293+#define MAX_7TAP_VRSZ_OUTWIDTH_ES2 1650
3294+
3295+#define DEFAULTSTPIXEL 0
3296+#define DEFAULTSTPHASE 1
3297+#define DEFAULTHSTPIXEL4TAPMODE 3
3298+#define FOURPHASE 4
3299+#define EIGHTPHASE 8
3300+#define RESIZECONSTANT 256
3301+#define SHIFTER4TAPMODE 0
3302+#define SHIFTER7TAPMODE 1
3303+#define DEFAULTOFFSET 7
3304+#define OFFSETVERT4TAPMODE 4
3305+#define OPWDALIGNCONSTANT 0xfffffff0
3306+
3307+/*
3308+ * The client is supposed to call resizer API in the following sequence:
3309+ * - request()
3310+ * - config_datatpath()
3311+ * - optionally config/enable sub modules
3312+ * - try/config size
3313+ * - setup callback
3314+ * - setup in/out memory offsets and ptrs
3315+ * - enable()
3316+ * ...
3317+ * - disable()
3318+ * - free()
3319+ */
3320+
3321+enum ispresizer_input {
3322+ RSZ_OTFLY_YUV,
3323+ RSZ_MEM_YUV,
3324+ RSZ_MEM_COL8
3325+};
3326+
3327+/**
3328+ * struct isprsz_coef - Structure for resizer filter coeffcients.
3329+ * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
3330+ * mode (.5x-4x)
3331+ * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
3332+ * mode (.5x-4x)
3333+ * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
3334+ * mode (.25x-.5x)
3335+ * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
3336+ * mode (.25x-.5x)
3337+ */
3338+struct isprsz_coef {
3339+ u16 h_filter_coef_4tap[32];
3340+ u16 v_filter_coef_4tap[32];
3341+ u16 h_filter_coef_7tap[28];
3342+ u16 v_filter_coef_7tap[28];
3343+};
3344+
3345+/**
3346+ * struct isprsz_yenh - Structure for resizer luminance enhancer parameters.
3347+ * @algo: Algorithm select.
3348+ * @gain: Maximum gain.
3349+ * @slope: Slope.
3350+ * @coreoffset: Coring offset.
3351+ */
3352+struct isprsz_yenh {
3353+ u8 algo;
3354+ u8 gain;
3355+ u8 slope;
3356+ u8 coreoffset;
3357+};
3358+
3359+void ispresizer_config_shadow_registers(void);
3360+
3361+int ispresizer_request(void);
3362+
3363+int ispresizer_free(void);
3364+
3365+int ispresizer_config_datapath(enum ispresizer_input input);
3366+
3367+void ispresizer_enable_cbilin(u8 enable);
3368+
3369+void ispresizer_config_ycpos(u8 yc);
3370+
3371+void ispresizer_config_startphase(u8 hstartphase, u8 vstartphase);
3372+
3373+void ispresizer_config_filter_coef(struct isprsz_coef *coef);
3374+
3375+void ispresizer_config_luma_enhance(struct isprsz_yenh *yenh);
3376+
3377+int ispresizer_try_size(u32 *input_w, u32 *input_h, u32 *output_w,
3378+ u32 *output_h);
3379+
3380+void ispresizer_applycrop(void);
3381+
3382+void ispresizer_trycrop(u32 left, u32 top, u32 width, u32 height, u32 ow,
3383+ u32 oh);
3384+
3385+int ispresizer_config_size(u32 input_w, u32 input_h, u32 output_w,
3386+ u32 output_h);
3387+
3388+int ispresizer_config_inlineoffset(u32 offset);
3389+
3390+int ispresizer_set_inaddr(u32 addr);
3391+
3392+int ispresizer_config_outlineoffset(u32 offset);
3393+
3394+int ispresizer_set_outaddr(u32 addr);
3395+
3396+void ispresizer_enable(int enable);
3397+
3398+void ispresizer_suspend(void);
3399+
3400+void ispresizer_resume(void);
3401+
3402+int ispresizer_busy(void);
3403+
3404+void ispresizer_save_context(void);
3405+
3406+void ispresizer_restore_context(void);
3407+
3408+void ispresizer_print_status(void);
3409+
3410+#endif /* OMAP_ISP_RESIZER_H */
3411--
34121.5.6.5
3413
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
new file mode 100644
index 0000000000..876ce780f0
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0006-omap3isp-Add-statistics-collection-modules-H3A-and.patch
@@ -0,0 +1,2741 @@
1From 9a39eab5ed1b70711c3b10de95cd90749293ef7a Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add statistics collection modules (H3A and HIST)
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 drivers/media/video/isp/isp_af.c | 784 +++++++++++++++++++++++++++++++
9 drivers/media/video/isp/isp_af.h | 125 +++++
10 drivers/media/video/isp/isph3a.c | 932 +++++++++++++++++++++++++++++++++++++
11 drivers/media/video/isp/isph3a.h | 127 +++++
12 drivers/media/video/isp/isphist.c | 608 ++++++++++++++++++++++++
13 drivers/media/video/isp/isphist.h | 105 +++++
14 6 files changed, 2681 insertions(+), 0 deletions(-)
15 create mode 100644 drivers/media/video/isp/isp_af.c
16 create mode 100644 drivers/media/video/isp/isp_af.h
17 create mode 100644 drivers/media/video/isp/isph3a.c
18 create mode 100644 drivers/media/video/isp/isph3a.h
19 create mode 100644 drivers/media/video/isp/isphist.c
20 create mode 100644 drivers/media/video/isp/isphist.h
21
22diff --git a/drivers/media/video/isp/isp_af.c b/drivers/media/video/isp/isp_af.c
23new file mode 100644
24index 0000000..a607b97
25--- /dev/null
26+++ b/drivers/media/video/isp/isp_af.c
27@@ -0,0 +1,784 @@
28+/*
29+ * isp_af.c
30+ *
31+ * AF module for TI's OMAP3 Camera ISP
32+ *
33+ * Copyright (C) 2009 Texas Instruments, Inc.
34+ *
35+ * Contributors:
36+ * Sergio Aguirre <saaguirre@ti.com>
37+ * Troy Laramy
38+ *
39+ * This package is free software; you can redistribute it and/or modify
40+ * it under the terms of the GNU General Public License version 2 as
41+ * published by the Free Software Foundation.
42+ *
43+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
46+ */
47+
48+/* Linux specific include files */
49+#include <asm/cacheflush.h>
50+
51+#include <linux/uaccess.h>
52+#include <linux/dma-mapping.h>
53+#include <asm/atomic.h>
54+
55+#include "isp.h"
56+#include "ispreg.h"
57+#include "isph3a.h"
58+#include "isp_af.h"
59+#include "ispmmu.h"
60+
61+/**
62+ * struct isp_af_buffer - AF frame stats buffer.
63+ * @virt_addr: Virtual address to mmap the buffer.
64+ * @phy_addr: Physical address of the buffer.
65+ * @addr_align: Virtual Address 32 bytes aligned.
66+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
67+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
68+ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
69+ * @frame_num: Frame number from which the statistics are taken.
70+ * @lens_position: Lens position currently set in the DW9710 Coil motor driver.
71+ * @next: Pointer to link next buffer.
72+ */
73+struct isp_af_buffer {
74+ unsigned long virt_addr;
75+ unsigned long phy_addr;
76+ unsigned long addr_align;
77+ unsigned long ispmmu_addr;
78+ unsigned long mmap_addr;
79+
80+ u8 locked;
81+ u16 frame_num;
82+ u32 config_counter;
83+ struct isp_af_xtrastats xtrastats;
84+ struct isp_af_buffer *next;
85+};
86+
87+/**
88+ * struct isp_af_status - AF status.
89+ * @initialized: 1 - Buffers initialized.
90+ * @update: 1 - Update registers.
91+ * @stats_req: 1 - Future stats requested.
92+ * @stats_done: 1 - Stats ready for user.
93+ * @frame_req: Number of frame requested for statistics.
94+ * @af_buff: Array of statistics buffers to access.
95+ * @stats_buf_size: Statistics buffer size.
96+ * @curr_cfg_buf_size: Current user configured stats buff size.
97+ * @min_buf_size: Minimum statisitics buffer size.
98+ * @frame_count: Frame Count.
99+ * @stats_wait: Wait primitive for locking/unlocking the stats request.
100+ * @buffer_lock: Spinlock for statistics buffers access.
101+ */
102+static struct isp_af_status {
103+ u8 initialized;
104+ u8 update;
105+ u8 stats_req;
106+ u8 stats_done;
107+ u16 frame_req;
108+
109+ struct isp_af_buffer af_buff[H3A_MAX_BUFF];
110+ unsigned int stats_buf_size;
111+ unsigned int min_buf_size;
112+ unsigned int curr_cfg_buf_size;
113+
114+ int pm_state;
115+ u32 frame_count;
116+ wait_queue_head_t stats_wait;
117+ atomic_t config_counter;
118+ spinlock_t buffer_lock; /* For stats buffers read/write sync */
119+} afstat;
120+
121+struct af_device *af_dev_configptr;
122+static struct isp_af_buffer *active_buff;
123+static int af_major = -1;
124+static int camnotify;
125+
126+/**
127+ * isp_af_setxtrastats - Receives extra statistics from prior frames.
128+ * @xtrastats: Pointer to structure containing extra statistics fields like
129+ * field count and timestamp of frame.
130+ *
131+ * Called from update_vbq in camera driver
132+ **/
133+void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag)
134+{
135+ int i, past_i;
136+
137+ if (active_buff == NULL)
138+ return;
139+
140+ for (i = 0; i < H3A_MAX_BUFF; i++) {
141+ if (afstat.af_buff[i].frame_num == active_buff->frame_num)
142+ break;
143+ }
144+
145+ if (i == H3A_MAX_BUFF)
146+ return;
147+
148+ if (i == 0) {
149+ if (afstat.af_buff[H3A_MAX_BUFF - 1].locked == 0)
150+ past_i = H3A_MAX_BUFF - 1;
151+ else
152+ past_i = H3A_MAX_BUFF - 2;
153+ } else if (i == 1) {
154+ if (afstat.af_buff[0].locked == 0)
155+ past_i = 0;
156+ else
157+ past_i = H3A_MAX_BUFF - 1;
158+ } else {
159+ if (afstat.af_buff[i - 1].locked == 0)
160+ past_i = i - 1;
161+ else
162+ past_i = i - 2;
163+ }
164+
165+ if (updateflag & AF_UPDATEXS_TS)
166+ afstat.af_buff[past_i].xtrastats.ts = xtrastats->ts;
167+
168+ if (updateflag & AF_UPDATEXS_FIELDCOUNT)
169+ afstat.af_buff[past_i].xtrastats.field_count =
170+ xtrastats->field_count;
171+}
172+EXPORT_SYMBOL(isp_af_setxtrastats);
173+
174+/*
175+ * Helper function to update buffer cache pages
176+ */
177+static void isp_af_update_req_buffer(struct isp_af_buffer *buffer)
178+{
179+ int size = afstat.stats_buf_size;
180+
181+ size = PAGE_ALIGN(size);
182+ /* Update the kernel pages of the requested buffer */
183+ dmac_inv_range((void *)buffer->addr_align, (void *)buffer->addr_align +
184+ size);
185+}
186+
187+#define IS_OUT_OF_BOUNDS(value, min, max) \
188+ (((value) < (min)) || ((value) > (max)))
189+
190+/* Function to check paxel parameters */
191+int isp_af_check_paxel(void)
192+{
193+ struct af_paxel *paxel_cfg = &af_dev_configptr->config->paxel_config;
194+ struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
195+
196+ /* Check horizontal Count */
197+ if (IS_OUT_OF_BOUNDS(paxel_cfg->hz_cnt, AF_PAXEL_HORIZONTAL_COUNT_MIN,
198+ AF_PAXEL_HORIZONTAL_COUNT_MAX)) {
199+ DPRINTK_ISP_AF("Error : Horizontal Count is incorrect");
200+ return -AF_ERR_HZ_COUNT;
201+ }
202+
203+ /*Check Vertical Count */
204+ if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_cnt, AF_PAXEL_VERTICAL_COUNT_MIN,
205+ AF_PAXEL_VERTICAL_COUNT_MAX)) {
206+ DPRINTK_ISP_AF("Error : Vertical Count is incorrect");
207+ return -AF_ERR_VT_COUNT;
208+ }
209+
210+ /*Check Height */
211+ if (IS_OUT_OF_BOUNDS(paxel_cfg->height, AF_PAXEL_HEIGHT_MIN,
212+ AF_PAXEL_HEIGHT_MAX)) {
213+ DPRINTK_ISP_AF("Error : Height is incorrect");
214+ return -AF_ERR_HEIGHT;
215+ }
216+
217+ /*Check width */
218+ if (IS_OUT_OF_BOUNDS(paxel_cfg->width, AF_PAXEL_WIDTH_MIN,
219+ AF_PAXEL_WIDTH_MAX)) {
220+ DPRINTK_ISP_AF("Error : Width is incorrect");
221+ return -AF_ERR_WIDTH;
222+ }
223+
224+ /*Check Line Increment */
225+ if (IS_OUT_OF_BOUNDS(paxel_cfg->line_incr, AF_PAXEL_INCREMENT_MIN,
226+ AF_PAXEL_INCREMENT_MAX)) {
227+ DPRINTK_ISP_AF("Error : Line Increment is incorrect");
228+ return -AF_ERR_INCR;
229+ }
230+
231+ /*Check Horizontal Start */
232+ if ((paxel_cfg->hz_start % 2 != 0) ||
233+ (paxel_cfg->hz_start < (iir_cfg->hz_start_pos + 2)) ||
234+ IS_OUT_OF_BOUNDS(paxel_cfg->hz_start,
235+ AF_PAXEL_HZSTART_MIN, AF_PAXEL_HZSTART_MAX)) {
236+ DPRINTK_ISP_AF("Error : Horizontal Start is incorrect");
237+ return -AF_ERR_HZ_START;
238+ }
239+
240+ /*Check Vertical Start */
241+ if (IS_OUT_OF_BOUNDS(paxel_cfg->vt_start, AF_PAXEL_VTSTART_MIN,
242+ AF_PAXEL_VTSTART_MAX)) {
243+ DPRINTK_ISP_AF("Error : Vertical Start is incorrect");
244+ return -AF_ERR_VT_START;
245+ }
246+ return 0;
247+}
248+
249+/**
250+ * isp_af_check_iir - Function to check IIR Coefficient.
251+ **/
252+int isp_af_check_iir(void)
253+{
254+ struct af_iir *iir_cfg = &af_dev_configptr->config->iir_config;
255+ int index;
256+
257+ for (index = 0; index < AF_NUMBER_OF_COEF; index++) {
258+ if ((iir_cfg->coeff_set0[index]) > AF_COEF_MAX) {
259+ DPRINTK_ISP_AF("Error : Coefficient for set 0 is "
260+ "incorrect");
261+ return -AF_ERR_IIR_COEF;
262+ }
263+
264+ if ((iir_cfg->coeff_set1[index]) > AF_COEF_MAX) {
265+ DPRINTK_ISP_AF("Error : Coefficient for set 1 is "
266+ "incorrect");
267+ return -AF_ERR_IIR_COEF;
268+ }
269+ }
270+
271+ if (IS_OUT_OF_BOUNDS(iir_cfg->hz_start_pos, AF_IIRSH_MIN,
272+ AF_IIRSH_MAX)) {
273+ DPRINTK_ISP_AF("Error : IIRSH is incorrect");
274+ return -AF_ERR_IIRSH;
275+ }
276+
277+ return 0;
278+}
279+/**
280+ * isp_af_unlock_buffers - Helper function to unlock all buffers.
281+ **/
282+static void isp_af_unlock_buffers(void)
283+{
284+ int i;
285+ unsigned long irqflags;
286+
287+ spin_lock_irqsave(&afstat.buffer_lock, irqflags);
288+ for (i = 0; i < H3A_MAX_BUFF; i++)
289+ afstat.af_buff[i].locked = 0;
290+
291+ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
292+}
293+
294+/*
295+ * Helper function to link allocated buffers
296+ */
297+static void isp_af_link_buffers(void)
298+{
299+ int i;
300+
301+ for (i = 0; i < H3A_MAX_BUFF; i++) {
302+ if ((i + 1) < H3A_MAX_BUFF)
303+ afstat.af_buff[i].next = &afstat.af_buff[i + 1];
304+ else
305+ afstat.af_buff[i].next = &afstat.af_buff[0];
306+ }
307+}
308+
309+/* Function to perform hardware set up */
310+int isp_af_configure(struct af_configuration *afconfig)
311+{
312+ int result;
313+ int buff_size, i;
314+ unsigned int busyaf;
315+ struct af_configuration *af_curr_cfg = af_dev_configptr->config;
316+
317+ if (NULL == afconfig) {
318+ printk(KERN_ERR "Null argument in configuration. \n");
319+ return -EINVAL;
320+ }
321+
322+ memcpy(af_curr_cfg, afconfig, sizeof(struct af_configuration));
323+ /* Get the value of PCR register */
324+ busyaf = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
325+
326+ if ((busyaf & AF_BUSYAF) == AF_BUSYAF) {
327+ DPRINTK_ISP_AF("AF_register_setup_ERROR : Engine Busy");
328+ DPRINTK_ISP_AF("\n Configuration cannot be done ");
329+ return -AF_ERR_ENGINE_BUSY;
330+ }
331+
332+ /* Check IIR Coefficient and start Values */
333+ result = isp_af_check_iir();
334+ if (result < 0)
335+ return result;
336+
337+ /* Check Paxel Values */
338+ result = isp_af_check_paxel();
339+ if (result < 0)
340+ return result;
341+
342+ /* Check HMF Threshold Values */
343+ if (af_curr_cfg->hmf_config.threshold > AF_THRESHOLD_MAX) {
344+ DPRINTK_ISP_AF("Error : HMF Threshold is incorrect");
345+ return -AF_ERR_THRESHOLD;
346+ }
347+
348+ /* Compute buffer size */
349+ buff_size = (af_curr_cfg->paxel_config.hz_cnt + 1) *
350+ (af_curr_cfg->paxel_config.vt_cnt + 1) * AF_PAXEL_SIZE;
351+
352+ afstat.curr_cfg_buf_size = buff_size;
353+ /* Deallocate the previous buffers */
354+ if (afstat.stats_buf_size && buff_size > afstat.stats_buf_size) {
355+ isp_af_enable(0);
356+ for (i = 0; i < H3A_MAX_BUFF; i++) {
357+ ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
358+ dma_free_coherent(
359+ NULL, afstat.min_buf_size,
360+ (void *)afstat.af_buff[i].virt_addr,
361+ (dma_addr_t)afstat.af_buff[i].phy_addr);
362+ afstat.af_buff[i].virt_addr = 0;
363+ }
364+ afstat.stats_buf_size = 0;
365+ }
366+
367+ if (!afstat.af_buff[0].virt_addr) {
368+ afstat.stats_buf_size = buff_size;
369+ afstat.min_buf_size = PAGE_ALIGN(afstat.stats_buf_size);
370+
371+ for (i = 0; i < H3A_MAX_BUFF; i++) {
372+ afstat.af_buff[i].virt_addr =
373+ (unsigned long)dma_alloc_coherent(
374+ NULL,
375+ afstat.min_buf_size,
376+ (dma_addr_t *)
377+ &afstat.af_buff[i].phy_addr,
378+ GFP_KERNEL | GFP_DMA);
379+ if (afstat.af_buff[i].virt_addr == 0) {
380+ printk(KERN_ERR "Can't acquire memory for "
381+ "buffer[%d]\n", i);
382+ return -ENOMEM;
383+ }
384+ afstat.af_buff[i].addr_align =
385+ afstat.af_buff[i].virt_addr;
386+ while ((afstat.af_buff[i].addr_align & 0xFFFFFFC0) !=
387+ afstat.af_buff[i].addr_align)
388+ afstat.af_buff[i].addr_align++;
389+ afstat.af_buff[i].ispmmu_addr =
390+ ispmmu_kmap(afstat.af_buff[i].phy_addr,
391+ afstat.min_buf_size);
392+ }
393+ isp_af_unlock_buffers();
394+ isp_af_link_buffers();
395+
396+ /* First active buffer */
397+ if (active_buff == NULL)
398+ active_buff = &afstat.af_buff[0];
399+ isp_af_set_address(active_buff->ispmmu_addr);
400+ }
401+
402+ result = isp_af_register_setup(af_dev_configptr);
403+ if (result < 0)
404+ return result;
405+ af_dev_configptr->size_paxel = buff_size;
406+ atomic_inc(&afstat.config_counter);
407+ afstat.initialized = 1;
408+ afstat.frame_count = 1;
409+ active_buff->frame_num = 1;
410+ /* Set configuration flag to indicate HW setup done */
411+ if (af_curr_cfg->af_config)
412+ isp_af_enable(1);
413+ else
414+ isp_af_enable(0);
415+
416+ /* Success */
417+ return 0;
418+}
419+EXPORT_SYMBOL(isp_af_configure);
420+
421+int isp_af_register_setup(struct af_device *af_dev)
422+{
423+ unsigned int pcr = 0, pax1 = 0, pax2 = 0, paxstart = 0;
424+ unsigned int coef = 0;
425+ unsigned int base_coef_set0 = 0;
426+ unsigned int base_coef_set1 = 0;
427+ int index;
428+
429+ /* Configure Hardware Registers */
430+ /* Read PCR Register */
431+ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
432+
433+ /* Set Accumulator Mode */
434+ if (af_dev->config->mode == ACCUMULATOR_PEAK)
435+ pcr |= FVMODE;
436+ else
437+ pcr &= ~FVMODE;
438+
439+ /* Set A-law */
440+ if (af_dev->config->alaw_enable == H3A_AF_ALAW_ENABLE)
441+ pcr |= AF_ALAW_EN;
442+ else
443+ pcr &= ~AF_ALAW_EN;
444+
445+ /* Set RGB Position */
446+ pcr &= ~RGBPOS;
447+ pcr |= af_dev->config->rgb_pos << AF_RGBPOS_SHIFT;
448+
449+ /* HMF Configurations */
450+ if (af_dev->config->hmf_config.enable == H3A_AF_HMF_ENABLE) {
451+ pcr &= ~AF_MED_EN;
452+ /* Enable HMF */
453+ pcr |= AF_MED_EN;
454+
455+ /* Set Median Threshold */
456+ pcr &= ~MED_TH;
457+ pcr |= af_dev->config->hmf_config.threshold << AF_MED_TH_SHIFT;
458+ } else
459+ pcr &= ~AF_MED_EN;
460+
461+ /* Set PCR Register */
462+ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
463+
464+ pax1 &= ~PAXW;
465+ pax1 |= af_dev->config->paxel_config.width << AF_PAXW_SHIFT;
466+
467+ /* Set height in AFPAX1 */
468+ pax1 &= ~PAXH;
469+ pax1 |= af_dev->config->paxel_config.height;
470+
471+ isp_reg_writel(pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
472+
473+ /* Configure AFPAX2 Register */
474+ /* Set Line Increment in AFPAX2 Register */
475+ pax2 &= ~AFINCV;
476+ pax2 |= af_dev->config->paxel_config.line_incr << AF_LINE_INCR_SHIFT;
477+ /* Set Vertical Count */
478+ pax2 &= ~PAXVC;
479+ pax2 |= af_dev->config->paxel_config.vt_cnt << AF_VT_COUNT_SHIFT;
480+ /* Set Horizontal Count */
481+ pax2 &= ~PAXHC;
482+ pax2 |= af_dev->config->paxel_config.hz_cnt;
483+ isp_reg_writel(pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
484+
485+ /* Configure PAXSTART Register */
486+ /*Configure Horizontal Start */
487+ paxstart &= ~PAXSH;
488+ paxstart |= af_dev->config->paxel_config.hz_start << AF_HZ_START_SHIFT;
489+ /* Configure Vertical Start */
490+ paxstart &= ~PAXSV;
491+ paxstart |= af_dev->config->paxel_config.vt_start;
492+ isp_reg_writel(paxstart, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART);
493+
494+ /*SetIIRSH Register */
495+ isp_reg_writel(af_dev->config->iir_config.hz_start_pos,
496+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
497+
498+ /*Set IIR Filter0 Coefficients */
499+ base_coef_set0 = ISPH3A_AFCOEF010;
500+ for (index = 0; index <= 8; index += 2) {
501+ coef &= ~COEF_MASK0;
502+ coef |= af_dev->config->iir_config.coeff_set0[index];
503+ coef &= ~COEF_MASK1;
504+ coef |= af_dev->config->iir_config.coeff_set0[index + 1] <<
505+ AF_COEF_SHIFT;
506+ isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set0);
507+ base_coef_set0 = base_coef_set0 + AFCOEF_OFFSET;
508+ }
509+
510+ /* set AFCOEF0010 Register */
511+ isp_reg_writel(af_dev->config->iir_config.coeff_set0[10],
512+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010);
513+
514+ /*Set IIR Filter1 Coefficients */
515+
516+ base_coef_set1 = ISPH3A_AFCOEF110;
517+ for (index = 0; index <= 8; index += 2) {
518+ coef &= ~COEF_MASK0;
519+ coef |= af_dev->config->iir_config.coeff_set1[index];
520+ coef &= ~COEF_MASK1;
521+ coef |= af_dev->config->iir_config.coeff_set1[index + 1] <<
522+ AF_COEF_SHIFT;
523+ isp_reg_writel(coef, OMAP3_ISP_IOMEM_H3A, base_coef_set1);
524+
525+ base_coef_set1 = base_coef_set1 + AFCOEF_OFFSET;
526+ }
527+ isp_reg_writel(af_dev->config->iir_config.coeff_set1[10],
528+ OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
529+
530+ return 0;
531+}
532+
533+/* Function to set address */
534+void isp_af_set_address(unsigned long address)
535+{
536+ isp_reg_writel(address, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST);
537+}
538+
539+static int isp_af_stats_available(struct isp_af_data *afdata)
540+{
541+ int i, ret;
542+ unsigned long irqflags;
543+
544+ spin_lock_irqsave(&afstat.buffer_lock, irqflags);
545+ for (i = 0; i < H3A_MAX_BUFF; i++) {
546+ DPRINTK_ISP_AF("Checking Stats buff[%d] (%d) for %d\n",
547+ i, afstat.af_buff[i].frame_num,
548+ afdata->frame_number);
549+ if (afdata->frame_number == afstat.af_buff[i].frame_num
550+ && afstat.af_buff[i].frame_num != active_buff->frame_num) {
551+ afstat.af_buff[i].locked = 1;
552+ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
553+ isp_af_update_req_buffer(&afstat.af_buff[i]);
554+ afstat.af_buff[i].frame_num = 0;
555+ ret = copy_to_user((void *)afdata->af_statistics_buf,
556+ (void *)afstat.af_buff[i].virt_addr,
557+ afstat.curr_cfg_buf_size);
558+ if (ret) {
559+ printk(KERN_ERR "Failed copy_to_user for "
560+ "H3A stats buff, %d\n", ret);
561+ }
562+ afdata->xtrastats.ts = afstat.af_buff[i].xtrastats.ts;
563+ afdata->xtrastats.field_count =
564+ afstat.af_buff[i].xtrastats.field_count;
565+ return 0;
566+ }
567+ }
568+ spin_unlock_irqrestore(&afstat.buffer_lock, irqflags);
569+ /* Stats unavailable */
570+
571+ return -1;
572+}
573+
574+void isp_af_notify(int notify)
575+{
576+ camnotify = notify;
577+ if (camnotify && afstat.initialized) {
578+ printk(KERN_DEBUG "Warning Camera Off \n");
579+ afstat.stats_req = 0;
580+ afstat.stats_done = 1;
581+ wake_up_interruptible(&afstat.stats_wait);
582+ }
583+}
584+EXPORT_SYMBOL(isp_af_notify);
585+/*
586+ * This API allows the user to update White Balance gains, as well as
587+ * exposure time and analog gain. It is also used to request frame
588+ * statistics.
589+ */
590+int isp_af_request_statistics(struct isp_af_data *afdata)
591+{
592+ int ret = 0;
593+ u16 frame_diff = 0;
594+ u16 frame_cnt = afstat.frame_count;
595+ wait_queue_t wqt;
596+
597+ if (!af_dev_configptr->config->af_config) {
598+ printk(KERN_ERR "AF engine not enabled\n");
599+ return -EINVAL;
600+ }
601+
602+ if (!(afdata->update & REQUEST_STATISTICS)) {
603+ afdata->af_statistics_buf = NULL;
604+ goto out;
605+ }
606+
607+ isp_af_unlock_buffers();
608+ /* Stats available? */
609+ DPRINTK_ISP_AF("Stats available?\n");
610+ ret = isp_af_stats_available(afdata);
611+ if (!ret)
612+ goto out;
613+
614+ /* Stats in near future? */
615+ DPRINTK_ISP_AF("Stats in near future?\n");
616+ if (afdata->frame_number > frame_cnt)
617+ frame_diff = afdata->frame_number - frame_cnt;
618+ else if (afdata->frame_number < frame_cnt) {
619+ if (frame_cnt > MAX_FRAME_COUNT - MAX_FUTURE_FRAMES
620+ && afdata->frame_number < MAX_FRAME_COUNT) {
621+ frame_diff = afdata->frame_number + MAX_FRAME_COUNT -
622+ frame_cnt;
623+ } else {
624+ /* Frame unavailable */
625+ frame_diff = MAX_FUTURE_FRAMES + 1;
626+ }
627+ }
628+
629+ if (frame_diff > MAX_FUTURE_FRAMES) {
630+ printk(KERN_ERR "Invalid frame requested, returning current"
631+ " frame stats\n");
632+ afdata->frame_number = frame_cnt;
633+ }
634+ if (!camnotify) {
635+ /* Block until frame in near future completes */
636+ afstat.frame_req = afdata->frame_number;
637+ afstat.stats_req = 1;
638+ afstat.stats_done = 0;
639+ init_waitqueue_entry(&wqt, current);
640+ ret = wait_event_interruptible(afstat.stats_wait,
641+ afstat.stats_done == 1);
642+ if (ret < 0) {
643+ afdata->af_statistics_buf = NULL;
644+ return ret;
645+ }
646+ DPRINTK_ISP_AF("ISP AF request status interrupt raised\n");
647+
648+ /* Stats now available */
649+ ret = isp_af_stats_available(afdata);
650+ if (ret) {
651+ printk(KERN_ERR "After waiting for stats, stats not"
652+ " available!!\n");
653+ afdata->af_statistics_buf = NULL;
654+ }
655+ }
656+
657+out:
658+ afdata->curr_frame = afstat.frame_count;
659+
660+ return 0;
661+}
662+EXPORT_SYMBOL(isp_af_request_statistics);
663+
664+/* This function will handle the H3A interrupt. */
665+static void isp_af_isr(unsigned long status, isp_vbq_callback_ptr arg1,
666+ void *arg2)
667+{
668+ u16 frame_align;
669+
670+ if ((H3A_AF_DONE & status) != H3A_AF_DONE)
671+ return;
672+
673+ /* timestamp stats buffer */
674+ do_gettimeofday(&active_buff->xtrastats.ts);
675+ active_buff->config_counter = atomic_read(&afstat.config_counter);
676+
677+ /* Exchange buffers */
678+ active_buff = active_buff->next;
679+ if (active_buff->locked == 1)
680+ active_buff = active_buff->next;
681+ isp_af_set_address(active_buff->ispmmu_addr);
682+
683+ /* Update frame counter */
684+ afstat.frame_count++;
685+ frame_align = afstat.frame_count;
686+ if (afstat.frame_count > MAX_FRAME_COUNT) {
687+ afstat.frame_count = 1;
688+ frame_align++;
689+ }
690+ active_buff->frame_num = afstat.frame_count;
691+
692+ /* Future Stats requested? */
693+ if (afstat.stats_req) {
694+ /* Is the frame we want already done? */
695+ if (frame_align >= afstat.frame_req + 1) {
696+ afstat.stats_req = 0;
697+ afstat.stats_done = 1;
698+ wake_up_interruptible(&afstat.stats_wait);
699+ }
700+ }
701+}
702+
703+int __isp_af_enable(int enable)
704+{
705+ unsigned int pcr;
706+
707+ pcr = isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
708+
709+ /* Set AF_EN bit in PCR Register */
710+ if (enable) {
711+ if (isp_set_callback(CBK_H3A_AF_DONE, isp_af_isr,
712+ (void *)NULL, (void *)NULL)) {
713+ printk(KERN_ERR "No callback for AF\n");
714+ return -EINVAL;
715+ }
716+
717+ pcr |= AF_EN;
718+ } else {
719+ isp_unset_callback(CBK_H3A_AF_DONE);
720+ pcr &= ~AF_EN;
721+ }
722+ isp_reg_writel(pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
723+ return 0;
724+}
725+
726+/* Function to Enable/Disable AF Engine */
727+int isp_af_enable(int enable)
728+{
729+ int rval;
730+
731+ rval = __isp_af_enable(enable);
732+
733+ if (!rval)
734+ afstat.pm_state = enable;
735+
736+ return rval;
737+}
738+
739+/* Function to Suspend AF Engine */
740+void isp_af_suspend(void)
741+{
742+ if (afstat.pm_state)
743+ __isp_af_enable(0);
744+}
745+
746+/* Function to Resume AF Engine */
747+void isp_af_resume(void)
748+{
749+ if (afstat.pm_state)
750+ __isp_af_enable(1);
751+}
752+
753+int isp_af_busy(void)
754+{
755+ return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
756+ & ISPH3A_PCR_BUSYAF;
757+}
758+
759+/* Function to register the AF character device driver. */
760+int __init isp_af_init(void)
761+{
762+ /*allocate memory for device structure and initialize it with 0 */
763+ af_dev_configptr = kzalloc(sizeof(struct af_device), GFP_KERNEL);
764+ if (!af_dev_configptr)
765+ goto err_nomem1;
766+
767+ active_buff = NULL;
768+
769+ af_dev_configptr->config = (struct af_configuration *)
770+ kzalloc(sizeof(struct af_configuration), GFP_KERNEL);
771+
772+ if (af_dev_configptr->config == NULL)
773+ goto err_nomem2;
774+
775+ memset(&afstat, 0, sizeof(afstat));
776+
777+ init_waitqueue_head(&afstat.stats_wait);
778+ spin_lock_init(&afstat.buffer_lock);
779+
780+ return 0;
781+
782+err_nomem2:
783+ kfree(af_dev_configptr);
784+err_nomem1:
785+ printk(KERN_ERR "Error: kmalloc fail");
786+ return -ENOMEM;
787+}
788+
789+void isp_af_exit(void)
790+{
791+ int i;
792+
793+ /* Free buffers */
794+ for (i = 0; i < H3A_MAX_BUFF; i++) {
795+ if (!afstat.af_buff[i].phy_addr)
796+ continue;
797+
798+ ispmmu_kunmap(afstat.af_buff[i].ispmmu_addr);
799+
800+ dma_free_coherent(NULL,
801+ afstat.min_buf_size,
802+ (void *)afstat.af_buff[i].virt_addr,
803+ (dma_addr_t)afstat.af_buff[i].phy_addr);
804+ }
805+ kfree(af_dev_configptr->config);
806+ kfree(af_dev_configptr);
807+
808+ memset(&afstat, 0, sizeof(afstat));
809+
810+ af_major = -1;
811+}
812diff --git a/drivers/media/video/isp/isp_af.h b/drivers/media/video/isp/isp_af.h
813new file mode 100644
814index 0000000..ee2b89f
815--- /dev/null
816+++ b/drivers/media/video/isp/isp_af.h
817@@ -0,0 +1,125 @@
818+/*
819+ * isp_af.h
820+ *
821+ * Include file for AF module in TI's OMAP3 Camera ISP
822+ *
823+ * Copyright (C) 2009 Texas Instruments, Inc.
824+ *
825+ * Contributors:
826+ * Sergio Aguirre <saaguirre@ti.com>
827+ * Troy Laramy
828+ *
829+ * This package is free software; you can redistribute it and/or modify
830+ * it under the terms of the GNU General Public License version 2 as
831+ * published by the Free Software Foundation.
832+ *
833+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
834+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
835+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
836+ */
837+
838+/* Device Constants */
839+#ifndef OMAP_ISP_AF_H
840+#define OMAP_ISP_AF_H
841+
842+#include <mach/isp_user.h>
843+
844+#define AF_MAJOR_NUMBER 0
845+#define ISPAF_NAME "OMAPISP_AF"
846+#define AF_NR_DEVS 1
847+#define AF_TIMEOUT ((300 * HZ) / 1000)
848+
849+
850+
851+/* Print Macros */
852+/*list of error code */
853+#define AF_ERR_HZ_COUNT 800 /* Invalid Horizontal Count */
854+#define AF_ERR_VT_COUNT 801 /* Invalid Vertical Count */
855+#define AF_ERR_HEIGHT 802 /* Invalid Height */
856+#define AF_ERR_WIDTH 803 /* Invalid width */
857+#define AF_ERR_INCR 804 /* Invalid Increment */
858+#define AF_ERR_HZ_START 805 /* Invalid horizontal Start */
859+#define AF_ERR_VT_START 806 /* Invalud vertical Start */
860+#define AF_ERR_IIRSH 807 /* Invalid IIRSH value */
861+#define AF_ERR_IIR_COEF 808 /* Invalid Coefficient */
862+#define AF_ERR_SETUP 809 /* Setup not done */
863+#define AF_ERR_THRESHOLD 810 /* Invalid Threshold */
864+#define AF_ERR_ENGINE_BUSY 811 /* Engine is busy */
865+
866+#define AFPID 0x0 /* Peripheral Revision
867+ * and Class Information
868+ */
869+
870+#define AFCOEF_OFFSET 0x00000004 /* COEFFICIENT BASE
871+ * ADDRESS
872+ */
873+
874+/*
875+ * PCR fields
876+ */
877+#define AF_BUSYAF (1 << 15)
878+#define FVMODE (1 << 14)
879+#define RGBPOS (0x7 << 11)
880+#define MED_TH (0xFF << 3)
881+#define AF_MED_EN (1 << 2)
882+#define AF_ALAW_EN (1 << 1)
883+#define AF_EN (1 << 0)
884+
885+/*
886+ * AFPAX1 fields
887+ */
888+#define PAXW (0x7F << 16)
889+#define PAXH 0x7F
890+
891+/*
892+ * AFPAX2 fields
893+ */
894+#define AFINCV (0xF << 13)
895+#define PAXVC (0x7F << 6)
896+#define PAXHC 0x3F
897+
898+/*
899+ * AFPAXSTART fields
900+ */
901+#define PAXSH (0xFFF<<16)
902+#define PAXSV 0xFFF
903+
904+/*
905+ * COEFFICIENT MASK
906+ */
907+
908+#define COEF_MASK0 0xFFF
909+#define COEF_MASK1 (0xFFF<<16)
910+
911+/* BIT SHIFTS */
912+#define AF_RGBPOS_SHIFT 11
913+#define AF_MED_TH_SHIFT 3
914+#define AF_PAXW_SHIFT 16
915+#define AF_LINE_INCR_SHIFT 13
916+#define AF_VT_COUNT_SHIFT 6
917+#define AF_HZ_START_SHIFT 16
918+#define AF_COEF_SHIFT 16
919+
920+#define AF_UPDATEXS_TS (1 << 0)
921+#define AF_UPDATEXS_FIELDCOUNT (1 << 1)
922+#define AF_UPDATEXS_LENSPOS (1 << 2)
923+
924+/* Structure for device of AF Engine */
925+struct af_device {
926+ struct af_configuration *config; /*Device configuration structure */
927+ int size_paxel; /*Paxel size in bytes */
928+};
929+
930+int isp_af_check_paxel(void);
931+int isp_af_check_iir(void);
932+int isp_af_register_setup(struct af_device *af_dev);
933+int isp_af_enable(int);
934+void isp_af_suspend(void);
935+void isp_af_resume(void);
936+int isp_af_busy(void);
937+void isp_af_notify(int notify);
938+int isp_af_request_statistics(struct isp_af_data *afdata);
939+int isp_af_configure(struct af_configuration *afconfig);
940+void isp_af_set_address(unsigned long);
941+void isp_af_setxtrastats(struct isp_af_xtrastats *xtrastats, u8 updateflag);
942+#endif /* OMAP_ISP_AF_H */
943diff --git a/drivers/media/video/isp/isph3a.c b/drivers/media/video/isp/isph3a.c
944new file mode 100644
945index 0000000..7ff1c5b
946--- /dev/null
947+++ b/drivers/media/video/isp/isph3a.c
948@@ -0,0 +1,932 @@
949+/*
950+ * isph3a.c
951+ *
952+ * H3A module for TI's OMAP3 Camera ISP
953+ *
954+ * Copyright (C) 2009 Texas Instruments, Inc.
955+ *
956+ * Contributors:
957+ * Sergio Aguirre <saaguirre@ti.com>
958+ * Troy Laramy
959+ *
960+ * This package is free software; you can redistribute it and/or modify
961+ * it under the terms of the GNU General Public License version 2 as
962+ * published by the Free Software Foundation.
963+ *
964+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
965+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
966+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
967+ */
968+
969+#include <asm/cacheflush.h>
970+
971+#include <linux/dma-mapping.h>
972+#include <linux/uaccess.h>
973+
974+#include "isp.h"
975+#include "ispreg.h"
976+#include "isph3a.h"
977+#include "ispmmu.h"
978+#include "isppreview.h"
979+
980+/**
981+ * struct isph3a_aewb_buffer - AE, AWB frame stats buffer.
982+ * @virt_addr: Virtual address to mmap the buffer.
983+ * @phy_addr: Physical address of the buffer.
984+ * @addr_align: Virtual Address 32 bytes aligned.
985+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
986+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
987+ * @locked: 1 - Buffer locked from write. 0 - Buffer can be overwritten.
988+ * @frame_num: Frame number from which the statistics are taken.
989+ * @next: Pointer to link next buffer.
990+ */
991+struct isph3a_aewb_buffer {
992+ unsigned long virt_addr;
993+ unsigned long phy_addr;
994+ unsigned long addr_align;
995+ unsigned long ispmmu_addr;
996+ unsigned long mmap_addr; /* For userspace */
997+ struct timeval ts;
998+ u32 config_counter;
999+
1000+ u8 locked;
1001+ u16 frame_num;
1002+ struct isph3a_aewb_buffer *next;
1003+};
1004+
1005+/**
1006+ * struct isph3a_aewb_status - AE, AWB status.
1007+ * @initialized: 1 - Buffers initialized.
1008+ * @update: 1 - Update registers.
1009+ * @stats_req: 1 - Future stats requested.
1010+ * @stats_done: 1 - Stats ready for user.
1011+ * @frame_req: Number of frame requested for statistics.
1012+ * @h3a_buff: Array of statistics buffers to access.
1013+ * @stats_buf_size: Statistics buffer size.
1014+ * @min_buf_size: Minimum statisitics buffer size.
1015+ * @win_count: Window Count.
1016+ * @frame_count: Frame Count.
1017+ * @stats_wait: Wait primitive for locking/unlocking the stats request.
1018+ * @buffer_lock: Spinlock for statistics buffers access.
1019+ */
1020+static struct isph3a_aewb_status {
1021+ u8 initialized;
1022+ u8 update;
1023+ u8 stats_req;
1024+ u8 stats_done;
1025+ u16 frame_req;
1026+ int pm_state;
1027+
1028+ struct isph3a_aewb_buffer h3a_buff[H3A_MAX_BUFF];
1029+ unsigned int stats_buf_size;
1030+ unsigned int min_buf_size;
1031+ unsigned int curr_cfg_buf_size;
1032+
1033+ atomic_t config_counter;
1034+
1035+ u16 win_count;
1036+ u32 frame_count;
1037+ wait_queue_head_t stats_wait;
1038+ spinlock_t buffer_lock; /* For stats buffers read/write sync */
1039+} aewbstat;
1040+
1041+/**
1042+ * struct isph3a_aewb_regs - Current value of AE, AWB configuration registers.
1043+ * reg_pcr: Peripheral control register.
1044+ * reg_win1: Control register.
1045+ * reg_start: Start position register.
1046+ * reg_blk: Black line register.
1047+ * reg_subwin: Configuration register.
1048+ */
1049+static struct isph3a_aewb_regs {
1050+ u32 reg_pcr;
1051+ u32 reg_win1;
1052+ u32 reg_start;
1053+ u32 reg_blk;
1054+ u32 reg_subwin;
1055+} aewb_regs;
1056+
1057+static struct isph3a_aewb_config aewb_config_local = {
1058+ .saturation_limit = 0x3FF,
1059+ .win_height = 0,
1060+ .win_width = 0,
1061+ .ver_win_count = 0,
1062+ .hor_win_count = 0,
1063+ .ver_win_start = 0,
1064+ .hor_win_start = 0,
1065+ .blk_ver_win_start = 0,
1066+ .blk_win_height = 0,
1067+ .subsample_ver_inc = 0,
1068+ .subsample_hor_inc = 0,
1069+ .alaw_enable = 0,
1070+ .aewb_enable = 0,
1071+};
1072+
1073+/* Structure for saving/restoring h3a module registers */
1074+static struct isp_reg isph3a_reg_list[] = {
1075+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, 0}, /* Should be the first one */
1076+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1, 0},
1077+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART, 0},
1078+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK, 0},
1079+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN, 0},
1080+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST, 0},
1081+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1, 0},
1082+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2, 0},
1083+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAXSTART, 0},
1084+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH, 0},
1085+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFBUFST, 0},
1086+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF010, 0},
1087+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF032, 0},
1088+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF054, 0},
1089+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF076, 0},
1090+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF098, 0},
1091+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010, 0},
1092+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF110, 0},
1093+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF132, 0},
1094+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF154, 0},
1095+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF176, 0},
1096+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF198, 0},
1097+ {OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010, 0},
1098+ {0, ISP_TOK_TERM, 0}
1099+};
1100+
1101+static struct ispprev_wbal h3awb_update;
1102+static struct isph3a_aewb_buffer *active_buff;
1103+static struct isph3a_aewb_xtrastats h3a_xtrastats[H3A_MAX_BUFF];
1104+static int camnotify;
1105+static int wb_update;
1106+static void isph3a_print_status(void);
1107+
1108+/**
1109+ * isph3a_aewb_setxtrastats - Receives extra statistics from prior frames.
1110+ * @xtrastats: Pointer to structure containing extra statistics fields like
1111+ * field count and timestamp of frame.
1112+ *
1113+ * Called from update_vbq in camera driver
1114+ **/
1115+void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats)
1116+{
1117+ int i;
1118+
1119+ if (active_buff == NULL)
1120+ return;
1121+
1122+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1123+ if (aewbstat.h3a_buff[i].frame_num != active_buff->frame_num)
1124+ continue;
1125+
1126+ if (i == 0) {
1127+ if (aewbstat.h3a_buff[H3A_MAX_BUFF - 1].locked == 0) {
1128+ h3a_xtrastats[H3A_MAX_BUFF - 1] =
1129+ *xtrastats;
1130+ } else {
1131+ h3a_xtrastats[H3A_MAX_BUFF - 2] =
1132+ *xtrastats;
1133+ }
1134+ } else if (i == 1) {
1135+ if (aewbstat.h3a_buff[0].locked == 0)
1136+ h3a_xtrastats[0] = *xtrastats;
1137+ else {
1138+ h3a_xtrastats[H3A_MAX_BUFF - 1] =
1139+ *xtrastats;
1140+ }
1141+ } else {
1142+ if (aewbstat.h3a_buff[i - 1].locked == 0)
1143+ h3a_xtrastats[i - 1] = *xtrastats;
1144+ else
1145+ h3a_xtrastats[i - 2] = *xtrastats;
1146+ }
1147+ return;
1148+ }
1149+}
1150+EXPORT_SYMBOL(isph3a_aewb_setxtrastats);
1151+
1152+void __isph3a_aewb_enable(u8 enable)
1153+{
1154+ isp_reg_writel(IRQ0STATUS_H3A_AWB_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
1155+ ISP_IRQ0STATUS);
1156+
1157+ if (enable) {
1158+ aewb_regs.reg_pcr |= ISPH3A_PCR_AEW_EN;
1159+ DPRINTK_ISPH3A(" H3A enabled \n");
1160+ } else {
1161+ aewb_regs.reg_pcr &= ~ISPH3A_PCR_AEW_EN;
1162+ DPRINTK_ISPH3A(" H3A disabled \n");
1163+ }
1164+ isp_reg_and_or(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR, ~ISPH3A_PCR_AEW_EN,
1165+ (enable ? ISPH3A_PCR_AEW_EN : 0));
1166+ aewb_config_local.aewb_enable = enable;
1167+}
1168+
1169+/**
1170+ * isph3a_aewb_enable - Enables AE, AWB engine in the H3A module.
1171+ * @enable: 1 - Enables the AE & AWB engine.
1172+ *
1173+ * Client should configure all the AE & AWB registers in H3A before this.
1174+ **/
1175+void isph3a_aewb_enable(u8 enable)
1176+{
1177+ __isph3a_aewb_enable(enable);
1178+ aewbstat.pm_state = enable;
1179+}
1180+
1181+/**
1182+ * isph3a_aewb_suspend - Suspend AE, AWB engine in the H3A module.
1183+ **/
1184+void isph3a_aewb_suspend(void)
1185+{
1186+ if (aewbstat.pm_state)
1187+ __isph3a_aewb_enable(0);
1188+}
1189+
1190+/**
1191+ * isph3a_aewb_resume - Resume AE, AWB engine in the H3A module.
1192+ **/
1193+void isph3a_aewb_resume(void)
1194+{
1195+ if (aewbstat.pm_state)
1196+ __isph3a_aewb_enable(1);
1197+}
1198+
1199+int isph3a_aewb_busy(void)
1200+{
1201+ return isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
1202+ & ISPH3A_PCR_BUSYAEAWB;
1203+}
1204+
1205+/**
1206+ * isph3a_update_wb - Updates WB parameters.
1207+ *
1208+ * Needs to be called when no ISP Preview processing is taking place.
1209+ **/
1210+void isph3a_update_wb(void)
1211+{
1212+ if (wb_update) {
1213+ isppreview_config_whitebalance(h3awb_update);
1214+ wb_update = 0;
1215+ }
1216+ return;
1217+}
1218+EXPORT_SYMBOL(isph3a_update_wb);
1219+
1220+/**
1221+ * isph3a_aewb_update_regs - Helper function to update h3a registers.
1222+ **/
1223+static void isph3a_aewb_update_regs(void)
1224+{
1225+ isp_reg_writel(aewb_regs.reg_pcr, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR);
1226+ isp_reg_writel(aewb_regs.reg_win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
1227+ isp_reg_writel(aewb_regs.reg_start, OMAP3_ISP_IOMEM_H3A,
1228+ ISPH3A_AEWINSTART);
1229+ isp_reg_writel(aewb_regs.reg_blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
1230+ isp_reg_writel(aewb_regs.reg_subwin, OMAP3_ISP_IOMEM_H3A,
1231+ ISPH3A_AEWSUBWIN);
1232+
1233+ aewbstat.update = 0;
1234+ aewbstat.frame_count = 1;
1235+}
1236+
1237+/**
1238+ * isph3a_aewb_update_req_buffer - Helper function to update buffer cache pages
1239+ * @buffer: Pointer to structure
1240+ **/
1241+static void isph3a_aewb_update_req_buffer(struct isph3a_aewb_buffer *buffer)
1242+{
1243+ int size = aewbstat.stats_buf_size;
1244+
1245+ size = PAGE_ALIGN(size);
1246+ dmac_inv_range((void *)buffer->addr_align,
1247+ (void *)buffer->addr_align + size);
1248+}
1249+
1250+/**
1251+ * isph3a_aewb_stats_available - Check for stats available of specified frame.
1252+ * @aewbdata: Pointer to return AE AWB statistics data
1253+ *
1254+ * Returns 0 if successful, or -1 if statistics are unavailable.
1255+ **/
1256+static int isph3a_aewb_stats_available(struct isph3a_aewb_data *aewbdata)
1257+{
1258+ int i, ret;
1259+ unsigned long irqflags;
1260+
1261+ spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
1262+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1263+ DPRINTK_ISPH3A("Checking Stats buff[%d] (%d) for %d\n",
1264+ i, aewbstat.h3a_buff[i].frame_num,
1265+ aewbdata->frame_number);
1266+ if ((aewbdata->frame_number !=
1267+ aewbstat.h3a_buff[i].frame_num) ||
1268+ (aewbstat.h3a_buff[i].frame_num ==
1269+ active_buff->frame_num))
1270+ continue;
1271+ aewbstat.h3a_buff[i].locked = 1;
1272+ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1273+ isph3a_aewb_update_req_buffer(&aewbstat.h3a_buff[i]);
1274+ aewbstat.h3a_buff[i].frame_num = 0;
1275+ ret = copy_to_user((void *)aewbdata->h3a_aewb_statistics_buf,
1276+ (void *)aewbstat.h3a_buff[i].virt_addr,
1277+ aewbstat.curr_cfg_buf_size);
1278+ if (ret) {
1279+ printk(KERN_ERR "Failed copy_to_user for "
1280+ "H3A stats buff, %d\n", ret);
1281+ }
1282+ aewbdata->ts = aewbstat.h3a_buff[i].ts;
1283+ aewbdata->config_counter = aewbstat.h3a_buff[i].config_counter;
1284+ aewbdata->field_count = h3a_xtrastats[i].field_count;
1285+ return 0;
1286+ }
1287+ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1288+
1289+ return -1;
1290+}
1291+
1292+/**
1293+ * isph3a_aewb_link_buffers - Helper function to link allocated buffers.
1294+ **/
1295+static void isph3a_aewb_link_buffers(void)
1296+{
1297+ int i;
1298+
1299+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1300+ if ((i + 1) < H3A_MAX_BUFF) {
1301+ aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[i + 1];
1302+ h3a_xtrastats[i].next = &h3a_xtrastats[i + 1];
1303+ } else {
1304+ aewbstat.h3a_buff[i].next = &aewbstat.h3a_buff[0];
1305+ h3a_xtrastats[i].next = &h3a_xtrastats[0];
1306+ }
1307+ }
1308+}
1309+
1310+/**
1311+ * isph3a_aewb_unlock_buffers - Helper function to unlock all buffers.
1312+ **/
1313+static void isph3a_aewb_unlock_buffers(void)
1314+{
1315+ int i;
1316+ unsigned long irqflags;
1317+
1318+ spin_lock_irqsave(&aewbstat.buffer_lock, irqflags);
1319+ for (i = 0; i < H3A_MAX_BUFF; i++)
1320+ aewbstat.h3a_buff[i].locked = 0;
1321+
1322+ spin_unlock_irqrestore(&aewbstat.buffer_lock, irqflags);
1323+}
1324+
1325+/**
1326+ * isph3a_aewb_isr - Callback from ISP driver for H3A AEWB interrupt.
1327+ * @status: IRQ0STATUS in case of MMU error, 0 for H3A interrupt.
1328+ * @arg1: Not used as of now.
1329+ * @arg2: Not used as of now.
1330+ */
1331+static void isph3a_aewb_isr(unsigned long status, isp_vbq_callback_ptr arg1,
1332+ void *arg2)
1333+{
1334+ u16 frame_align;
1335+
1336+ if ((H3A_AWB_DONE & status) != H3A_AWB_DONE)
1337+ return;
1338+
1339+ do_gettimeofday(&active_buff->ts);
1340+ active_buff->config_counter = atomic_read(&aewbstat.config_counter);
1341+ active_buff = active_buff->next;
1342+ if (active_buff->locked == 1)
1343+ active_buff = active_buff->next;
1344+ isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
1345+ ISPH3A_AEWBUFST);
1346+
1347+ aewbstat.frame_count++;
1348+ frame_align = aewbstat.frame_count;
1349+ if (aewbstat.frame_count > MAX_FRAME_COUNT) {
1350+ aewbstat.frame_count = 1;
1351+ frame_align++;
1352+ }
1353+ active_buff->frame_num = aewbstat.frame_count;
1354+
1355+ if (aewbstat.stats_req) {
1356+ DPRINTK_ISPH3A("waiting for frame %d\n", aewbstat.frame_req);
1357+ if (frame_align >= aewbstat.frame_req + 1) {
1358+ aewbstat.stats_req = 0;
1359+ aewbstat.stats_done = 1;
1360+ wake_up_interruptible(&aewbstat.stats_wait);
1361+ }
1362+ }
1363+
1364+ if (aewbstat.update)
1365+ isph3a_aewb_update_regs();
1366+}
1367+
1368+/**
1369+ * isph3a_aewb_set_params - Helper function to check & store user given params.
1370+ * @user_cfg: Pointer to AE and AWB parameters struct.
1371+ *
1372+ * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
1373+ * program them during ISR.
1374+ *
1375+ * Returns 0 if successful, or -EINVAL if any of the parameters are invalid.
1376+ **/
1377+static int isph3a_aewb_set_params(struct isph3a_aewb_config *user_cfg)
1378+{
1379+ if (unlikely(user_cfg->saturation_limit > MAX_SATURATION_LIM)) {
1380+ printk(KERN_ERR "Invalid Saturation_limit: %d\n",
1381+ user_cfg->saturation_limit);
1382+ return -EINVAL;
1383+ }
1384+ if (aewb_config_local.saturation_limit != user_cfg->saturation_limit) {
1385+ WRITE_SAT_LIM(aewb_regs.reg_pcr, user_cfg->saturation_limit);
1386+ aewb_config_local.saturation_limit =
1387+ user_cfg->saturation_limit;
1388+ aewbstat.update = 1;
1389+ }
1390+
1391+ if (aewb_config_local.alaw_enable != user_cfg->alaw_enable) {
1392+ WRITE_ALAW(aewb_regs.reg_pcr, user_cfg->alaw_enable);
1393+ aewb_config_local.alaw_enable = user_cfg->alaw_enable;
1394+ aewbstat.update = 1;
1395+ }
1396+
1397+ if (unlikely(user_cfg->win_height < MIN_WIN_H ||
1398+ user_cfg->win_height > MAX_WIN_H ||
1399+ user_cfg->win_height & 0x01)) {
1400+ printk(KERN_ERR "Invalid window height: %d\n",
1401+ user_cfg->win_height);
1402+ return -EINVAL;
1403+ }
1404+ if (aewb_config_local.win_height != user_cfg->win_height) {
1405+ WRITE_WIN_H(aewb_regs.reg_win1, user_cfg->win_height);
1406+ aewb_config_local.win_height = user_cfg->win_height;
1407+ aewbstat.update = 1;
1408+ }
1409+
1410+ if (unlikely(user_cfg->win_width < MIN_WIN_W ||
1411+ user_cfg->win_width > MAX_WIN_W ||
1412+ user_cfg->win_width & 0x01)) {
1413+ printk(KERN_ERR "Invalid window width: %d\n",
1414+ user_cfg->win_width);
1415+ return -EINVAL;
1416+ }
1417+ if (aewb_config_local.win_width != user_cfg->win_width) {
1418+ WRITE_WIN_W(aewb_regs.reg_win1, user_cfg->win_width);
1419+ aewb_config_local.win_width = user_cfg->win_width;
1420+ aewbstat.update = 1;
1421+ }
1422+
1423+ if (unlikely(user_cfg->ver_win_count < 1 ||
1424+ user_cfg->ver_win_count > MAX_WINVC)) {
1425+ printk(KERN_ERR "Invalid vertical window count: %d\n",
1426+ user_cfg->ver_win_count);
1427+ return -EINVAL;
1428+ }
1429+ if (aewb_config_local.ver_win_count != user_cfg->ver_win_count) {
1430+ WRITE_VER_C(aewb_regs.reg_win1, user_cfg->ver_win_count);
1431+ aewb_config_local.ver_win_count = user_cfg->ver_win_count;
1432+ aewbstat.update = 1;
1433+ }
1434+
1435+ if (unlikely(user_cfg->hor_win_count < 1 ||
1436+ user_cfg->hor_win_count > MAX_WINHC)) {
1437+ printk(KERN_ERR "Invalid horizontal window count: %d\n",
1438+ user_cfg->hor_win_count);
1439+ return -EINVAL;
1440+ }
1441+ if (aewb_config_local.hor_win_count != user_cfg->hor_win_count) {
1442+ WRITE_HOR_C(aewb_regs.reg_win1, user_cfg->hor_win_count);
1443+ aewb_config_local.hor_win_count = user_cfg->hor_win_count;
1444+ aewbstat.update = 1;
1445+ }
1446+
1447+ if (unlikely(user_cfg->ver_win_start > MAX_WINSTART)) {
1448+ printk(KERN_ERR "Invalid vertical window start: %d\n",
1449+ user_cfg->ver_win_start);
1450+ return -EINVAL;
1451+ }
1452+ if (aewb_config_local.ver_win_start != user_cfg->ver_win_start) {
1453+ WRITE_VER_WIN_ST(aewb_regs.reg_start, user_cfg->ver_win_start);
1454+ aewb_config_local.ver_win_start = user_cfg->ver_win_start;
1455+ aewbstat.update = 1;
1456+ }
1457+
1458+ if (unlikely(user_cfg->hor_win_start > MAX_WINSTART)) {
1459+ printk(KERN_ERR "Invalid horizontal window start: %d\n",
1460+ user_cfg->hor_win_start);
1461+ return -EINVAL;
1462+ }
1463+ if (aewb_config_local.hor_win_start != user_cfg->hor_win_start) {
1464+ WRITE_HOR_WIN_ST(aewb_regs.reg_start, user_cfg->hor_win_start);
1465+ aewb_config_local.hor_win_start = user_cfg->hor_win_start;
1466+ aewbstat.update = 1;
1467+ }
1468+
1469+ if (unlikely(user_cfg->blk_ver_win_start > MAX_WINSTART)) {
1470+ printk(KERN_ERR "Invalid black vertical window start: %d\n",
1471+ user_cfg->blk_ver_win_start);
1472+ return -EINVAL;
1473+ }
1474+ if (aewb_config_local.blk_ver_win_start !=
1475+ user_cfg->blk_ver_win_start) {
1476+ WRITE_BLK_VER_WIN_ST(aewb_regs.reg_blk,
1477+ user_cfg->blk_ver_win_start);
1478+ aewb_config_local.blk_ver_win_start =
1479+ user_cfg->blk_ver_win_start;
1480+ aewbstat.update = 1;
1481+ }
1482+
1483+ if (unlikely(user_cfg->blk_win_height < MIN_WIN_H ||
1484+ user_cfg->blk_win_height > MAX_WIN_H ||
1485+ user_cfg->blk_win_height & 0x01)) {
1486+ printk(KERN_ERR "Invalid black window height: %d\n",
1487+ user_cfg->blk_win_height);
1488+ return -EINVAL;
1489+ }
1490+ if (aewb_config_local.blk_win_height != user_cfg->blk_win_height) {
1491+ WRITE_BLK_WIN_H(aewb_regs.reg_blk, user_cfg->blk_win_height);
1492+ aewb_config_local.blk_win_height = user_cfg->blk_win_height;
1493+ aewbstat.update = 1;
1494+ }
1495+
1496+ if (unlikely(user_cfg->subsample_ver_inc < MIN_SUB_INC ||
1497+ user_cfg->subsample_ver_inc > MAX_SUB_INC ||
1498+ user_cfg->subsample_ver_inc & 0x01)) {
1499+ printk(KERN_ERR "Invalid vertical subsample increment: %d\n",
1500+ user_cfg->subsample_ver_inc);
1501+ return -EINVAL;
1502+ }
1503+ if (aewb_config_local.subsample_ver_inc !=
1504+ user_cfg->subsample_ver_inc) {
1505+ WRITE_SUB_VER_INC(aewb_regs.reg_subwin,
1506+ user_cfg->subsample_ver_inc);
1507+ aewb_config_local.subsample_ver_inc =
1508+ user_cfg->subsample_ver_inc;
1509+ aewbstat.update = 1;
1510+ }
1511+
1512+ if (unlikely(user_cfg->subsample_hor_inc < MIN_SUB_INC ||
1513+ user_cfg->subsample_hor_inc > MAX_SUB_INC ||
1514+ user_cfg->subsample_hor_inc & 0x01)) {
1515+ printk(KERN_ERR "Invalid horizontal subsample increment: %d\n",
1516+ user_cfg->subsample_hor_inc);
1517+ return -EINVAL;
1518+ }
1519+ if (aewb_config_local.subsample_hor_inc !=
1520+ user_cfg->subsample_hor_inc) {
1521+ WRITE_SUB_HOR_INC(aewb_regs.reg_subwin,
1522+ user_cfg->subsample_hor_inc);
1523+ aewb_config_local.subsample_hor_inc =
1524+ user_cfg->subsample_hor_inc;
1525+ aewbstat.update = 1;
1526+ }
1527+
1528+ if (!aewbstat.initialized || !aewb_config_local.aewb_enable) {
1529+ isph3a_aewb_update_regs();
1530+ aewbstat.initialized = 1;
1531+ }
1532+ return 0;
1533+}
1534+
1535+/**
1536+ * isph3a_aewb_configure - Configure AEWB regs, enable/disable H3A engine.
1537+ * @aewbcfg: Pointer to AEWB config structure.
1538+ *
1539+ * Returns 0 if successful, -EINVAL if aewbcfg pointer is NULL, -ENOMEM if
1540+ * was unable to allocate memory for the buffer, of other errors if H3A
1541+ * callback is not set or the parameters for AEWB are invalid.
1542+ **/
1543+int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg)
1544+{
1545+ int ret = 0;
1546+ int i;
1547+ int win_count = 0;
1548+
1549+ if (NULL == aewbcfg) {
1550+ printk(KERN_ERR "Null argument in configuration. \n");
1551+ return -EINVAL;
1552+ }
1553+
1554+ if (!aewbstat.initialized) {
1555+ DPRINTK_ISPH3A("Setting callback for H3A\n");
1556+ ret = isp_set_callback(CBK_H3A_AWB_DONE, isph3a_aewb_isr,
1557+ (void *)NULL, (void *)NULL);
1558+ if (ret) {
1559+ printk(KERN_ERR "No callback for H3A\n");
1560+ return ret;
1561+ }
1562+ }
1563+
1564+ ret = isph3a_aewb_set_params(aewbcfg);
1565+ if (ret) {
1566+ printk(KERN_ERR "Invalid parameters! \n");
1567+ return ret;
1568+ }
1569+
1570+ win_count = aewbcfg->ver_win_count * aewbcfg->hor_win_count;
1571+ win_count += aewbcfg->hor_win_count;
1572+ ret = win_count / 8;
1573+ win_count += win_count % 8 ? 1 : 0;
1574+ win_count += ret;
1575+
1576+ aewbstat.win_count = win_count;
1577+ aewbstat.curr_cfg_buf_size = win_count * AEWB_PACKET_SIZE;
1578+
1579+ if (aewbstat.stats_buf_size
1580+ && win_count * AEWB_PACKET_SIZE > aewbstat.stats_buf_size) {
1581+ DPRINTK_ISPH3A("There was a previous buffer... "
1582+ "Freeing/unmapping current stat busffs\n");
1583+ isph3a_aewb_enable(0);
1584+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1585+ ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
1586+ dma_free_coherent(
1587+ NULL,
1588+ aewbstat.min_buf_size,
1589+ (void *)aewbstat.h3a_buff[i].virt_addr,
1590+ (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
1591+ aewbstat.h3a_buff[i].virt_addr = 0;
1592+ }
1593+ aewbstat.stats_buf_size = 0;
1594+ }
1595+
1596+ if (!aewbstat.h3a_buff[0].virt_addr) {
1597+ aewbstat.stats_buf_size = win_count * AEWB_PACKET_SIZE;
1598+ aewbstat.min_buf_size = PAGE_ALIGN(aewbstat.stats_buf_size);
1599+
1600+ DPRINTK_ISPH3A("Allocating/mapping new stat buffs\n");
1601+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1602+ aewbstat.h3a_buff[i].virt_addr =
1603+ (unsigned long)dma_alloc_coherent(
1604+ NULL,
1605+ aewbstat.min_buf_size,
1606+ (dma_addr_t *)
1607+ &aewbstat.h3a_buff[i].phy_addr,
1608+ GFP_KERNEL | GFP_DMA);
1609+ if (aewbstat.h3a_buff[i].virt_addr == 0) {
1610+ printk(KERN_ERR "Can't acquire memory for "
1611+ "buffer[%d]\n", i);
1612+ return -ENOMEM;
1613+ }
1614+ aewbstat.h3a_buff[i].addr_align =
1615+ aewbstat.h3a_buff[i].virt_addr;
1616+ while ((aewbstat.h3a_buff[i].addr_align & 0xFFFFFFC0) !=
1617+ aewbstat.h3a_buff[i].addr_align)
1618+ aewbstat.h3a_buff[i].addr_align++;
1619+ aewbstat.h3a_buff[i].ispmmu_addr =
1620+ ispmmu_kmap(aewbstat.h3a_buff[i].phy_addr,
1621+ aewbstat.min_buf_size);
1622+ }
1623+ isph3a_aewb_unlock_buffers();
1624+ isph3a_aewb_link_buffers();
1625+
1626+ if (active_buff == NULL)
1627+ active_buff = &aewbstat.h3a_buff[0];
1628+
1629+ isp_reg_writel(active_buff->ispmmu_addr, OMAP3_ISP_IOMEM_H3A,
1630+ ISPH3A_AEWBUFST);
1631+ }
1632+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1633+ DPRINTK_ISPH3A("buff[%d] addr is:\n virt 0x%lX\n"
1634+ " aligned 0x%lX\n"
1635+ " phys 0x%lX\n"
1636+ " ispmmu 0x%08lX\n"
1637+ " mmapped 0x%lX\n"
1638+ " frame_num %d\n", i,
1639+ aewbstat.h3a_buff[i].virt_addr,
1640+ aewbstat.h3a_buff[i].addr_align,
1641+ aewbstat.h3a_buff[i].phy_addr,
1642+ aewbstat.h3a_buff[i].ispmmu_addr,
1643+ aewbstat.h3a_buff[i].mmap_addr,
1644+ aewbstat.h3a_buff[i].frame_num);
1645+ }
1646+
1647+ active_buff->frame_num = 1;
1648+
1649+ atomic_inc(&aewbstat.config_counter);
1650+ isph3a_aewb_enable(aewbcfg->aewb_enable);
1651+ isph3a_print_status();
1652+
1653+ return 0;
1654+}
1655+EXPORT_SYMBOL(isph3a_aewb_configure);
1656+
1657+/**
1658+ * isph3a_aewb_request_statistics - REquest statistics and update gains in AEWB
1659+ * @aewbdata: Pointer to return AE AWB statistics data.
1660+ *
1661+ * This API allows the user to update White Balance gains, as well as
1662+ * exposure time and analog gain. It is also used to request frame
1663+ * statistics.
1664+ *
1665+ * Returns 0 if successful, -EINVAL when H3A engine is not enabled, or other
1666+ * errors when setting gains.
1667+ **/
1668+int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata)
1669+{
1670+ int ret = 0;
1671+ u16 frame_diff = 0;
1672+ u16 frame_cnt = aewbstat.frame_count;
1673+ wait_queue_t wqt;
1674+
1675+ if (!aewb_config_local.aewb_enable) {
1676+ printk(KERN_ERR "H3A engine not enabled\n");
1677+ return -EINVAL;
1678+ }
1679+
1680+ DPRINTK_ISPH3A("isph3a_aewb_request_statistics: Enter "
1681+ "(frame req. => %d, current frame => %d,"
1682+ "update => %d)\n",
1683+ aewbdata->frame_number, frame_cnt, aewbdata->update);
1684+ DPRINTK_ISPH3A("User data received: \n");
1685+ DPRINTK_ISPH3A("Digital gain = 0x%04x\n", aewbdata->dgain);
1686+ DPRINTK_ISPH3A("WB gain b *= 0x%04x\n", aewbdata->wb_gain_b);
1687+ DPRINTK_ISPH3A("WB gain r *= 0x%04x\n", aewbdata->wb_gain_r);
1688+ DPRINTK_ISPH3A("WB gain gb = 0x%04x\n", aewbdata->wb_gain_gb);
1689+ DPRINTK_ISPH3A("WB gain gr = 0x%04x\n", aewbdata->wb_gain_gr);
1690+
1691+ if (!aewbdata->update) {
1692+ aewbdata->h3a_aewb_statistics_buf = NULL;
1693+ goto out;
1694+ }
1695+ if (aewbdata->update & SET_DIGITAL_GAIN)
1696+ h3awb_update.dgain = (u16)aewbdata->dgain;
1697+ if (aewbdata->update & SET_COLOR_GAINS) {
1698+ h3awb_update.coef0 = (u8)aewbdata->wb_gain_gr;
1699+ h3awb_update.coef1 = (u8)aewbdata->wb_gain_r;
1700+ h3awb_update.coef2 = (u8)aewbdata->wb_gain_b;
1701+ h3awb_update.coef3 = (u8)aewbdata->wb_gain_gb;
1702+ }
1703+ if (aewbdata->update & (SET_COLOR_GAINS | SET_DIGITAL_GAIN))
1704+ wb_update = 1;
1705+
1706+ if (!(aewbdata->update & REQUEST_STATISTICS)) {
1707+ aewbdata->h3a_aewb_statistics_buf = NULL;
1708+ goto out;
1709+ }
1710+
1711+ if (aewbdata->frame_number < 1) {
1712+ printk(KERN_ERR "Illeagal frame number "
1713+ "requested (%d)\n",
1714+ aewbdata->frame_number);
1715+ return -EINVAL;
1716+ }
1717+
1718+ isph3a_aewb_unlock_buffers();
1719+
1720+ DPRINTK_ISPH3A("Stats available?\n");
1721+ ret = isph3a_aewb_stats_available(aewbdata);
1722+ if (!ret)
1723+ goto out;
1724+
1725+ DPRINTK_ISPH3A("Stats in near future?\n");
1726+ if (aewbdata->frame_number > frame_cnt)
1727+ frame_diff = aewbdata->frame_number - frame_cnt;
1728+ else if (aewbdata->frame_number < frame_cnt) {
1729+ if ((frame_cnt > (MAX_FRAME_COUNT - MAX_FUTURE_FRAMES)) &&
1730+ (aewbdata->frame_number < MAX_FRAME_COUNT)) {
1731+ frame_diff = aewbdata->frame_number + MAX_FRAME_COUNT -
1732+ frame_cnt;
1733+ } else
1734+ frame_diff = MAX_FUTURE_FRAMES + 1;
1735+ }
1736+
1737+ if (frame_diff > MAX_FUTURE_FRAMES) {
1738+ printk(KERN_ERR "Invalid frame requested, returning current"
1739+ " frame stats\n");
1740+ aewbdata->frame_number = frame_cnt;
1741+ }
1742+ if (camnotify) {
1743+ DPRINTK_ISPH3A("NOT Waiting on stats IRQ for frame %d "
1744+ "because camnotify set\n",
1745+ aewbdata->frame_number);
1746+ aewbdata->h3a_aewb_statistics_buf = NULL;
1747+ goto out;
1748+ }
1749+ DPRINTK_ISPH3A("Waiting on stats IRQ for frame %d\n",
1750+ aewbdata->frame_number);
1751+ aewbstat.frame_req = aewbdata->frame_number;
1752+ aewbstat.stats_req = 1;
1753+ aewbstat.stats_done = 0;
1754+ init_waitqueue_entry(&wqt, current);
1755+ ret = wait_event_interruptible(aewbstat.stats_wait,
1756+ aewbstat.stats_done == 1);
1757+ if (ret < 0) {
1758+ printk(KERN_ERR "isph3a_aewb_request_statistics"
1759+ " Error on wait event %d\n", ret);
1760+ aewbdata->h3a_aewb_statistics_buf = NULL;
1761+ return ret;
1762+ }
1763+
1764+ DPRINTK_ISPH3A("ISP AEWB request status interrupt raised\n");
1765+ ret = isph3a_aewb_stats_available(aewbdata);
1766+ if (ret) {
1767+ DPRINTK_ISPH3A("After waiting for stats,"
1768+ " stats not available!!\n");
1769+ aewbdata->h3a_aewb_statistics_buf = NULL;
1770+ }
1771+out:
1772+ DPRINTK_ISPH3A("isph3a_aewb_request_statistics: "
1773+ "aewbdata->h3a_aewb_statistics_buf => %p\n",
1774+ aewbdata->h3a_aewb_statistics_buf);
1775+ aewbdata->curr_frame = aewbstat.frame_count;
1776+
1777+ return 0;
1778+}
1779+EXPORT_SYMBOL(isph3a_aewb_request_statistics);
1780+
1781+/**
1782+ * isph3a_aewb_init - Module Initialisation.
1783+ *
1784+ * Always returns 0.
1785+ **/
1786+int __init isph3a_aewb_init(void)
1787+{
1788+ memset(&aewbstat, 0, sizeof(aewbstat));
1789+ memset(&aewb_regs, 0, sizeof(aewb_regs));
1790+
1791+ init_waitqueue_head(&aewbstat.stats_wait);
1792+ spin_lock_init(&aewbstat.buffer_lock);
1793+ return 0;
1794+}
1795+
1796+/**
1797+ * isph3a_aewb_cleanup - Module exit.
1798+ **/
1799+void isph3a_aewb_cleanup(void)
1800+{
1801+ int i;
1802+
1803+ for (i = 0; i < H3A_MAX_BUFF; i++) {
1804+ if (!aewbstat.h3a_buff[i].phy_addr)
1805+ continue;
1806+
1807+ ispmmu_kunmap(aewbstat.h3a_buff[i].ispmmu_addr);
1808+ dma_free_coherent(NULL,
1809+ aewbstat.min_buf_size,
1810+ (void *)aewbstat.h3a_buff[i].virt_addr,
1811+ (dma_addr_t)aewbstat.h3a_buff[i].phy_addr);
1812+ }
1813+ memset(&aewbstat, 0, sizeof(aewbstat));
1814+ memset(&aewb_regs, 0, sizeof(aewb_regs));
1815+}
1816+
1817+/**
1818+ * isph3a_print_status - Debug print. Values of H3A related registers.
1819+ **/
1820+static void isph3a_print_status(void)
1821+{
1822+ DPRINTK_ISPH3A("ISPH3A_PCR = 0x%08x\n",
1823+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR));
1824+ DPRINTK_ISPH3A("ISPH3A_AEWWIN1 = 0x%08x\n",
1825+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1));
1826+ DPRINTK_ISPH3A("ISPH3A_AEWINSTART = 0x%08x\n",
1827+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINSTART));
1828+ DPRINTK_ISPH3A("ISPH3A_AEWINBLK = 0x%08x\n",
1829+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK));
1830+ DPRINTK_ISPH3A("ISPH3A_AEWSUBWIN = 0x%08x\n",
1831+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWSUBWIN));
1832+ DPRINTK_ISPH3A("ISPH3A_AEWBUFST = 0x%08x\n",
1833+ isp_reg_readl(OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST));
1834+ DPRINTK_ISPH3A("stats windows = %d\n", aewbstat.win_count);
1835+ DPRINTK_ISPH3A("stats buff size = %d\n", aewbstat.stats_buf_size);
1836+ DPRINTK_ISPH3A("currently configured stats buff size = %d\n",
1837+ aewbstat.curr_cfg_buf_size);
1838+}
1839+
1840+/**
1841+ * isph3a_notify - Unblocks user request for statistics when camera is off
1842+ * @notify: 1 - Camera is turned off
1843+ *
1844+ * Used when the user has requested statistics about a future frame, but the
1845+ * camera is turned off before it happens, and this function unblocks the
1846+ * request so the user can continue in its program.
1847+ **/
1848+void isph3a_notify(int notify)
1849+{
1850+ camnotify = notify;
1851+ if (camnotify && aewbstat.initialized) {
1852+ printk(KERN_DEBUG "Warning Camera Off \n");
1853+ aewbstat.stats_req = 0;
1854+ aewbstat.stats_done = 1;
1855+ wake_up_interruptible(&aewbstat.stats_wait);
1856+ }
1857+}
1858+EXPORT_SYMBOL(isph3a_notify);
1859+
1860+/**
1861+ * isph3a_save_context - Saves the values of the h3a module registers.
1862+ **/
1863+void isph3a_save_context(void)
1864+{
1865+ DPRINTK_ISPH3A(" Saving context\n");
1866+ isp_save_context(isph3a_reg_list);
1867+ /* Avoid enable during restore ctx */
1868+ isph3a_reg_list[0].val &= ~ISPH3A_PCR_AEW_EN;
1869+}
1870+EXPORT_SYMBOL(isph3a_save_context);
1871+
1872+/**
1873+ * isph3a_restore_context - Restores the values of the h3a module registers.
1874+ **/
1875+void isph3a_restore_context(void)
1876+{
1877+ DPRINTK_ISPH3A(" Restoring context\n");
1878+ isp_restore_context(isph3a_reg_list);
1879+}
1880+EXPORT_SYMBOL(isph3a_restore_context);
1881diff --git a/drivers/media/video/isp/isph3a.h b/drivers/media/video/isp/isph3a.h
1882new file mode 100644
1883index 0000000..7d4c765
1884--- /dev/null
1885+++ b/drivers/media/video/isp/isph3a.h
1886@@ -0,0 +1,127 @@
1887+/*
1888+ * isph3a.h
1889+ *
1890+ * Include file for H3A module in TI's OMAP3 Camera ISP
1891+ *
1892+ * Copyright (C) 2009 Texas Instruments, Inc.
1893+ *
1894+ * Contributors:
1895+ * Sergio Aguirre <saaguirre@ti.com>
1896+ * Troy Laramy
1897+ *
1898+ * This package is free software; you can redistribute it and/or modify
1899+ * it under the terms of the GNU General Public License version 2 as
1900+ * published by the Free Software Foundation.
1901+ *
1902+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1903+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1904+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1905+ */
1906+
1907+#ifndef OMAP_ISP_H3A_H
1908+#define OMAP_ISP_H3A_H
1909+
1910+#include <mach/isp_user.h>
1911+
1912+#define AEWB_PACKET_SIZE 16
1913+#define H3A_MAX_BUFF 5
1914+
1915+/* Flags for changed registers */
1916+#define PCR_CHNG (1 << 0)
1917+#define AEWWIN1_CHNG (1 << 1)
1918+#define AEWINSTART_CHNG (1 << 2)
1919+#define AEWINBLK_CHNG (1 << 3)
1920+#define AEWSUBWIN_CHNG (1 << 4)
1921+#define PRV_WBDGAIN_CHNG (1 << 5)
1922+#define PRV_WBGAIN_CHNG (1 << 6)
1923+
1924+/* ISPH3A REGISTERS bits */
1925+#define ISPH3A_PCR_AF_EN (1 << 0)
1926+#define ISPH3A_PCR_AF_ALAW_EN (1 << 1)
1927+#define ISPH3A_PCR_AF_MED_EN (1 << 2)
1928+#define ISPH3A_PCR_AF_BUSY (1 << 15)
1929+#define ISPH3A_PCR_AEW_EN (1 << 16)
1930+#define ISPH3A_PCR_AEW_ALAW_EN (1 << 17)
1931+#define ISPH3A_PCR_AEW_BUSY (1 << 18)
1932+
1933+#define WRITE_SAT_LIM(reg, sat_limit) \
1934+ (reg = (reg & (~(ISPH3A_PCR_AEW_AVE2LMT_MASK))) \
1935+ | (sat_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT))
1936+
1937+#define WRITE_ALAW(reg, alaw_en) \
1938+ (reg = (reg & (~(ISPH3A_PCR_AEW_ALAW_EN))) \
1939+ | ((alaw_en & ISPH3A_PCR_AF_ALAW_EN) \
1940+ << ISPH3A_PCR_AEW_ALAW_EN_SHIFT))
1941+
1942+#define WRITE_WIN_H(reg, height) \
1943+ (reg = (reg & (~(ISPH3A_AEWWIN1_WINH_MASK))) \
1944+ | (((height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT))
1945+
1946+#define WRITE_WIN_W(reg, width) \
1947+ (reg = (reg & (~(ISPH3A_AEWWIN1_WINW_MASK))) \
1948+ | (((width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT))
1949+
1950+#define WRITE_VER_C(reg, ver_count) \
1951+ (reg = (reg & ~(ISPH3A_AEWWIN1_WINVC_MASK)) \
1952+ | ((ver_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT))
1953+
1954+#define WRITE_HOR_C(reg, hor_count) \
1955+ (reg = (reg & ~(ISPH3A_AEWWIN1_WINHC_MASK)) \
1956+ | ((hor_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT))
1957+
1958+#define WRITE_VER_WIN_ST(reg, ver_win_st) \
1959+ (reg = (reg & ~(ISPH3A_AEWINSTART_WINSV_MASK)) \
1960+ | (ver_win_st << ISPH3A_AEWINSTART_WINSV_SHIFT))
1961+
1962+#define WRITE_HOR_WIN_ST(reg, hor_win_st) \
1963+ (reg = (reg & ~(ISPH3A_AEWINSTART_WINSH_MASK)) \
1964+ | (hor_win_st << ISPH3A_AEWINSTART_WINSH_SHIFT))
1965+
1966+#define WRITE_BLK_VER_WIN_ST(reg, blk_win_st) \
1967+ (reg = (reg & ~(ISPH3A_AEWINBLK_WINSV_MASK)) \
1968+ | (blk_win_st << ISPH3A_AEWINBLK_WINSV_SHIFT))
1969+
1970+#define WRITE_BLK_WIN_H(reg, height) \
1971+ (reg = (reg & ~(ISPH3A_AEWINBLK_WINH_MASK)) \
1972+ | (((height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT))
1973+
1974+#define WRITE_SUB_VER_INC(reg, sub_ver_inc) \
1975+ (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCV_MASK)) \
1976+ | (((sub_ver_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCV_SHIFT))
1977+
1978+#define WRITE_SUB_HOR_INC(reg, sub_hor_inc) \
1979+ (reg = (reg & ~(ISPH3A_AEWSUBWIN_AEWINCH_MASK)) \
1980+ | (((sub_hor_inc >> 1) - 1) << ISPH3A_AEWSUBWIN_AEWINCH_SHIFT))
1981+
1982+/**
1983+ * struct isph3a_aewb_xtrastats - Structure with extra statistics sent by cam.
1984+ * @field_count: Sequence number of returned framestats.
1985+ * @isph3a_aewb_xtrastats: Pointer to next buffer with extra stats.
1986+ */
1987+struct isph3a_aewb_xtrastats {
1988+ unsigned long field_count;
1989+ struct isph3a_aewb_xtrastats *next;
1990+};
1991+
1992+void isph3a_aewb_setxtrastats(struct isph3a_aewb_xtrastats *xtrastats);
1993+
1994+int isph3a_aewb_configure(struct isph3a_aewb_config *aewbcfg);
1995+
1996+int isph3a_aewb_request_statistics(struct isph3a_aewb_data *aewbdata);
1997+
1998+void isph3a_save_context(void);
1999+
2000+void isph3a_restore_context(void);
2001+
2002+void isph3a_aewb_enable(u8 enable);
2003+
2004+int isph3a_aewb_busy(void);
2005+
2006+void isph3a_aewb_suspend(void);
2007+
2008+void isph3a_aewb_resume(void);
2009+
2010+void isph3a_update_wb(void);
2011+
2012+void isph3a_notify(int notify);
2013+#endif /* OMAP_ISP_H3A_H */
2014diff --git a/drivers/media/video/isp/isphist.c b/drivers/media/video/isp/isphist.c
2015new file mode 100644
2016index 0000000..c6f6a77
2017--- /dev/null
2018+++ b/drivers/media/video/isp/isphist.c
2019@@ -0,0 +1,608 @@
2020+/*
2021+ * isphist.c
2022+ *
2023+ * HISTOGRAM module for TI's OMAP3 Camera ISP
2024+ *
2025+ * Copyright (C) 2009 Texas Instruments, Inc.
2026+ *
2027+ * Contributors:
2028+ * Sergio Aguirre <saaguirre@ti.com>
2029+ * Troy Laramy
2030+ *
2031+ * This package is free software; you can redistribute it and/or modify
2032+ * it under the terms of the GNU General Public License version 2 as
2033+ * published by the Free Software Foundation.
2034+ *
2035+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2036+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2037+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2038+ */
2039+
2040+#include <asm/cacheflush.h>
2041+
2042+#include <linux/delay.h>
2043+#include <linux/dma-mapping.h>
2044+#include <linux/uaccess.h>
2045+
2046+#include "isp.h"
2047+#include "ispreg.h"
2048+#include "isphist.h"
2049+#include "ispmmu.h"
2050+
2051+/**
2052+ * struct isp_hist_status - Histogram status.
2053+ * @hist_enable: Enables the histogram module.
2054+ * @initialized: Flag to indicate that the module is correctly initializated.
2055+ * @frame_cnt: Actual frame count.
2056+ * @frame_req: Frame requested by user.
2057+ * @completed: Flag to indicate if a frame request is completed.
2058+ */
2059+struct isp_hist_status {
2060+ u8 hist_enable;
2061+ u8 pm_state;
2062+ u8 initialized;
2063+ u8 frame_cnt;
2064+ u8 frame_req;
2065+ u8 completed;
2066+} histstat;
2067+
2068+/**
2069+ * struct isp_hist_buffer - Frame histogram buffer.
2070+ * @virt_addr: Virtual address to mmap the buffer.
2071+ * @phy_addr: Physical address of the buffer.
2072+ * @addr_align: Virtual Address 32 bytes aligned.
2073+ * @ispmmu_addr: Address of the buffer mapped by the ISPMMU.
2074+ * @mmap_addr: Mapped memory area of buffer. For userspace access.
2075+ */
2076+struct isp_hist_buffer {
2077+ unsigned long virt_addr;
2078+ unsigned long phy_addr;
2079+ unsigned long addr_align;
2080+ unsigned long ispmmu_addr;
2081+ unsigned long mmap_addr;
2082+} hist_buff;
2083+
2084+/**
2085+ * struct isp_hist_regs - Current value of Histogram configuration registers.
2086+ * @reg_pcr: Peripheral control register.
2087+ * @reg_cnt: Histogram control register.
2088+ * @reg_wb_gain: Histogram white balance gain register.
2089+ * @reg_r0_h: Region 0 horizontal register.
2090+ * @reg_r0_v: Region 0 vertical register.
2091+ * @reg_r1_h: Region 1 horizontal register.
2092+ * @reg_r1_v: Region 1 vertical register.
2093+ * @reg_r2_h: Region 2 horizontal register.
2094+ * @reg_r2_v: Region 2 vertical register.
2095+ * @reg_r3_h: Region 3 horizontal register.
2096+ * @reg_r3_v: Region 3 vertical register.
2097+ * @reg_hist_addr: Histogram address register.
2098+ * @reg_hist_data: Histogram data.
2099+ * @reg_hist_radd: Address register. When input data comes from mem.
2100+ * @reg_hist_radd_off: Address offset register. When input data comes from mem.
2101+ * @reg_h_v_info: Image size register. When input data comes from mem.
2102+ */
2103+static struct isp_hist_regs {
2104+ u32 reg_pcr;
2105+ u32 reg_cnt;
2106+ u32 reg_wb_gain;
2107+ u32 reg_r0_h;
2108+ u32 reg_r0_v;
2109+ u32 reg_r1_h;
2110+ u32 reg_r1_v;
2111+ u32 reg_r2_h;
2112+ u32 reg_r2_v;
2113+ u32 reg_r3_h;
2114+ u32 reg_r3_v;
2115+ u32 reg_hist_addr;
2116+ u32 reg_hist_data;
2117+ u32 reg_hist_radd;
2118+ u32 reg_hist_radd_off;
2119+ u32 reg_h_v_info;
2120+} hist_regs;
2121+
2122+/* Structure for saving/restoring histogram module registers */
2123+struct isp_reg isphist_reg_list[] = {
2124+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, 0},
2125+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN, 0},
2126+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ, 0},
2127+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT, 0},
2128+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ, 0},
2129+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT, 0},
2130+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ, 0},
2131+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT, 0},
2132+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ, 0},
2133+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT, 0},
2134+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR, 0},
2135+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD, 0},
2136+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF, 0},
2137+ {OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO, 0},
2138+ {0, ISP_TOK_TERM, 0}
2139+};
2140+
2141+static void isp_hist_print_status(void);
2142+
2143+void __isp_hist_enable(u8 enable)
2144+{
2145+ if (enable)
2146+ DPRINTK_ISPHIST(" histogram enabled \n");
2147+ else
2148+ DPRINTK_ISPHIST(" histogram disabled \n");
2149+
2150+ isp_reg_and_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ~ISPHIST_PCR_EN,
2151+ (enable ? ISPHIST_PCR_EN : 0));
2152+ histstat.hist_enable = enable;
2153+}
2154+
2155+/**
2156+ * isp_hist_enable - Enables ISP Histogram submodule operation.
2157+ * @enable: 1 - Enables the histogram submodule.
2158+ *
2159+ * Client should configure all the Histogram registers before calling this
2160+ * function.
2161+ **/
2162+void isp_hist_enable(u8 enable)
2163+{
2164+ __isp_hist_enable(enable);
2165+ histstat.pm_state = enable;
2166+}
2167+
2168+/**
2169+ * isp_hist_suspend - Suspend ISP Histogram submodule.
2170+ **/
2171+void isp_hist_suspend(void)
2172+{
2173+ if (histstat.pm_state)
2174+ __isp_hist_enable(0);
2175+}
2176+
2177+/**
2178+ * isp_hist_resume - Resume ISP Histogram submodule.
2179+ **/
2180+void isp_hist_resume(void)
2181+{
2182+ if (histstat.pm_state)
2183+ __isp_hist_enable(1);
2184+}
2185+
2186+int isp_hist_busy(void)
2187+{
2188+ return isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR) &
2189+ ISPHIST_PCR_BUSY;
2190+}
2191+
2192+
2193+/**
2194+ * isp_hist_update_regs - Helper function to update Histogram registers.
2195+ **/
2196+static void isp_hist_update_regs(void)
2197+{
2198+ isp_reg_writel(hist_regs.reg_pcr, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR);
2199+ isp_reg_writel(hist_regs.reg_cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
2200+ isp_reg_writel(hist_regs.reg_wb_gain, OMAP3_ISP_IOMEM_HIST,
2201+ ISPHIST_WB_GAIN);
2202+ isp_reg_writel(hist_regs.reg_r0_h, OMAP3_ISP_IOMEM_HIST,
2203+ ISPHIST_R0_HORZ);
2204+ isp_reg_writel(hist_regs.reg_r0_v, OMAP3_ISP_IOMEM_HIST,
2205+ ISPHIST_R0_VERT);
2206+ isp_reg_writel(hist_regs.reg_r1_h, OMAP3_ISP_IOMEM_HIST,
2207+ ISPHIST_R1_HORZ);
2208+ isp_reg_writel(hist_regs.reg_r1_v, OMAP3_ISP_IOMEM_HIST,
2209+ ISPHIST_R1_VERT);
2210+ isp_reg_writel(hist_regs.reg_r2_h, OMAP3_ISP_IOMEM_HIST,
2211+ ISPHIST_R2_HORZ);
2212+ isp_reg_writel(hist_regs.reg_r2_v, OMAP3_ISP_IOMEM_HIST,
2213+ ISPHIST_R2_VERT);
2214+ isp_reg_writel(hist_regs.reg_r3_h, OMAP3_ISP_IOMEM_HIST,
2215+ ISPHIST_R3_HORZ);
2216+ isp_reg_writel(hist_regs.reg_r3_v, OMAP3_ISP_IOMEM_HIST,
2217+ ISPHIST_R3_VERT);
2218+ isp_reg_writel(hist_regs.reg_hist_addr, OMAP3_ISP_IOMEM_HIST,
2219+ ISPHIST_ADDR);
2220+ isp_reg_writel(hist_regs.reg_hist_data, OMAP3_ISP_IOMEM_HIST,
2221+ ISPHIST_DATA);
2222+ isp_reg_writel(hist_regs.reg_hist_radd, OMAP3_ISP_IOMEM_HIST,
2223+ ISPHIST_RADD);
2224+ isp_reg_writel(hist_regs.reg_hist_radd_off, OMAP3_ISP_IOMEM_HIST,
2225+ ISPHIST_RADD_OFF);
2226+ isp_reg_writel(hist_regs.reg_h_v_info, OMAP3_ISP_IOMEM_HIST,
2227+ ISPHIST_H_V_INFO);
2228+}
2229+
2230+/**
2231+ * isp_hist_isr - Callback from ISP driver for HIST interrupt.
2232+ * @status: IRQ0STATUS in case of MMU error, 0 for hist interrupt.
2233+ * arg1 and arg2 Not used as of now.
2234+ **/
2235+static void isp_hist_isr(unsigned long status, isp_vbq_callback_ptr arg1,
2236+ void *arg2)
2237+{
2238+ isp_hist_enable(0);
2239+
2240+ if (!(status & HIST_DONE))
2241+ return;
2242+
2243+ if (!histstat.completed) {
2244+ if (histstat.frame_req == histstat.frame_cnt) {
2245+ histstat.frame_cnt = 0;
2246+ histstat.frame_req = 0;
2247+ histstat.completed = 1;
2248+ } else {
2249+ isp_hist_enable(1);
2250+ histstat.frame_cnt++;
2251+ }
2252+ }
2253+}
2254+
2255+/**
2256+ * isp_hist_reset_mem - clear Histogram memory before start stats engine.
2257+ *
2258+ * Returns 0 after histogram memory was cleared.
2259+ **/
2260+static int isp_hist_reset_mem(void)
2261+{
2262+ int i;
2263+
2264+ isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
2265+
2266+ for (i = 0; i < HIST_MEM_SIZE; i++)
2267+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
2268+
2269+ isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ~ISPHIST_CNT_CLR_EN);
2270+
2271+ return 0;
2272+}
2273+
2274+/**
2275+ * isp_hist_set_params - Helper function to check and store user given params.
2276+ * @user_cfg: Pointer to user configuration structure.
2277+ *
2278+ * Returns 0 on success configuration.
2279+ **/
2280+static int isp_hist_set_params(struct isp_hist_config *user_cfg)
2281+{
2282+
2283+ int reg_num = 0;
2284+ int bit_shift = 0;
2285+
2286+
2287+ if (isp_hist_busy())
2288+ return -EINVAL;
2289+
2290+ if (user_cfg->input_bit_width > MIN_BIT_WIDTH)
2291+ WRITE_DATA_SIZE(hist_regs.reg_cnt, 0);
2292+ else
2293+ WRITE_DATA_SIZE(hist_regs.reg_cnt, 1);
2294+
2295+ WRITE_SOURCE(hist_regs.reg_cnt, user_cfg->hist_source);
2296+
2297+ if (user_cfg->hist_source) {
2298+ WRITE_HV_INFO(hist_regs.reg_h_v_info, user_cfg->hist_h_v_info);
2299+
2300+ if ((user_cfg->hist_radd & ISP_32B_BOUNDARY_BUF) ==
2301+ user_cfg->hist_radd) {
2302+ WRITE_RADD(hist_regs.reg_hist_radd,
2303+ user_cfg->hist_radd);
2304+ } else {
2305+ printk(KERN_ERR "Address should be in 32 byte boundary"
2306+ "\n");
2307+ return -EINVAL;
2308+ }
2309+
2310+ if ((user_cfg->hist_radd_off & ISP_32B_BOUNDARY_OFFSET) ==
2311+ user_cfg->hist_radd_off) {
2312+ WRITE_RADD_OFF(hist_regs.reg_hist_radd_off,
2313+ user_cfg->hist_radd_off);
2314+ } else {
2315+ printk(KERN_ERR "Offset should be in 32 byte boundary"
2316+ "\n");
2317+ return -EINVAL;
2318+ }
2319+
2320+ }
2321+
2322+ isp_hist_reset_mem();
2323+ DPRINTK_ISPHIST("ISPHIST: Memory Cleared\n");
2324+ histstat.frame_req = user_cfg->hist_frames;
2325+
2326+ if (unlikely(user_cfg->wb_gain_R > MAX_WB_GAIN ||
2327+ user_cfg->wb_gain_RG > MAX_WB_GAIN ||
2328+ user_cfg->wb_gain_B > MAX_WB_GAIN ||
2329+ user_cfg->wb_gain_BG > MAX_WB_GAIN)) {
2330+ printk(KERN_ERR "Invalid WB gain\n");
2331+ return -EINVAL;
2332+ } else {
2333+ WRITE_WB_R(hist_regs.reg_wb_gain, user_cfg->wb_gain_R);
2334+ WRITE_WB_RG(hist_regs.reg_wb_gain, user_cfg->wb_gain_RG);
2335+ WRITE_WB_B(hist_regs.reg_wb_gain, user_cfg->wb_gain_B);
2336+ WRITE_WB_BG(hist_regs.reg_wb_gain, user_cfg->wb_gain_BG);
2337+ }
2338+
2339+ /* Regions size and position */
2340+
2341+ if (user_cfg->num_regions > MAX_REGIONS)
2342+ return -EINVAL;
2343+
2344+ if (likely((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2345+ ((user_cfg->reg0_hor & ISPHIST_REGHORIZ_HSTART_MASK) >>
2346+ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2347+ WRITE_REG_HORIZ(hist_regs.reg_r0_h, user_cfg->reg0_hor);
2348+ reg_num++;
2349+ } else {
2350+ printk(KERN_ERR "Invalid Region parameters\n");
2351+ return -EINVAL;
2352+ }
2353+
2354+ if (likely((user_cfg->reg0_ver & ISPHIST_REGVERT_VEND_MASK) -
2355+ ((user_cfg->reg0_ver & ISPHIST_REGVERT_VSTART_MASK) >>
2356+ ISPHIST_REGVERT_VSTART_SHIFT))) {
2357+ WRITE_REG_VERT(hist_regs.reg_r0_v, user_cfg->reg0_ver);
2358+ } else {
2359+ printk(KERN_ERR "Invalid Region parameters\n");
2360+ return -EINVAL;
2361+ }
2362+
2363+ if (user_cfg->num_regions >= 1) {
2364+ if (likely((user_cfg->reg1_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2365+ ((user_cfg->reg1_hor &
2366+ ISPHIST_REGHORIZ_HSTART_MASK) >>
2367+ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2368+ WRITE_REG_HORIZ(hist_regs.reg_r1_h, user_cfg->reg1_hor);
2369+ } else {
2370+ printk(KERN_ERR "Invalid Region parameters\n");
2371+ return -EINVAL;
2372+ }
2373+
2374+ if (likely((user_cfg->reg1_ver & ISPHIST_REGVERT_VEND_MASK) -
2375+ ((user_cfg->reg1_ver &
2376+ ISPHIST_REGVERT_VSTART_MASK) >>
2377+ ISPHIST_REGVERT_VSTART_SHIFT))) {
2378+ WRITE_REG_VERT(hist_regs.reg_r1_v, user_cfg->reg1_ver);
2379+ } else {
2380+ printk(KERN_ERR "Invalid Region parameters\n");
2381+ return -EINVAL;
2382+ }
2383+ }
2384+
2385+ if (user_cfg->num_regions >= 2) {
2386+ if (likely((user_cfg->reg2_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2387+ ((user_cfg->reg2_hor &
2388+ ISPHIST_REGHORIZ_HSTART_MASK) >>
2389+ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2390+ WRITE_REG_HORIZ(hist_regs.reg_r2_h, user_cfg->reg2_hor);
2391+ } else {
2392+ printk(KERN_ERR "Invalid Region parameters\n");
2393+ return -EINVAL;
2394+ }
2395+
2396+ if (likely((user_cfg->reg2_ver & ISPHIST_REGVERT_VEND_MASK) -
2397+ ((user_cfg->reg2_ver &
2398+ ISPHIST_REGVERT_VSTART_MASK) >>
2399+ ISPHIST_REGVERT_VSTART_SHIFT))) {
2400+ WRITE_REG_VERT(hist_regs.reg_r2_v, user_cfg->reg2_ver);
2401+ } else {
2402+ printk(KERN_ERR "Invalid Region parameters\n");
2403+ return -EINVAL;
2404+ }
2405+ }
2406+
2407+ if (user_cfg->num_regions >= 3) {
2408+ if (likely((user_cfg->reg3_hor & ISPHIST_REGHORIZ_HEND_MASK) -
2409+ ((user_cfg->reg3_hor &
2410+ ISPHIST_REGHORIZ_HSTART_MASK) >>
2411+ ISPHIST_REGHORIZ_HSTART_SHIFT))) {
2412+ WRITE_REG_HORIZ(hist_regs.reg_r3_h, user_cfg->reg3_hor);
2413+ } else {
2414+ printk(KERN_ERR "Invalid Region parameters\n");
2415+ return -EINVAL;
2416+ }
2417+
2418+ if (likely((user_cfg->reg3_ver & ISPHIST_REGVERT_VEND_MASK) -
2419+ ((user_cfg->reg3_ver &
2420+ ISPHIST_REGVERT_VSTART_MASK) >>
2421+ ISPHIST_REGVERT_VSTART_SHIFT))) {
2422+ WRITE_REG_VERT(hist_regs.reg_r3_v, user_cfg->reg3_ver);
2423+ } else {
2424+ printk(KERN_ERR "Invalid Region parameters\n");
2425+ return -EINVAL;
2426+ }
2427+ }
2428+ reg_num = user_cfg->num_regions;
2429+ if (unlikely(((user_cfg->hist_bins > BINS_256) &&
2430+ (user_cfg->hist_bins != BINS_32)) ||
2431+ ((user_cfg->hist_bins == BINS_256) &&
2432+ reg_num != 0) || ((user_cfg->hist_bins ==
2433+ BINS_128) && reg_num >= 2))) {
2434+ printk(KERN_ERR "Invalid Bins Number: %d\n",
2435+ user_cfg->hist_bins);
2436+ return -EINVAL;
2437+ } else {
2438+ WRITE_NUM_BINS(hist_regs.reg_cnt, user_cfg->hist_bins);
2439+ }
2440+
2441+ if (user_cfg->input_bit_width > MAX_BIT_WIDTH ||
2442+ user_cfg->input_bit_width < MIN_BIT_WIDTH) {
2443+ printk(KERN_ERR "Invalid Bit Width: %d\n",
2444+ user_cfg->input_bit_width);
2445+ return -EINVAL;
2446+ } else {
2447+ switch (user_cfg->hist_bins) {
2448+ case BINS_256:
2449+ bit_shift = user_cfg->input_bit_width - 8;
2450+ break;
2451+ case BINS_128:
2452+ bit_shift = user_cfg->input_bit_width - 7;
2453+ break;
2454+ case BINS_64:
2455+ bit_shift = user_cfg->input_bit_width - 6;
2456+ break;
2457+ case BINS_32:
2458+ bit_shift = user_cfg->input_bit_width - 5;
2459+ break;
2460+ default:
2461+ return -EINVAL;
2462+ }
2463+ WRITE_BIT_SHIFT(hist_regs.reg_cnt, bit_shift);
2464+ }
2465+
2466+ isp_hist_update_regs();
2467+ histstat.initialized = 1;
2468+
2469+ return 0;
2470+}
2471+
2472+/**
2473+ * isp_hist_configure - API to configure HIST registers.
2474+ * @histcfg: Pointer to user configuration structure.
2475+ *
2476+ * Returns 0 on success configuration.
2477+ **/
2478+int isp_hist_configure(struct isp_hist_config *histcfg)
2479+{
2480+
2481+ int ret = 0;
2482+
2483+ if (NULL == histcfg) {
2484+ printk(KERN_ERR "Null argument in configuration. \n");
2485+ return -EINVAL;
2486+ }
2487+
2488+ if (!histstat.initialized) {
2489+ DPRINTK_ISPHIST("Setting callback for HISTOGRAM\n");
2490+ ret = isp_set_callback(CBK_HIST_DONE, isp_hist_isr,
2491+ (void *)NULL, (void *)NULL);
2492+ if (ret) {
2493+ printk(KERN_ERR "No callback for HIST\n");
2494+ return ret;
2495+ }
2496+ }
2497+
2498+ ret = isp_hist_set_params(histcfg);
2499+ if (ret) {
2500+ printk(KERN_ERR "Invalid parameters! \n");
2501+ return ret;
2502+ }
2503+
2504+ histstat.frame_cnt = 0;
2505+ histstat.completed = 0;
2506+ isp_hist_enable(1);
2507+ isp_hist_print_status();
2508+
2509+ return 0;
2510+}
2511+EXPORT_SYMBOL(isp_hist_configure);
2512+
2513+/**
2514+ * isp_hist_request_statistics - Request statistics in Histogram.
2515+ * @histdata: Pointer to data structure.
2516+ *
2517+ * This API allows the user to request for histogram statistics.
2518+ *
2519+ * Returns 0 on successful request.
2520+ **/
2521+int isp_hist_request_statistics(struct isp_hist_data *histdata)
2522+{
2523+ int i, ret;
2524+ u32 curr;
2525+
2526+ if (isp_hist_busy())
2527+ return -EBUSY;
2528+
2529+ if (!histstat.completed && histstat.initialized)
2530+ return -EINVAL;
2531+
2532+ isp_reg_or(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLR_EN);
2533+
2534+ for (i = 0; i < HIST_MEM_SIZE; i++) {
2535+ curr = isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
2536+ ret = put_user(curr, histdata->hist_statistics_buf + i);
2537+ if (ret) {
2538+ printk(KERN_ERR "Failed copy_to_user for "
2539+ "HIST stats buff, %d\n", ret);
2540+ }
2541+ }
2542+
2543+ isp_reg_and(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
2544+ ~ISPHIST_CNT_CLR_EN);
2545+ histstat.completed = 0;
2546+ return 0;
2547+}
2548+EXPORT_SYMBOL(isp_hist_request_statistics);
2549+
2550+/**
2551+ * isp_hist_init - Module Initialization.
2552+ *
2553+ * Returns 0 if successful.
2554+ **/
2555+int __init isp_hist_init(void)
2556+{
2557+ memset(&histstat, 0, sizeof(histstat));
2558+ memset(&hist_regs, 0, sizeof(hist_regs));
2559+
2560+ return 0;
2561+}
2562+
2563+/**
2564+ * isp_hist_cleanup - Module cleanup.
2565+ **/
2566+void isp_hist_cleanup(void)
2567+{
2568+ memset(&histstat, 0, sizeof(histstat));
2569+ memset(&hist_regs, 0, sizeof(hist_regs));
2570+}
2571+
2572+/**
2573+ * isphist_save_context - Saves the values of the histogram module registers.
2574+ **/
2575+void isphist_save_context(void)
2576+{
2577+ DPRINTK_ISPHIST(" Saving context\n");
2578+ isp_save_context(isphist_reg_list);
2579+}
2580+EXPORT_SYMBOL(isphist_save_context);
2581+
2582+/**
2583+ * isphist_restore_context - Restores the values of the histogram module regs.
2584+ **/
2585+void isphist_restore_context(void)
2586+{
2587+ DPRINTK_ISPHIST(" Restoring context\n");
2588+ isp_restore_context(isphist_reg_list);
2589+}
2590+EXPORT_SYMBOL(isphist_restore_context);
2591+
2592+/**
2593+ * isp_hist_print_status - Debug print
2594+ **/
2595+static void isp_hist_print_status(void)
2596+{
2597+ DPRINTK_ISPHIST("ISPHIST_PCR = 0x%08x\n",
2598+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR));
2599+ DPRINTK_ISPHIST("ISPHIST_CNT = 0x%08x\n",
2600+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT));
2601+ DPRINTK_ISPHIST("ISPHIST_WB_GAIN = 0x%08x\n",
2602+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN));
2603+ DPRINTK_ISPHIST("ISPHIST_R0_HORZ = 0x%08x\n",
2604+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ));
2605+ DPRINTK_ISPHIST("ISPHIST_R0_VERT = 0x%08x\n",
2606+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT));
2607+ DPRINTK_ISPHIST("ISPHIST_R1_HORZ = 0x%08x\n",
2608+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ));
2609+ DPRINTK_ISPHIST("ISPHIST_R1_VERT = 0x%08x\n",
2610+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT));
2611+ DPRINTK_ISPHIST("ISPHIST_R2_HORZ = 0x%08x\n",
2612+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ));
2613+ DPRINTK_ISPHIST("ISPHIST_R2_VERT = 0x%08x\n",
2614+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT));
2615+ DPRINTK_ISPHIST("ISPHIST_R3_HORZ = 0x%08x\n",
2616+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ));
2617+ DPRINTK_ISPHIST("ISPHIST_R3_VERT = 0x%08x\n",
2618+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT));
2619+ DPRINTK_ISPHIST("ISPHIST_ADDR = 0x%08x\n",
2620+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR));
2621+ DPRINTK_ISPHIST("ISPHIST_RADD = 0x%08x\n",
2622+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD));
2623+ DPRINTK_ISPHIST("ISPHIST_RADD_OFF = 0x%08x\n",
2624+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_RADD_OFF));
2625+ DPRINTK_ISPHIST("ISPHIST_H_V_INFO = 0x%08x\n",
2626+ isp_reg_readl(OMAP3_ISP_IOMEM_HIST, ISPHIST_H_V_INFO));
2627+}
2628diff --git a/drivers/media/video/isp/isphist.h b/drivers/media/video/isp/isphist.h
2629new file mode 100644
2630index 0000000..6b17c4e
2631--- /dev/null
2632+++ b/drivers/media/video/isp/isphist.h
2633@@ -0,0 +1,105 @@
2634+/*
2635+ * isphist.h
2636+ *
2637+ * Header file for HISTOGRAM module in TI's OMAP3 Camera ISP
2638+ *
2639+ * Copyright (C) 2009 Texas Instruments, Inc.
2640+ *
2641+ * Contributors:
2642+ * Sergio Aguirre <saaguirre@ti.com>
2643+ * Troy Laramy
2644+ *
2645+ * This package is free software; you can redistribute it and/or modify
2646+ * it under the terms of the GNU General Public License version 2 as
2647+ * published by the Free Software Foundation.
2648+ *
2649+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2650+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2651+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2652+ */
2653+
2654+#ifndef OMAP_ISP_HIST_H
2655+#define OMAP_ISP_HIST_H
2656+
2657+#include <mach/isp_user.h>
2658+
2659+#define MAX_REGIONS 0x4
2660+#define MAX_WB_GAIN 255
2661+#define MIN_WB_GAIN 0x0
2662+#define MAX_BIT_WIDTH 14
2663+#define MIN_BIT_WIDTH 8
2664+
2665+#define ISPHIST_PCR_EN (1 << 0)
2666+#define HIST_MEM_SIZE 1024
2667+#define ISPHIST_CNT_CLR_EN (1 << 7)
2668+
2669+#define WRITE_SOURCE(reg, source) \
2670+ (reg = (reg & ~(ISPHIST_CNT_SOURCE_MASK)) \
2671+ | (source << ISPHIST_CNT_SOURCE_SHIFT))
2672+
2673+#define WRITE_HV_INFO(reg, hv_info) \
2674+ (reg = ((reg & ~(ISPHIST_HV_INFO_MASK)) \
2675+ | (hv_info & ISPHIST_HV_INFO_MASK)))
2676+
2677+#define WRITE_RADD(reg, radd) \
2678+ (reg = (reg & ~(ISPHIST_RADD_MASK)) \
2679+ | (radd << ISPHIST_RADD_SHIFT))
2680+
2681+#define WRITE_RADD_OFF(reg, radd_off) \
2682+ (reg = (reg & ~(ISPHIST_RADD_OFF_MASK)) \
2683+ | (radd_off << ISPHIST_RADD_OFF_SHIFT))
2684+
2685+#define WRITE_BIT_SHIFT(reg, bit_shift) \
2686+ (reg = (reg & ~(ISPHIST_CNT_SHIFT_MASK)) \
2687+ | (bit_shift << ISPHIST_CNT_SHIFT_SHIFT))
2688+
2689+#define WRITE_DATA_SIZE(reg, data_size) \
2690+ (reg = (reg & ~(ISPHIST_CNT_DATASIZE_MASK)) \
2691+ | (data_size << ISPHIST_CNT_DATASIZE_SHIFT))
2692+
2693+#define WRITE_NUM_BINS(reg, num_bins) \
2694+ (reg = (reg & ~(ISPHIST_CNT_BINS_MASK)) \
2695+ | (num_bins << ISPHIST_CNT_BINS_SHIFT))
2696+
2697+#define WRITE_WB_R(reg, reg_wb_gain) \
2698+ reg = ((reg & ~(ISPHIST_WB_GAIN_WG00_MASK)) \
2699+ | (reg_wb_gain << ISPHIST_WB_GAIN_WG00_SHIFT))
2700+
2701+#define WRITE_WB_RG(reg, reg_wb_gain) \
2702+ (reg = (reg & ~(ISPHIST_WB_GAIN_WG01_MASK)) \
2703+ | (reg_wb_gain << ISPHIST_WB_GAIN_WG01_SHIFT))
2704+
2705+#define WRITE_WB_B(reg, reg_wb_gain) \
2706+ (reg = (reg & ~(ISPHIST_WB_GAIN_WG02_MASK)) \
2707+ | (reg_wb_gain << ISPHIST_WB_GAIN_WG02_SHIFT))
2708+
2709+#define WRITE_WB_BG(reg, reg_wb_gain) \
2710+ (reg = (reg & ~(ISPHIST_WB_GAIN_WG03_MASK)) \
2711+ | (reg_wb_gain << ISPHIST_WB_GAIN_WG03_SHIFT))
2712+
2713+#define WRITE_REG_HORIZ(reg, reg_n_hor) \
2714+ (reg = ((reg & ~ISPHIST_REGHORIZ_MASK) \
2715+ | (reg_n_hor & ISPHIST_REGHORIZ_MASK)))
2716+
2717+#define WRITE_REG_VERT(reg, reg_n_vert) \
2718+ (reg = ((reg & ~ISPHIST_REGVERT_MASK) \
2719+ | (reg_n_vert & ISPHIST_REGVERT_MASK)))
2720+
2721+
2722+void isp_hist_enable(u8 enable);
2723+
2724+int isp_hist_busy(void);
2725+
2726+int isp_hist_configure(struct isp_hist_config *histcfg);
2727+
2728+int isp_hist_request_statistics(struct isp_hist_data *histdata);
2729+
2730+void isphist_save_context(void);
2731+
2732+void isp_hist_suspend(void);
2733+
2734+void isp_hist_resume(void);
2735+
2736+void isphist_restore_context(void);
2737+
2738+#endif /* OMAP_ISP_HIST */
2739--
27401.5.6.5
2741
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
new file mode 100644
index 0000000000..842f395388
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0007-omap3isp-Add-CSI2-interface-support.patch
@@ -0,0 +1,2384 @@
1From 9fbe7b786427d981cac890a7407da09232f5d1e2 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add CSI2 interface support
5
6Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
7---
8 drivers/media/video/isp/ispcsi2.c | 2124 +++++++++++++++++++++++++++++++++++++
9 drivers/media/video/isp/ispcsi2.h | 232 ++++
10 2 files changed, 2356 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/media/video/isp/ispcsi2.c
12 create mode 100644 drivers/media/video/isp/ispcsi2.h
13
14diff --git a/drivers/media/video/isp/ispcsi2.c b/drivers/media/video/isp/ispcsi2.c
15new file mode 100644
16index 0000000..5141b5a
17--- /dev/null
18+++ b/drivers/media/video/isp/ispcsi2.c
19@@ -0,0 +1,2124 @@
20+/*
21+ * ispcsi2.c
22+ *
23+ * Driver Library for ISP CSI Control module in TI's OMAP3 Camera ISP
24+ * ISP CSI interface and IRQ related APIs are defined here.
25+ *
26+ * Copyright (C) 2009 Texas Instruments.
27+ *
28+ * Contributors:
29+ * Sergio Aguirre <saaguirre@ti.com>
30+ * Dominic Curran <dcurran@ti.com>
31+ *
32+ * This package is free software; you can redistribute it and/or modify
33+ * it under the terms of the GNU General Public License version 2 as
34+ * published by the Free Software Foundation.
35+ *
36+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
37+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
38+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39+ */
40+
41+#include <linux/delay.h>
42+#include <media/v4l2-common.h>
43+
44+#include "isp.h"
45+#include "ispreg.h"
46+#include "ispcsi2.h"
47+
48+static struct isp_csi2_cfg current_csi2_cfg;
49+static struct isp_csi2_cfg_update current_csi2_cfg_update;
50+
51+static bool update_complexio_cfg1;
52+static bool update_phy_cfg0;
53+static bool update_phy_cfg1;
54+static bool update_ctx_ctrl1[8];
55+static bool update_ctx_ctrl2[8];
56+static bool update_ctx_ctrl3[8];
57+static bool update_timing;
58+static bool update_ctrl;
59+static bool uses_videoport;
60+
61+/**
62+ * isp_csi2_complexio_lanes_config - Configuration of CSI2 ComplexIO lanes.
63+ * @reqcfg: Pointer to structure containing desired lane configuration
64+ *
65+ * Validates and saves to internal driver memory the passed configuration.
66+ * Returns 0 if successful, or -EINVAL if null pointer is passed, invalid
67+ * lane position or polarity is set, and if 2 lanes try to occupy the same
68+ * position. To apply this settings, use the isp_csi2_complexio_lanes_update()
69+ * function just after calling this function.
70+ **/
71+int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg)
72+{
73+ int i;
74+ bool pos_occupied[5] = {false, false, false, false, false};
75+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
76+ struct isp_csi2_lanes_cfg_update *currlanes_u =
77+ &current_csi2_cfg_update.lanes;
78+
79+ /* Validating parameters sent by driver */
80+ if (reqcfg == NULL) {
81+ printk(KERN_ERR "Invalid Complex IO Configuration sent by"
82+ " sensor\n");
83+ goto err_einval;
84+ }
85+
86+ /* Data lanes verification */
87+ for (i = 0; i < 4; i++) {
88+ if ((reqcfg->data[i].pol > 1) || (reqcfg->data[i].pos > 5)) {
89+ printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
90+ " parameters for data lane #%d\n", i);
91+ goto err_einval;
92+ }
93+ if (pos_occupied[reqcfg->data[i].pos - 1] &&
94+ reqcfg->data[i].pos > 0) {
95+ printk(KERN_ERR "Lane #%d already occupied\n",
96+ reqcfg->data[i].pos);
97+ goto err_einval;
98+ } else
99+ pos_occupied[reqcfg->data[i].pos - 1] = true;
100+ }
101+
102+ /* Clock lane verification */
103+ if ((reqcfg->clk.pol > 1) || (reqcfg->clk.pos > 5) ||
104+ (reqcfg->clk.pos == 0)) {
105+ printk(KERN_ERR "Invalid CSI-2 Complex IO configuration"
106+ " parameters for clock lane\n");
107+ goto err_einval;
108+ }
109+ if (pos_occupied[reqcfg->clk.pos - 1]) {
110+ printk(KERN_ERR "Lane #%d already occupied",
111+ reqcfg->clk.pos);
112+ goto err_einval;
113+ } else
114+ pos_occupied[reqcfg->clk.pos - 1] = true;
115+
116+ for (i = 0; i < 4; i++) {
117+ if (currlanes->data[i].pos != reqcfg->data[i].pos) {
118+ currlanes->data[i].pos = reqcfg->data[i].pos;
119+ currlanes_u->data[i] = true;
120+ update_complexio_cfg1 = true;
121+ }
122+ if (currlanes->data[i].pol != reqcfg->data[i].pol) {
123+ currlanes->data[i].pol = reqcfg->data[i].pol;
124+ currlanes_u->data[i] = true;
125+ update_complexio_cfg1 = true;
126+ }
127+ }
128+
129+ if (currlanes->clk.pos != reqcfg->clk.pos) {
130+ currlanes->clk.pos = reqcfg->clk.pos;
131+ currlanes_u->clk = true;
132+ update_complexio_cfg1 = true;
133+ }
134+ if (currlanes->clk.pol != reqcfg->clk.pol) {
135+ currlanes->clk.pol = reqcfg->clk.pol;
136+ currlanes_u->clk = true;
137+ update_complexio_cfg1 = true;
138+ }
139+ return 0;
140+err_einval:
141+ return -EINVAL;
142+}
143+
144+/**
145+ * isp_csi2_complexio_lanes_update - Applies CSI2 ComplexIO lanes configuration.
146+ * @force_update: Flag to force rewrite of registers, even if they haven't been
147+ * updated with the isp_csi2_complexio_lanes_config() function.
148+ *
149+ * It only saves settings when they were previously updated using the
150+ * isp_csi2_complexio_lanes_config() function, unless the force_update flag is
151+ * set to true.
152+ * Always returns 0.
153+ **/
154+int isp_csi2_complexio_lanes_update(bool force_update)
155+{
156+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
157+ struct isp_csi2_lanes_cfg_update *currlanes_u =
158+ &current_csi2_cfg_update.lanes;
159+ u32 reg;
160+ int i;
161+
162+ if (!update_complexio_cfg1 && !force_update)
163+ return 0;
164+
165+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
166+ for (i = 0; i < 4; i++) {
167+ if (currlanes_u->data[i] || force_update) {
168+ reg &= ~(ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1) |
169+ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i +
170+ 1));
171+ reg |= (currlanes->data[i].pol <<
172+ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1));
173+ reg |= (currlanes->data[i].pos <<
174+ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i +
175+ 1));
176+ currlanes_u->data[i] = false;
177+ }
178+ }
179+
180+ if (currlanes_u->clk || force_update) {
181+ reg &= ~(ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK |
182+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK);
183+ reg |= (currlanes->clk.pol <<
184+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT);
185+ reg |= (currlanes->clk.pos <<
186+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT);
187+ currlanes_u->clk = false;
188+ }
189+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
190+
191+ update_complexio_cfg1 = false;
192+ return 0;
193+}
194+
195+/**
196+ * isp_csi2_complexio_lanes_get - Gets CSI2 ComplexIO lanes configuration.
197+ *
198+ * Gets settings from HW registers and fills in the internal driver memory
199+ * Always returns 0.
200+ **/
201+int isp_csi2_complexio_lanes_get(void)
202+{
203+ struct isp_csi2_lanes_cfg *currlanes = &current_csi2_cfg.lanes;
204+ struct isp_csi2_lanes_cfg_update *currlanes_u =
205+ &current_csi2_cfg_update.lanes;
206+ u32 reg;
207+ int i;
208+
209+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
210+ for (i = 0; i < 4; i++) {
211+ currlanes->data[i].pol = (reg &
212+ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_MASK(i + 1)) >>
213+ ISPCSI2_COMPLEXIO_CFG1_DATA_POL_SHIFT(i + 1);
214+ currlanes->data[i].pos = (reg &
215+ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_MASK(i + 1)) >>
216+ ISPCSI2_COMPLEXIO_CFG1_DATA_POSITION_SHIFT(i + 1);
217+ currlanes_u->data[i] = false;
218+ }
219+ currlanes->clk.pol = (reg & ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_MASK) >>
220+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POL_SHIFT;
221+ currlanes->clk.pos = (reg &
222+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_MASK) >>
223+ ISPCSI2_COMPLEXIO_CFG1_CLOCK_POSITION_SHIFT;
224+ currlanes_u->clk = false;
225+
226+ update_complexio_cfg1 = false;
227+ return 0;
228+}
229+
230+/**
231+ * isp_csi2_complexio_power_status - Gets CSI2 ComplexIO power status.
232+ *
233+ * Returns 3 possible valid states: ISP_CSI2_POWER_OFF, ISP_CSI2_POWER_ON,
234+ * and ISP_CSI2_POWER_ULPW.
235+ **/
236+static enum isp_csi2_power_cmds isp_csi2_complexio_power_status(void)
237+{
238+ enum isp_csi2_power_cmds ret;
239+ u32 reg;
240+
241+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
242+ ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_MASK;
243+ switch (reg) {
244+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_OFF:
245+ ret = ISP_CSI2_POWER_OFF;
246+ break;
247+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ON:
248+ ret = ISP_CSI2_POWER_ON;
249+ break;
250+ case ISPCSI2_COMPLEXIO_CFG1_PWR_STATUS_ULPW:
251+ ret = ISP_CSI2_POWER_ULPW;
252+ break;
253+ default:
254+ return -EINVAL;
255+ }
256+ return ret;
257+}
258+
259+/**
260+ * isp_csi2_complexio_power_autoswitch - Sets CSI2 ComplexIO power autoswitch.
261+ * @enable: Sets or clears the autoswitch function enable flag.
262+ *
263+ * Always returns 0.
264+ **/
265+int isp_csi2_complexio_power_autoswitch(bool enable)
266+{
267+ u32 reg;
268+
269+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
270+ reg &= ~ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_MASK;
271+
272+ if (enable)
273+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_ENABLE;
274+ else
275+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_AUTO_DISABLE;
276+
277+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
278+ return 0;
279+}
280+
281+/**
282+ * isp_csi2_complexio_power - Sets the desired power command for CSI2 ComplexIO.
283+ * @power_cmd: Power command to be set.
284+ *
285+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
286+ **/
287+int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd)
288+{
289+ enum isp_csi2_power_cmds current_state;
290+ u32 reg;
291+ u8 retry_count;
292+
293+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1) &
294+ ~ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_MASK;
295+ switch (power_cmd) {
296+ case ISP_CSI2_POWER_OFF:
297+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_OFF;
298+ break;
299+ case ISP_CSI2_POWER_ON:
300+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ON;
301+ break;
302+ case ISP_CSI2_POWER_ULPW:
303+ reg |= ISPCSI2_COMPLEXIO_CFG1_PWR_CMD_ULPW;
304+ break;
305+ default:
306+ printk(KERN_ERR "CSI2: ERROR - Wrong Power command!\n");
307+ return -EINVAL;
308+ }
309+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_COMPLEXIO_CFG1);
310+
311+ retry_count = 0;
312+ do {
313+ udelay(50);
314+ current_state = isp_csi2_complexio_power_status();
315+
316+ if (current_state != power_cmd) {
317+ printk(KERN_DEBUG "CSI2: Complex IO power command not"
318+ " yet taken.");
319+ if (++retry_count < 100) {
320+ printk(KERN_DEBUG " Retrying...\n");
321+ udelay(50);
322+ } else {
323+ printk(KERN_DEBUG " Retry count exceeded!\n");
324+ }
325+ }
326+ } while ((current_state != power_cmd) && (retry_count < 100));
327+
328+ if (retry_count == 100)
329+ return -EBUSY;
330+
331+ return 0;
332+}
333+
334+/**
335+ * isp_csi2_ctrl_config_frame_mode - Configure if_en behaviour for CSI2
336+ * @frame_mode: Desired action for IF_EN switch off. 0 - disable IF immediately
337+ * 1 - disable after all Frame end Code is received in all
338+ * contexts.
339+ *
340+ * Validates and saves to internal driver memory the passed configuration.
341+ * Always returns 0.
342+ **/
343+int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode)
344+{
345+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
346+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
347+ &current_csi2_cfg_update.ctrl;
348+
349+ if (currctrl->frame_mode != frame_mode) {
350+ currctrl->frame_mode = frame_mode;
351+ currctrl_u->frame_mode = true;
352+ update_ctrl = true;
353+ }
354+ return 0;
355+}
356+
357+/**
358+ * isp_csi2_ctrl_config_vp_clk_enable - Enables/disables CSI2 Videoport clock.
359+ * @vp_clk_enable: Boolean value to specify the Videoport clock state.
360+ *
361+ * Validates and saves to internal driver memory the passed configuration.
362+ * Always returns 0.
363+ **/
364+int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable)
365+{
366+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
367+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
368+ &current_csi2_cfg_update.ctrl;
369+
370+ if (currctrl->vp_clk_enable != vp_clk_enable) {
371+ currctrl->vp_clk_enable = vp_clk_enable;
372+ currctrl_u->vp_clk_enable = true;
373+ update_ctrl = true;
374+ }
375+ return 0;
376+}
377+
378+/**
379+ * isp_csi2_ctrl_config_vp_only_enable - Sets CSI2 Videoport clock as exclusive
380+ * @vp_only_enable: Boolean value to specify if the Videoport clock is
381+ * exclusive, setting the OCP port as disabled.
382+ *
383+ * Validates and saves to internal driver memory the passed configuration.
384+ * Always returns 0.
385+ **/
386+int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable)
387+{
388+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
389+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
390+ &current_csi2_cfg_update.ctrl;
391+
392+ if (currctrl->vp_only_enable != vp_only_enable) {
393+ currctrl->vp_only_enable = vp_only_enable;
394+ currctrl_u->vp_only_enable = true;
395+ update_ctrl = true;
396+ }
397+ return 0;
398+}
399+
400+/**
401+ * isp_csi2_ctrl_config_vp_out_ctrl - Sets CSI2 Videoport clock divider
402+ * @vp_out_ctrl: Divider value for setting videoport clock frequency based on
403+ * OCP port frequency, valid dividers are between 1 and 4.
404+ *
405+ * Validates and saves to internal driver memory the passed configuration.
406+ * Returns 0 if successful, or -EINVAL if wrong divider value is passed.
407+ **/
408+int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl)
409+{
410+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
411+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
412+ &current_csi2_cfg_update.ctrl;
413+
414+ if ((vp_out_ctrl == 0) || (vp_out_ctrl > 4)) {
415+ printk(KERN_ERR "CSI2: Wrong divisor value. Must be between"
416+ " 1 and 4");
417+ return -EINVAL;
418+ }
419+
420+ if (currctrl->vp_out_ctrl != vp_out_ctrl) {
421+ currctrl->vp_out_ctrl = vp_out_ctrl;
422+ currctrl_u->vp_out_ctrl = true;
423+ update_ctrl = true;
424+ }
425+ return 0;
426+}
427+
428+/**
429+ * isp_csi2_ctrl_config_debug_enable - Sets CSI2 debug
430+ * @debug_enable: Boolean for setting debug configuration on CSI2.
431+ *
432+ * Always returns 0.
433+ **/
434+int isp_csi2_ctrl_config_debug_enable(bool debug_enable)
435+{
436+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
437+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
438+ &current_csi2_cfg_update.ctrl;
439+
440+ if (currctrl->debug_enable != debug_enable) {
441+ currctrl->debug_enable = debug_enable;
442+ currctrl_u->debug_enable = true;
443+ update_ctrl = true;
444+ }
445+ return 0;
446+}
447+
448+/**
449+ * isp_csi2_ctrl_config_burst_size - Sets CSI2 burst size.
450+ * @burst_size: Burst size of the memory saving capability of receiver.
451+ *
452+ * Returns 0 if successful, or -EINVAL if burst size is wrong.
453+ **/
454+int isp_csi2_ctrl_config_burst_size(u8 burst_size)
455+{
456+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
457+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
458+ &current_csi2_cfg_update.ctrl;
459+ if (burst_size > 3) {
460+ printk(KERN_ERR "CSI2: Wrong burst size. Must be between"
461+ " 0 and 3");
462+ return -EINVAL;
463+ }
464+
465+ if (currctrl->burst_size != burst_size) {
466+ currctrl->burst_size = burst_size;
467+ currctrl_u->burst_size = true;
468+ update_ctrl = true;
469+ }
470+ return 0;
471+}
472+
473+/**
474+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
475+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
476+ *
477+ * Always returns 0.
478+ **/
479+int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable)
480+{
481+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
482+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
483+ &current_csi2_cfg_update.ctrl;
484+
485+ if (currctrl->ecc_enable != ecc_enable) {
486+ currctrl->ecc_enable = ecc_enable;
487+ currctrl_u->ecc_enable = true;
488+ update_ctrl = true;
489+ }
490+ return 0;
491+}
492+
493+/**
494+ * isp_csi2_ctrl_config_ecc_enable - Enables ECC on CSI2 Receiver
495+ * @ecc_enable: Boolean to enable/disable the CSI2 receiver ECC handling.
496+ *
497+ * Always returns 0.
498+ **/
499+int isp_csi2_ctrl_config_secure_mode(bool secure_mode)
500+{
501+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
502+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
503+ &current_csi2_cfg_update.ctrl;
504+
505+ if (currctrl->secure_mode != secure_mode) {
506+ currctrl->secure_mode = secure_mode;
507+ currctrl_u->secure_mode = true;
508+ update_ctrl = true;
509+ }
510+ return 0;
511+}
512+
513+/**
514+ * isp_csi2_ctrl_config_if_enable - Enables CSI2 Receiver interface.
515+ * @if_enable: Boolean to enable/disable the CSI2 receiver interface.
516+ *
517+ * Always returns 0.
518+ **/
519+int isp_csi2_ctrl_config_if_enable(bool if_enable)
520+{
521+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
522+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
523+ &current_csi2_cfg_update.ctrl;
524+
525+ if (currctrl->if_enable != if_enable) {
526+ currctrl->if_enable = if_enable;
527+ currctrl_u->if_enable = true;
528+ update_ctrl = true;
529+ }
530+ return 0;
531+}
532+
533+/**
534+ * isp_csi2_ctrl_update - Applies CSI2 control configuration.
535+ * @force_update: Flag to force rewrite of registers, even if they haven't been
536+ * updated with the isp_csi2_ctrl_config_*() functions.
537+ *
538+ * It only saves settings when they were previously updated using the
539+ * isp_csi2_ctrl_config_*() functions, unless the force_update flag is
540+ * set to true.
541+ * Always returns 0.
542+ **/
543+int isp_csi2_ctrl_update(bool force_update)
544+{
545+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
546+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
547+ &current_csi2_cfg_update.ctrl;
548+ u32 reg;
549+
550+ if (update_ctrl || force_update) {
551+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
552+ if (currctrl_u->frame_mode || force_update) {
553+ reg &= ~ISPCSI2_CTRL_FRAME_MASK;
554+ if (currctrl->frame_mode)
555+ reg |= ISPCSI2_CTRL_FRAME_DISABLE_FEC;
556+ else
557+ reg |= ISPCSI2_CTRL_FRAME_DISABLE_IMM;
558+ currctrl_u->frame_mode = false;
559+ }
560+ if (currctrl_u->vp_clk_enable || force_update) {
561+ reg &= ~ISPCSI2_CTRL_VP_CLK_EN_MASK;
562+ if (currctrl->vp_clk_enable)
563+ reg |= ISPCSI2_CTRL_VP_CLK_EN_ENABLE;
564+ else
565+ reg |= ISPCSI2_CTRL_VP_CLK_EN_DISABLE;
566+ currctrl_u->vp_clk_enable = false;
567+ }
568+ if (currctrl_u->vp_only_enable || force_update) {
569+ reg &= ~ISPCSI2_CTRL_VP_ONLY_EN_MASK;
570+ uses_videoport = currctrl->vp_only_enable;
571+ if (currctrl->vp_only_enable)
572+ reg |= ISPCSI2_CTRL_VP_ONLY_EN_ENABLE;
573+ else
574+ reg |= ISPCSI2_CTRL_VP_ONLY_EN_DISABLE;
575+ currctrl_u->vp_only_enable = false;
576+ }
577+ if (currctrl_u->vp_out_ctrl || force_update) {
578+ reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
579+ reg |= (currctrl->vp_out_ctrl - 1) <<
580+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
581+ currctrl_u->vp_out_ctrl = false;
582+ }
583+ if (currctrl_u->debug_enable || force_update) {
584+ reg &= ~ISPCSI2_CTRL_DBG_EN_MASK;
585+ if (currctrl->debug_enable)
586+ reg |= ISPCSI2_CTRL_DBG_EN_ENABLE;
587+ else
588+ reg |= ISPCSI2_CTRL_DBG_EN_DISABLE;
589+ currctrl_u->debug_enable = false;
590+ }
591+ if (currctrl_u->burst_size || force_update) {
592+ reg &= ~ISPCSI2_CTRL_BURST_SIZE_MASK;
593+ reg |= currctrl->burst_size <<
594+ ISPCSI2_CTRL_BURST_SIZE_SHIFT;
595+ currctrl_u->burst_size = false;
596+ }
597+ if (currctrl_u->ecc_enable || force_update) {
598+ reg &= ~ISPCSI2_CTRL_ECC_EN_MASK;
599+ if (currctrl->ecc_enable)
600+ reg |= ISPCSI2_CTRL_ECC_EN_ENABLE;
601+ else
602+ reg |= ISPCSI2_CTRL_ECC_EN_DISABLE;
603+ currctrl_u->ecc_enable = false;
604+ }
605+ if (currctrl_u->secure_mode || force_update) {
606+ reg &= ~ISPCSI2_CTRL_SECURE_MASK;
607+ if (currctrl->secure_mode)
608+ reg |= ISPCSI2_CTRL_SECURE_ENABLE;
609+ else
610+ reg |= ISPCSI2_CTRL_SECURE_DISABLE;
611+ currctrl_u->secure_mode = false;
612+ }
613+ if (currctrl_u->if_enable || force_update) {
614+ reg &= ~ISPCSI2_CTRL_IF_EN_MASK;
615+ if (currctrl->if_enable)
616+ reg |= ISPCSI2_CTRL_IF_EN_ENABLE;
617+ else
618+ reg |= ISPCSI2_CTRL_IF_EN_DISABLE;
619+ currctrl_u->if_enable = false;
620+ }
621+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
622+ update_ctrl = false;
623+ }
624+ return 0;
625+}
626+
627+/**
628+ * isp_csi2_ctrl_get - Gets CSI2 control configuration
629+ *
630+ * Always returns 0.
631+ **/
632+int isp_csi2_ctrl_get(void)
633+{
634+ struct isp_csi2_ctrl_cfg *currctrl = &current_csi2_cfg.ctrl;
635+ struct isp_csi2_ctrl_cfg_update *currctrl_u =
636+ &current_csi2_cfg_update.ctrl;
637+ u32 reg;
638+
639+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL);
640+ currctrl->frame_mode = (reg & ISPCSI2_CTRL_FRAME_MASK) >>
641+ ISPCSI2_CTRL_FRAME_SHIFT;
642+ currctrl_u->frame_mode = false;
643+
644+ if ((reg & ISPCSI2_CTRL_VP_CLK_EN_MASK) ==
645+ ISPCSI2_CTRL_VP_CLK_EN_ENABLE)
646+ currctrl->vp_clk_enable = true;
647+ else
648+ currctrl->vp_clk_enable = false;
649+ currctrl_u->vp_clk_enable = false;
650+
651+ if ((reg & ISPCSI2_CTRL_VP_ONLY_EN_MASK) ==
652+ ISPCSI2_CTRL_VP_ONLY_EN_ENABLE)
653+ currctrl->vp_only_enable = true;
654+ else
655+ currctrl->vp_only_enable = false;
656+ uses_videoport = currctrl->vp_only_enable;
657+ currctrl_u->vp_only_enable = false;
658+
659+ currctrl->vp_out_ctrl = ((reg & ISPCSI2_CTRL_VP_OUT_CTRL_MASK) >>
660+ ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT) + 1;
661+ currctrl_u->vp_out_ctrl = false;
662+
663+ if ((reg & ISPCSI2_CTRL_DBG_EN_MASK) == ISPCSI2_CTRL_DBG_EN_ENABLE)
664+ currctrl->debug_enable = true;
665+ else
666+ currctrl->debug_enable = false;
667+ currctrl_u->debug_enable = false;
668+
669+ currctrl->burst_size = (reg & ISPCSI2_CTRL_BURST_SIZE_MASK) >>
670+ ISPCSI2_CTRL_BURST_SIZE_SHIFT;
671+ currctrl_u->burst_size = false;
672+
673+ if ((reg & ISPCSI2_CTRL_ECC_EN_MASK) == ISPCSI2_CTRL_ECC_EN_ENABLE)
674+ currctrl->ecc_enable = true;
675+ else
676+ currctrl->ecc_enable = false;
677+ currctrl_u->ecc_enable = false;
678+
679+ if ((reg & ISPCSI2_CTRL_SECURE_MASK) == ISPCSI2_CTRL_SECURE_ENABLE)
680+ currctrl->secure_mode = true;
681+ else
682+ currctrl->secure_mode = false;
683+ currctrl_u->secure_mode = false;
684+
685+ if ((reg & ISPCSI2_CTRL_IF_EN_MASK) == ISPCSI2_CTRL_IF_EN_ENABLE)
686+ currctrl->if_enable = true;
687+ else
688+ currctrl->if_enable = false;
689+ currctrl_u->if_enable = false;
690+
691+ update_ctrl = false;
692+ return 0;
693+}
694+
695+/**
696+ * isp_csi2_ctx_validate - Validates the context number value
697+ * @ctxnum: Pointer to variable containing context number.
698+ *
699+ * If the value is not in range (3 bits), it is being ANDed with 0x7 to force
700+ * it to be on range.
701+ **/
702+static void isp_csi2_ctx_validate(u8 *ctxnum)
703+{
704+ if (*ctxnum > 7) {
705+ printk(KERN_ERR "Invalid context number. Forcing valid"
706+ " value...\n");
707+ *ctxnum &= ~(0x7);
708+ }
709+}
710+
711+/**
712+ * isp_csi2_ctx_config_virtual_id - Maps a virtual ID with a CSI2 Rx context
713+ * @ctxnum: Context number, valid between 0 and 7 values.
714+ * @virtual_id: CSI2 Virtual ID to associate with specified context number.
715+ *
716+ * Returns 0 if successful, or -EINVAL if Virtual ID is not in range (0-3).
717+ **/
718+int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id)
719+{
720+ struct isp_csi2_ctx_cfg *selected_ctx;
721+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
722+
723+ isp_csi2_ctx_validate(&ctxnum);
724+
725+ if (virtual_id > 3) {
726+ printk(KERN_ERR "Wrong requested virtual_id\n");
727+ return -EINVAL;
728+ }
729+
730+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
731+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
732+
733+ if (selected_ctx->virtual_id != virtual_id) {
734+ selected_ctx->virtual_id = virtual_id;
735+ selected_ctx_u->virtual_id = true;
736+ update_ctx_ctrl2[ctxnum] = true;
737+ }
738+
739+ return 0;
740+}
741+
742+/**
743+ * isp_csi2_ctx_config_frame_count - Sets frame count to be received in CSI2 Rx.
744+ * @ctxnum: Context number, valid between 0 and 7 values.
745+ * @frame_count: Number of frames to acquire.
746+ *
747+ * Always returns 0.
748+ **/
749+int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count)
750+{
751+ struct isp_csi2_ctx_cfg *selected_ctx;
752+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
753+
754+ isp_csi2_ctx_validate(&ctxnum);
755+
756+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
757+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
758+
759+ if (selected_ctx->frame_count != frame_count) {
760+ selected_ctx->frame_count = frame_count;
761+ selected_ctx_u->frame_count = true;
762+ update_ctx_ctrl1[ctxnum] = true;
763+ }
764+
765+ return 0;
766+}
767+
768+/**
769+ * isp_csi2_ctx_config_format - Maps a pixel format to a specified context.
770+ * @ctxnum: Context number, valid between 0 and 7 values.
771+ * @pixformat: V4L2 structure for pixel format.
772+ *
773+ * Returns 0 if successful, or -EINVAL if the format is not supported by the
774+ * receiver.
775+ **/
776+int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat)
777+{
778+ struct isp_csi2_ctx_cfg *selected_ctx;
779+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
780+ struct v4l2_pix_format pix;
781+
782+ isp_csi2_ctx_validate(&ctxnum);
783+
784+ pix.pixelformat = pixformat;
785+ switch (pix.pixelformat) {
786+ case V4L2_PIX_FMT_RGB565:
787+ case V4L2_PIX_FMT_RGB565X:
788+ case V4L2_PIX_FMT_YUYV:
789+ case V4L2_PIX_FMT_UYVY:
790+ case V4L2_PIX_FMT_RGB555:
791+ case V4L2_PIX_FMT_RGB555X:
792+ case V4L2_PIX_FMT_SGRBG10:
793+ break;
794+ default:
795+ printk(KERN_ERR "Context config pixel format unsupported\n");
796+ return -EINVAL;
797+ }
798+
799+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
800+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
801+
802+ selected_ctx->format = pix;
803+ selected_ctx_u->format = true;
804+ update_ctx_ctrl2[ctxnum] = true;
805+
806+ return 0;
807+}
808+
809+/**
810+ * isp_csi2_ctx_config_alpha - Sets the alpha value for pixel format
811+ * @ctxnum: Context number, valid between 0 and 7 values.
812+ * @alpha: Alpha value.
813+ *
814+ * Returns 0 if successful, or -EINVAL if the alpha value is bigger than 16383.
815+ **/
816+int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha)
817+{
818+ struct isp_csi2_ctx_cfg *selected_ctx;
819+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
820+
821+ isp_csi2_ctx_validate(&ctxnum);
822+
823+ if (alpha > 0x3FFF) {
824+ printk(KERN_ERR "Wrong alpha value\n");
825+ return -EINVAL;
826+ }
827+
828+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
829+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
830+
831+ if (selected_ctx->alpha != alpha) {
832+ selected_ctx->alpha = alpha;
833+ selected_ctx_u->alpha = true;
834+ update_ctx_ctrl3[ctxnum] = true;
835+ }
836+ return 0;
837+}
838+
839+/**
840+ * isp_csi2_ctx_config_data_offset - Sets the offset between received lines
841+ * @ctxnum: Context number, valid between 0 and 7 values.
842+ * @data_offset: Offset between first pixel of each 2 contiguous lines.
843+ *
844+ * Returns 0 if successful, or -EINVAL if the line offset is bigger than 1023.
845+ **/
846+int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset)
847+{
848+ struct isp_csi2_ctx_cfg *selected_ctx;
849+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
850+
851+ isp_csi2_ctx_validate(&ctxnum);
852+
853+ if (data_offset > 0x3FF) {
854+ printk(KERN_ERR "Wrong line offset\n");
855+ return -EINVAL;
856+ }
857+
858+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
859+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
860+
861+ if (selected_ctx->data_offset != data_offset) {
862+ selected_ctx->data_offset = data_offset;
863+ selected_ctx_u->data_offset = true;
864+ }
865+ return 0;
866+}
867+
868+/**
869+ * isp_csi2_ctx_config_ping_addr - Sets Ping address for CSI2 Rx. buffer saving
870+ * @ctxnum: Context number, valid between 0 and 7 values.
871+ * @ping_addr: 32 bit ISP MMU mapped address.
872+ *
873+ * Always returns 0.
874+ **/
875+int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr)
876+{
877+ struct isp_csi2_ctx_cfg *selected_ctx;
878+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
879+
880+ isp_csi2_ctx_validate(&ctxnum);
881+
882+ ping_addr &= ~(0x1F);
883+
884+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
885+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
886+
887+ if (selected_ctx->ping_addr != ping_addr) {
888+ selected_ctx->ping_addr = ping_addr;
889+ selected_ctx_u->ping_addr = true;
890+ }
891+ return 0;
892+}
893+
894+/**
895+ * isp_csi2_ctx_config_pong_addr - Sets Pong address for CSI2 Rx. buffer saving
896+ * @ctxnum: Context number, valid between 0 and 7 values.
897+ * @pong_addr: 32 bit ISP MMU mapped address.
898+ *
899+ * Always returns 0.
900+ **/
901+int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr)
902+{
903+ struct isp_csi2_ctx_cfg *selected_ctx;
904+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
905+
906+ isp_csi2_ctx_validate(&ctxnum);
907+
908+ pong_addr &= ~(0x1F);
909+
910+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
911+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
912+
913+ if (selected_ctx->pong_addr != pong_addr) {
914+ selected_ctx->pong_addr = pong_addr;
915+ selected_ctx_u->pong_addr = true;
916+ }
917+ return 0;
918+}
919+
920+/**
921+ * isp_csi2_ctx_config_eof_enabled - Enables EOF signal assertion
922+ * @ctxnum: Context number, valid between 0 and 7 values.
923+ * @eof_enabled: Boolean to enable/disable EOF signal assertion on received
924+ * packets.
925+ *
926+ * Always returns 0.
927+ **/
928+int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled)
929+{
930+ struct isp_csi2_ctx_cfg *selected_ctx;
931+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
932+
933+ isp_csi2_ctx_validate(&ctxnum);
934+
935+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
936+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
937+
938+ if (selected_ctx->eof_enabled != eof_enabled) {
939+ selected_ctx->eof_enabled = eof_enabled;
940+ selected_ctx_u->eof_enabled = true;
941+ update_ctx_ctrl1[ctxnum] = true;
942+ }
943+ return 0;
944+}
945+
946+/**
947+ * isp_csi2_ctx_config_eol_enabled - Enables EOL signal assertion
948+ * @ctxnum: Context number, valid between 0 and 7 values.
949+ * @eol_enabled: Boolean to enable/disable EOL signal assertion on received
950+ * packets.
951+ *
952+ * Always returns 0.
953+ **/
954+int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled)
955+{
956+ struct isp_csi2_ctx_cfg *selected_ctx;
957+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
958+
959+ isp_csi2_ctx_validate(&ctxnum);
960+
961+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
962+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
963+
964+ if (selected_ctx->eol_enabled != eol_enabled) {
965+ selected_ctx->eol_enabled = eol_enabled;
966+ selected_ctx_u->eol_enabled = true;
967+ update_ctx_ctrl1[ctxnum] = true;
968+ }
969+ return 0;
970+}
971+
972+/**
973+ * isp_csi2_ctx_config_checksum_enabled - Enables Checksum check in rcvd packets
974+ * @ctxnum: Context number, valid between 0 and 7 values.
975+ * @checksum_enabled: Boolean to enable/disable Checksum check on received
976+ * packets
977+ *
978+ * Always returns 0.
979+ **/
980+int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled)
981+{
982+ struct isp_csi2_ctx_cfg *selected_ctx;
983+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
984+
985+ isp_csi2_ctx_validate(&ctxnum);
986+
987+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
988+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
989+
990+ if (selected_ctx->checksum_enabled != checksum_enabled) {
991+ selected_ctx->checksum_enabled = checksum_enabled;
992+ selected_ctx_u->checksum_enabled = true;
993+ update_ctx_ctrl1[ctxnum] = true;
994+ }
995+ return 0;
996+}
997+
998+/**
999+ * isp_csi2_ctx_config_enabled - Enables specified CSI2 context
1000+ * @ctxnum: Context number, valid between 0 and 7 values.
1001+ * @enabled: Boolean to enable/disable specified context.
1002+ *
1003+ * Always returns 0.
1004+ **/
1005+int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled)
1006+{
1007+ struct isp_csi2_ctx_cfg *selected_ctx;
1008+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1009+
1010+ isp_csi2_ctx_validate(&ctxnum);
1011+
1012+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1013+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1014+
1015+ if (selected_ctx->enabled != enabled) {
1016+ selected_ctx->enabled = enabled;
1017+ selected_ctx_u->enabled = true;
1018+ update_ctx_ctrl1[ctxnum] = true;
1019+ }
1020+ return 0;
1021+}
1022+
1023+/**
1024+ * isp_csi2_ctx_update - Applies CSI2 context configuration.
1025+ * @ctxnum: Context number, valid between 0 and 7 values.
1026+ * @force_update: Flag to force rewrite of registers, even if they haven't been
1027+ * updated with the isp_csi2_ctx_config_*() functions.
1028+ *
1029+ * It only saves settings when they were previously updated using the
1030+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1031+ * set to true.
1032+ * Always returns 0.
1033+ **/
1034+int isp_csi2_ctx_update(u8 ctxnum, bool force_update)
1035+{
1036+ struct isp_csi2_ctx_cfg *selected_ctx;
1037+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1038+ u32 reg;
1039+
1040+ isp_csi2_ctx_validate(&ctxnum);
1041+
1042+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1043+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1044+
1045+ if (update_ctx_ctrl1[ctxnum] || force_update) {
1046+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1047+ ISPCSI2_CTX_CTRL1(ctxnum));
1048+ if (selected_ctx_u->frame_count || force_update) {
1049+ reg &= ~(ISPCSI2_CTX_CTRL1_COUNT_MASK);
1050+ reg |= selected_ctx->frame_count <<
1051+ ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
1052+ selected_ctx_u->frame_count = false;
1053+ }
1054+ if (selected_ctx_u->eof_enabled || force_update) {
1055+ reg &= ~(ISPCSI2_CTX_CTRL1_EOF_EN_MASK);
1056+ if (selected_ctx->eof_enabled)
1057+ reg |= ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE;
1058+ else
1059+ reg |= ISPCSI2_CTX_CTRL1_EOF_EN_DISABLE;
1060+ selected_ctx_u->eof_enabled = false;
1061+ }
1062+ if (selected_ctx_u->eol_enabled || force_update) {
1063+ reg &= ~(ISPCSI2_CTX_CTRL1_EOL_EN_MASK);
1064+ if (selected_ctx->eol_enabled)
1065+ reg |= ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE;
1066+ else
1067+ reg |= ISPCSI2_CTX_CTRL1_EOL_EN_DISABLE;
1068+ selected_ctx_u->eol_enabled = false;
1069+ }
1070+ if (selected_ctx_u->checksum_enabled || force_update) {
1071+ reg &= ~(ISPCSI2_CTX_CTRL1_CS_EN_MASK);
1072+ if (selected_ctx->checksum_enabled)
1073+ reg |= ISPCSI2_CTX_CTRL1_CS_EN_ENABLE;
1074+ else
1075+ reg |= ISPCSI2_CTX_CTRL1_CS_EN_DISABLE;
1076+ selected_ctx_u->checksum_enabled = false;
1077+ }
1078+ if (selected_ctx_u->enabled || force_update) {
1079+ reg &= ~(ISPCSI2_CTX_CTRL1_CTX_EN_MASK);
1080+ if (selected_ctx->enabled)
1081+ reg |= ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE;
1082+ else
1083+ reg |= ISPCSI2_CTX_CTRL1_CTX_EN_DISABLE;
1084+ selected_ctx_u->enabled = false;
1085+ }
1086+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1087+ ISPCSI2_CTX_CTRL1(ctxnum));
1088+ update_ctx_ctrl1[ctxnum] = false;
1089+ }
1090+
1091+ if (update_ctx_ctrl2[ctxnum] || force_update) {
1092+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1093+ ISPCSI2_CTX_CTRL2(ctxnum));
1094+ if (selected_ctx_u->virtual_id || force_update) {
1095+ reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
1096+ reg |= selected_ctx->virtual_id <<
1097+ ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
1098+ selected_ctx_u->virtual_id = false;
1099+ }
1100+
1101+ if (selected_ctx_u->format || force_update) {
1102+ struct v4l2_pix_format *pix;
1103+ u16 new_format = 0;
1104+
1105+ reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
1106+ pix = &selected_ctx->format;
1107+ switch (pix->pixelformat) {
1108+ case V4L2_PIX_FMT_RGB565:
1109+ case V4L2_PIX_FMT_RGB565X:
1110+ new_format = 0x22;
1111+ break;
1112+ case V4L2_PIX_FMT_YUYV:
1113+ case V4L2_PIX_FMT_UYVY:
1114+ if (uses_videoport)
1115+ new_format = 0x9E;
1116+ else
1117+ new_format = 0x1E;
1118+ break;
1119+ case V4L2_PIX_FMT_RGB555:
1120+ case V4L2_PIX_FMT_RGB555X:
1121+ new_format = 0xA1;
1122+ break;
1123+ case V4L2_PIX_FMT_SGRBG10:
1124+ if (uses_videoport)
1125+ new_format = 0x12F;
1126+ else
1127+ new_format = 0xAB;
1128+ break;
1129+ }
1130+ reg |= (new_format << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT);
1131+ selected_ctx_u->format = false;
1132+ }
1133+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1134+ ISPCSI2_CTX_CTRL2(ctxnum));
1135+ update_ctx_ctrl2[ctxnum] = false;
1136+ }
1137+
1138+ if (update_ctx_ctrl3[ctxnum] || force_update) {
1139+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1140+ ISPCSI2_CTX_CTRL3(ctxnum));
1141+ if (selected_ctx_u->alpha || force_update) {
1142+ reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
1143+ reg |= (selected_ctx->alpha <<
1144+ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
1145+ selected_ctx_u->alpha = false;
1146+ }
1147+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1148+ ISPCSI2_CTX_CTRL3(ctxnum));
1149+ update_ctx_ctrl3[ctxnum] = false;
1150+ }
1151+
1152+ if (selected_ctx_u->data_offset) {
1153+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1154+ ISPCSI2_CTX_DAT_OFST(ctxnum));
1155+ reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
1156+ reg |= selected_ctx->data_offset <<
1157+ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
1158+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1159+ ISPCSI2_CTX_DAT_OFST(ctxnum));
1160+ selected_ctx_u->data_offset = false;
1161+ }
1162+
1163+ if (selected_ctx_u->ping_addr) {
1164+ reg = selected_ctx->ping_addr;
1165+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1166+ ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
1167+ selected_ctx_u->ping_addr = false;
1168+ }
1169+
1170+ if (selected_ctx_u->pong_addr) {
1171+ reg = selected_ctx->pong_addr;
1172+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1173+ ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
1174+ selected_ctx_u->pong_addr = false;
1175+ }
1176+ return 0;
1177+}
1178+
1179+/**
1180+ * isp_csi2_ctx_get - Gets specific CSI2 Context configuration
1181+ * @ctxnum: Context number, valid between 0 and 7 values.
1182+ *
1183+ * Always returns 0.
1184+ **/
1185+int isp_csi2_ctx_get(u8 ctxnum)
1186+{
1187+ struct isp_csi2_ctx_cfg *selected_ctx;
1188+ struct isp_csi2_ctx_cfg_update *selected_ctx_u;
1189+ u32 reg;
1190+
1191+ isp_csi2_ctx_validate(&ctxnum);
1192+
1193+ selected_ctx = &current_csi2_cfg.contexts[ctxnum];
1194+ selected_ctx_u = &current_csi2_cfg_update.contexts[ctxnum];
1195+
1196+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL1(ctxnum));
1197+ selected_ctx->frame_count = (reg & ISPCSI2_CTX_CTRL1_COUNT_MASK) >>
1198+ ISPCSI2_CTX_CTRL1_COUNT_SHIFT;
1199+ selected_ctx_u->frame_count = false;
1200+
1201+ if ((reg & ISPCSI2_CTX_CTRL1_EOF_EN_MASK) ==
1202+ ISPCSI2_CTX_CTRL1_EOF_EN_ENABLE)
1203+ selected_ctx->eof_enabled = true;
1204+ else
1205+ selected_ctx->eof_enabled = false;
1206+ selected_ctx_u->eof_enabled = false;
1207+
1208+ if ((reg & ISPCSI2_CTX_CTRL1_EOL_EN_MASK) ==
1209+ ISPCSI2_CTX_CTRL1_EOL_EN_ENABLE)
1210+ selected_ctx->eol_enabled = true;
1211+ else
1212+ selected_ctx->eol_enabled = false;
1213+ selected_ctx_u->eol_enabled = false;
1214+
1215+ if ((reg & ISPCSI2_CTX_CTRL1_CS_EN_MASK) ==
1216+ ISPCSI2_CTX_CTRL1_CS_EN_ENABLE)
1217+ selected_ctx->checksum_enabled = true;
1218+ else
1219+ selected_ctx->checksum_enabled = false;
1220+ selected_ctx_u->checksum_enabled = false;
1221+
1222+ if ((reg & ISPCSI2_CTX_CTRL1_CTX_EN_MASK) ==
1223+ ISPCSI2_CTX_CTRL1_CTX_EN_ENABLE)
1224+ selected_ctx->enabled = true;
1225+ else
1226+ selected_ctx->enabled = false;
1227+ selected_ctx_u->enabled = false;
1228+ update_ctx_ctrl1[ctxnum] = false;
1229+
1230+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTX_CTRL2(ctxnum));
1231+
1232+ selected_ctx->virtual_id = (reg & ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK) >>
1233+ ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
1234+ selected_ctx_u->virtual_id = false;
1235+
1236+ switch ((reg & ISPCSI2_CTX_CTRL2_FORMAT_MASK) >>
1237+ ISPCSI2_CTX_CTRL2_FORMAT_SHIFT) {
1238+ case 0x22:
1239+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB565;
1240+ break;
1241+ case 0x9E:
1242+ case 0x1E:
1243+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_YUYV;
1244+ break;
1245+ case 0xA1:
1246+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_RGB555;
1247+ break;
1248+ case 0xAB:
1249+ case 0x12F:
1250+ selected_ctx->format.pixelformat = V4L2_PIX_FMT_SGRBG10;
1251+ break;
1252+ }
1253+ selected_ctx_u->format = false;
1254+ update_ctx_ctrl2[ctxnum] = false;
1255+
1256+ selected_ctx->alpha = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1257+ ISPCSI2_CTX_CTRL3(ctxnum)) &
1258+ ISPCSI2_CTX_CTRL3_ALPHA_MASK) >>
1259+ ISPCSI2_CTX_CTRL3_ALPHA_SHIFT;
1260+ selected_ctx_u->alpha = false;
1261+ update_ctx_ctrl3[ctxnum] = false;
1262+
1263+ selected_ctx->data_offset = (isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1264+ ISPCSI2_CTX_DAT_OFST(ctxnum)) &
1265+ ISPCSI2_CTX_DAT_OFST_OFST_MASK) >>
1266+ ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
1267+ selected_ctx_u->data_offset = false;
1268+
1269+ selected_ctx->ping_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1270+ ISPCSI2_CTX_DAT_PING_ADDR(ctxnum));
1271+ selected_ctx_u->ping_addr = false;
1272+
1273+ selected_ctx->pong_addr = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1274+ ISPCSI2_CTX_DAT_PONG_ADDR(ctxnum));
1275+ selected_ctx_u->pong_addr = false;
1276+ return 0;
1277+}
1278+
1279+/**
1280+ * isp_csi2_ctx_update_all - Applies all CSI2 context configuration.
1281+ * @force_update: Flag to force rewrite of registers, even if they haven't been
1282+ * updated with the isp_csi2_ctx_config_*() functions.
1283+ *
1284+ * It only saves settings when they were previously updated using the
1285+ * isp_csi2_ctx_config_*() functions, unless the force_update flag is
1286+ * set to true.
1287+ * Always returns 0.
1288+ **/
1289+int isp_csi2_ctx_update_all(bool force_update)
1290+{
1291+ u8 ctxnum;
1292+
1293+ for (ctxnum = 0; ctxnum < 8; ctxnum++)
1294+ isp_csi2_ctx_update(ctxnum, force_update);
1295+
1296+ return 0;
1297+}
1298+
1299+/**
1300+ * isp_csi2_ctx_get_all - Gets all CSI2 Context configurations
1301+ *
1302+ * Always returns 0.
1303+ **/
1304+int isp_csi2_ctx_get_all(void)
1305+{
1306+ u8 ctxnum;
1307+
1308+ for (ctxnum = 0; ctxnum < 8; ctxnum++)
1309+ isp_csi2_ctx_get(ctxnum);
1310+
1311+ return 0;
1312+}
1313+
1314+int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig)
1315+{
1316+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1317+ struct isp_csi2_phy_cfg_update *currphy_u =
1318+ &current_csi2_cfg_update.phy;
1319+
1320+ if ((desiredphyconfig->tclk_term > 0x7f) ||
1321+ (desiredphyconfig->tclk_miss > 0x3)) {
1322+ printk(KERN_ERR "Invalid PHY configuration sent by the"
1323+ " driver\n");
1324+ return -EINVAL;
1325+ }
1326+
1327+ if (currphy->ths_term != desiredphyconfig->ths_term) {
1328+ currphy->ths_term = desiredphyconfig->ths_term;
1329+ currphy_u->ths_term = true;
1330+ update_phy_cfg0 = true;
1331+ }
1332+ if (currphy->ths_settle != desiredphyconfig->ths_settle) {
1333+ currphy->ths_settle = desiredphyconfig->ths_settle;
1334+ currphy_u->ths_settle = true;
1335+ update_phy_cfg0 = true;
1336+ }
1337+ if (currphy->tclk_term != desiredphyconfig->tclk_term) {
1338+ currphy->tclk_term = desiredphyconfig->tclk_term;
1339+ currphy_u->tclk_term = true;
1340+ update_phy_cfg1 = true;
1341+ }
1342+ if (currphy->tclk_miss != desiredphyconfig->tclk_miss) {
1343+ currphy->tclk_miss = desiredphyconfig->tclk_miss;
1344+ currphy_u->tclk_miss = true;
1345+ update_phy_cfg1 = true;
1346+ }
1347+ if (currphy->tclk_settle != desiredphyconfig->tclk_settle) {
1348+ currphy->tclk_settle = desiredphyconfig->tclk_settle;
1349+ currphy_u->tclk_settle = true;
1350+ update_phy_cfg1 = true;
1351+ }
1352+ return 0;
1353+}
1354+
1355+/**
1356+ * isp_csi2_calc_phy_cfg0 - Calculates D-PHY config based on the MIPIClk speed.
1357+ * @mipiclk: MIPI clock frequency being used with CSI2 sensor.
1358+ * @lbound_hs_settle: Lower bound for CSI2 High Speed Settle transition.
1359+ * @ubound_hs_settle: Upper bound for CSI2 High Speed Settle transition.
1360+ *
1361+ * From TRM, we have the same calculation for HS Termination signal.
1362+ * THS_TERM = ceil( 12.5ns / DDRCLK period ) - 1
1363+ * But for Settle, we use the mid value between the two passed boundaries from
1364+ * sensor:
1365+ * THS_SETTLE = (Upper bound + Lower bound) / 2
1366+ *
1367+ * Always returns 0.
1368+ */
1369+int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
1370+ u32 ubound_hs_settle)
1371+{
1372+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1373+ struct isp_csi2_phy_cfg_update *currphy_u =
1374+ &current_csi2_cfg_update.phy;
1375+ u32 tmp, ddrclk = mipiclk >> 1;
1376+
1377+ /* Calculate THS_TERM */
1378+ tmp = ddrclk / 80000000;
1379+ if ((ddrclk % 80000000) > 0)
1380+ tmp++;
1381+ currphy->ths_term = tmp - 1;
1382+ currphy_u->ths_term = true;
1383+
1384+ /* Calculate THS_SETTLE */
1385+ currphy->ths_settle = (ubound_hs_settle + lbound_hs_settle) / 2;
1386+
1387+ currphy_u->ths_settle = true;
1388+ isp_csi2_phy_update(true);
1389+ return 0;
1390+}
1391+EXPORT_SYMBOL(isp_csi2_calc_phy_cfg0);
1392+
1393+/**
1394+ * isp_csi2_phy_update - Applies CSI2 D-PHY configuration.
1395+ * @force_update: Flag to force rewrite of registers, even if they haven't been
1396+ * updated with the isp_csi2_phy_config_*() functions.
1397+ *
1398+ * It only saves settings when they were previously updated using the
1399+ * isp_csi2_phy_config_*() functions, unless the force_update flag is
1400+ * set to true.
1401+ * Always returns 0.
1402+ **/
1403+int isp_csi2_phy_update(bool force_update)
1404+{
1405+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1406+ struct isp_csi2_phy_cfg_update *currphy_u =
1407+ &current_csi2_cfg_update.phy;
1408+ u32 reg;
1409+
1410+ if (update_phy_cfg0 || force_update) {
1411+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1412+ if (currphy_u->ths_term || force_update) {
1413+ reg &= ~ISPCSI2PHY_CFG0_THS_TERM_MASK;
1414+ reg |= (currphy->ths_term <<
1415+ ISPCSI2PHY_CFG0_THS_TERM_SHIFT);
1416+ currphy_u->ths_term = false;
1417+ }
1418+ if (currphy_u->ths_settle || force_update) {
1419+ reg &= ~ISPCSI2PHY_CFG0_THS_SETTLE_MASK;
1420+ reg |= (currphy->ths_settle <<
1421+ ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT);
1422+ currphy_u->ths_settle = false;
1423+ }
1424+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1425+ update_phy_cfg0 = false;
1426+ }
1427+
1428+ if (update_phy_cfg1 || force_update) {
1429+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1430+ if (currphy_u->tclk_term || force_update) {
1431+ reg &= ~ISPCSI2PHY_CFG1_TCLK_TERM_MASK;
1432+ reg |= (currphy->tclk_term <<
1433+ ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT);
1434+ currphy_u->tclk_term = false;
1435+ }
1436+ if (currphy_u->tclk_miss || force_update) {
1437+ reg &= ~ISPCSI2PHY_CFG1_TCLK_MISS_MASK;
1438+ reg |= (currphy->tclk_miss <<
1439+ ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT);
1440+ currphy_u->tclk_miss = false;
1441+ }
1442+ if (currphy_u->tclk_settle || force_update) {
1443+ reg &= ~ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK;
1444+ reg |= (currphy->tclk_settle <<
1445+ ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT);
1446+ currphy_u->tclk_settle = false;
1447+ }
1448+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1449+ update_phy_cfg1 = false;
1450+ }
1451+ return 0;
1452+}
1453+
1454+/**
1455+ * isp_csi2_phy_get - Gets CSI2 D-PHY configuration
1456+ *
1457+ * Gets settings from HW registers and fills in the internal driver memory
1458+ * Always returns 0.
1459+ **/
1460+int isp_csi2_phy_get(void)
1461+{
1462+ struct isp_csi2_phy_cfg *currphy = &current_csi2_cfg.phy;
1463+ struct isp_csi2_phy_cfg_update *currphy_u =
1464+ &current_csi2_cfg_update.phy;
1465+ u32 reg;
1466+
1467+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG0);
1468+ currphy->ths_term = (reg & ISPCSI2PHY_CFG0_THS_TERM_MASK) >>
1469+ ISPCSI2PHY_CFG0_THS_TERM_SHIFT;
1470+ currphy_u->ths_term = false;
1471+
1472+ currphy->ths_settle = (reg & ISPCSI2PHY_CFG0_THS_SETTLE_MASK) >>
1473+ ISPCSI2PHY_CFG0_THS_SETTLE_SHIFT;
1474+ currphy_u->ths_settle = false;
1475+ update_phy_cfg0 = false;
1476+
1477+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY, ISPCSI2PHY_CFG1);
1478+
1479+ currphy->tclk_term = (reg & ISPCSI2PHY_CFG1_TCLK_TERM_MASK) >>
1480+ ISPCSI2PHY_CFG1_TCLK_TERM_SHIFT;
1481+ currphy_u->tclk_term = false;
1482+
1483+ currphy->tclk_miss = (reg & ISPCSI2PHY_CFG1_TCLK_MISS_MASK) >>
1484+ ISPCSI2PHY_CFG1_TCLK_MISS_SHIFT;
1485+ currphy_u->tclk_miss = false;
1486+
1487+ currphy->tclk_settle = (reg & ISPCSI2PHY_CFG1_TCLK_SETTLE_MASK) >>
1488+ ISPCSI2PHY_CFG1_TCLK_SETTLE_SHIFT;
1489+ currphy_u->tclk_settle = false;
1490+
1491+ update_phy_cfg1 = false;
1492+ return 0;
1493+}
1494+
1495+/**
1496+ * isp_csi2_timings_config_forcerxmode - Sets Force Rx mode on stop state count
1497+ * @force_rx_mode: Boolean to enable/disable forcing Rx mode in CSI2 receiver
1498+ *
1499+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1500+ **/
1501+int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode)
1502+{
1503+ struct isp_csi2_timings_cfg *currtimings;
1504+ struct isp_csi2_timings_cfg_update *currtimings_u;
1505+
1506+ if (io < 1 || io > 2) {
1507+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1508+ return -EINVAL;
1509+ }
1510+
1511+ currtimings = &current_csi2_cfg.timings[io - 1];
1512+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1513+ if (currtimings->force_rx_mode != force_rx_mode) {
1514+ currtimings->force_rx_mode = force_rx_mode;
1515+ currtimings_u->force_rx_mode = true;
1516+ update_timing = true;
1517+ }
1518+ return 0;
1519+}
1520+
1521+/**
1522+ * isp_csi2_timings_config_stopstate_16x - Sets 16x factor for L3 cycles
1523+ * @stop_state_16x: Boolean to use or not use the 16x multiplier for stop count
1524+ *
1525+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1526+ **/
1527+int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x)
1528+{
1529+ struct isp_csi2_timings_cfg *currtimings;
1530+ struct isp_csi2_timings_cfg_update *currtimings_u;
1531+
1532+ if (io < 1 || io > 2) {
1533+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1534+ return -EINVAL;
1535+ }
1536+
1537+ currtimings = &current_csi2_cfg.timings[io - 1];
1538+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1539+ if (currtimings->stop_state_16x != stop_state_16x) {
1540+ currtimings->stop_state_16x = stop_state_16x;
1541+ currtimings_u->stop_state_16x = true;
1542+ update_timing = true;
1543+ }
1544+ return 0;
1545+}
1546+
1547+/**
1548+ * isp_csi2_timings_config_stopstate_4x - Sets 4x factor for L3 cycles
1549+ * @stop_state_4x: Boolean to use or not use the 4x multiplier for stop count
1550+ *
1551+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1552+ **/
1553+int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x)
1554+{
1555+ struct isp_csi2_timings_cfg *currtimings;
1556+ struct isp_csi2_timings_cfg_update *currtimings_u;
1557+
1558+ if (io < 1 || io > 2) {
1559+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1560+ return -EINVAL;
1561+ }
1562+
1563+ currtimings = &current_csi2_cfg.timings[io - 1];
1564+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1565+ if (currtimings->stop_state_4x != stop_state_4x) {
1566+ currtimings->stop_state_4x = stop_state_4x;
1567+ currtimings_u->stop_state_4x = true;
1568+ update_timing = true;
1569+ }
1570+ return 0;
1571+}
1572+
1573+/**
1574+ * isp_csi2_timings_config_stopstate_cnt - Sets L3 cycles
1575+ * @stop_state_counter: Stop state counter value for L3 cycles
1576+ *
1577+ * Returns 0 if successful, or -EINVAL if wrong ComplexIO number is selected.
1578+ **/
1579+int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter)
1580+{
1581+ struct isp_csi2_timings_cfg *currtimings;
1582+ struct isp_csi2_timings_cfg_update *currtimings_u;
1583+
1584+ if (io < 1 || io > 2) {
1585+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1586+ return -EINVAL;
1587+ }
1588+
1589+ currtimings = &current_csi2_cfg.timings[io - 1];
1590+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1591+ if (currtimings->stop_state_counter != stop_state_counter) {
1592+ currtimings->stop_state_counter = (stop_state_counter & 0x1FFF);
1593+ currtimings_u->stop_state_counter = true;
1594+ update_timing = true;
1595+ }
1596+ return 0;
1597+}
1598+
1599+/**
1600+ * isp_csi2_timings_update - Applies specified CSI2 timing configuration.
1601+ * @io: IO number (1 or 2) which specifies which ComplexIO are we updating
1602+ * @force_update: Flag to force rewrite of registers, even if they haven't been
1603+ * updated with the isp_csi2_timings_config_*() functions.
1604+ *
1605+ * It only saves settings when they were previously updated using the
1606+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
1607+ * set to true.
1608+ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
1609+ **/
1610+int isp_csi2_timings_update(u8 io, bool force_update)
1611+{
1612+ struct isp_csi2_timings_cfg *currtimings;
1613+ struct isp_csi2_timings_cfg_update *currtimings_u;
1614+ u32 reg;
1615+
1616+ if (io < 1 || io > 2) {
1617+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1618+ return -EINVAL;
1619+ }
1620+
1621+ currtimings = &current_csi2_cfg.timings[io - 1];
1622+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1623+
1624+ if (update_timing || force_update) {
1625+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1626+ if (currtimings_u->force_rx_mode || force_update) {
1627+ reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io);
1628+ if (currtimings->force_rx_mode)
1629+ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE
1630+ (io);
1631+ else
1632+ reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO_DISABLE
1633+ (io);
1634+ currtimings_u->force_rx_mode = false;
1635+ }
1636+ if (currtimings_u->stop_state_16x || force_update) {
1637+ reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io);
1638+ if (currtimings->stop_state_16x)
1639+ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE
1640+ (io);
1641+ else
1642+ reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO_DISABLE
1643+ (io);
1644+ currtimings_u->stop_state_16x = false;
1645+ }
1646+ if (currtimings_u->stop_state_4x || force_update) {
1647+ reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io);
1648+ if (currtimings->stop_state_4x) {
1649+ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE
1650+ (io);
1651+ } else {
1652+ reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO_DISABLE
1653+ (io);
1654+ }
1655+ currtimings_u->stop_state_4x = false;
1656+ }
1657+ if (currtimings_u->stop_state_counter || force_update) {
1658+ reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io);
1659+ reg |= currtimings->stop_state_counter <<
1660+ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
1661+ currtimings_u->stop_state_counter = false;
1662+ }
1663+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1664+ update_timing = false;
1665+ }
1666+ return 0;
1667+}
1668+
1669+/**
1670+ * isp_csi2_timings_get - Gets specific CSI2 ComplexIO timing configuration
1671+ * @io: IO number (1 or 2) which specifies which ComplexIO are we getting
1672+ *
1673+ * Gets settings from HW registers and fills in the internal driver memory
1674+ * Returns 0 if successful, or -EINVAL if invalid IO number is passed.
1675+ **/
1676+int isp_csi2_timings_get(u8 io)
1677+{
1678+ struct isp_csi2_timings_cfg *currtimings;
1679+ struct isp_csi2_timings_cfg_update *currtimings_u;
1680+ u32 reg;
1681+
1682+ if (io < 1 || io > 2) {
1683+ printk(KERN_ERR "CSI2 - Timings config: Invalid IO number\n");
1684+ return -EINVAL;
1685+ }
1686+
1687+ currtimings = &current_csi2_cfg.timings[io - 1];
1688+ currtimings_u = &current_csi2_cfg_update.timings[io - 1];
1689+
1690+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING);
1691+ if ((reg & ISPCSI2_TIMING_FORCE_RX_MODE_IO_MASK(io)) ==
1692+ ISPCSI2_TIMING_FORCE_RX_MODE_IO_ENABLE(io))
1693+ currtimings->force_rx_mode = true;
1694+ else
1695+ currtimings->force_rx_mode = false;
1696+ currtimings_u->force_rx_mode = false;
1697+
1698+ if ((reg & ISPCSI2_TIMING_STOP_STATE_X16_IO_MASK(io)) ==
1699+ ISPCSI2_TIMING_STOP_STATE_X16_IO_ENABLE(io))
1700+ currtimings->stop_state_16x = true;
1701+ else
1702+ currtimings->stop_state_16x = false;
1703+ currtimings_u->stop_state_16x = false;
1704+
1705+ if ((reg & ISPCSI2_TIMING_STOP_STATE_X4_IO_MASK(io)) ==
1706+ ISPCSI2_TIMING_STOP_STATE_X4_IO_ENABLE(io))
1707+ currtimings->stop_state_4x = true;
1708+ else
1709+ currtimings->stop_state_4x = false;
1710+ currtimings_u->stop_state_4x = false;
1711+
1712+ currtimings->stop_state_counter = (reg &
1713+ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(io)) >>
1714+ ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(io);
1715+ currtimings_u->stop_state_counter = false;
1716+ update_timing = false;
1717+ return 0;
1718+}
1719+
1720+/**
1721+ * isp_csi2_timings_update_all - Applies specified CSI2 timing configuration.
1722+ * @force_update: Flag to force rewrite of registers, even if they haven't been
1723+ * updated with the isp_csi2_timings_config_*() functions.
1724+ *
1725+ * It only saves settings when they were previously updated using the
1726+ * isp_csi2_timings_config_*() functions, unless the force_update flag is
1727+ * set to true.
1728+ * Always returns 0.
1729+ **/
1730+int isp_csi2_timings_update_all(bool force_update)
1731+{
1732+ int i;
1733+
1734+ for (i = 1; i < 3; i++)
1735+ isp_csi2_timings_update(i, force_update);
1736+ return 0;
1737+}
1738+
1739+/**
1740+ * isp_csi2_timings_get_all - Gets all CSI2 ComplexIO timing configurations
1741+ *
1742+ * Always returns 0.
1743+ **/
1744+int isp_csi2_timings_get_all(void)
1745+{
1746+ int i;
1747+
1748+ for (i = 1; i < 3; i++)
1749+ isp_csi2_timings_get(i);
1750+ return 0;
1751+}
1752+
1753+/**
1754+ * isp_csi2_isr - CSI2 interrupt handling.
1755+ **/
1756+void isp_csi2_isr(void)
1757+{
1758+ u32 csi2_irqstatus, cpxio1_irqstatus, ctxirqstatus;
1759+
1760+ csi2_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1761+ ISPCSI2_IRQSTATUS);
1762+ isp_reg_writel(csi2_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
1763+ ISPCSI2_IRQSTATUS);
1764+
1765+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
1766+ cpxio1_irqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1767+ ISPCSI2_COMPLEXIO1_IRQSTATUS);
1768+ isp_reg_writel(cpxio1_irqstatus, OMAP3_ISP_IOMEM_CSI2A,
1769+ ISPCSI2_COMPLEXIO1_IRQSTATUS);
1770+ printk(KERN_ERR "CSI2: ComplexIO Error IRQ %x\n",
1771+ cpxio1_irqstatus);
1772+ }
1773+
1774+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) {
1775+ ctxirqstatus = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1776+ ISPCSI2_CTX_IRQSTATUS(0));
1777+ isp_reg_writel(ctxirqstatus, OMAP3_ISP_IOMEM_CSI2A,
1778+ ISPCSI2_CTX_IRQSTATUS(0));
1779+ }
1780+
1781+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_OCP_ERR_IRQ)
1782+ printk(KERN_ERR "CSI2: OCP Transmission Error\n");
1783+
1784+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ)
1785+ printk(KERN_ERR "CSI2: Short packet receive error\n");
1786+
1787+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
1788+ printk(KERN_DEBUG "CSI2: ECC correction done\n");
1789+
1790+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ)
1791+ printk(KERN_ERR "CSI2: ECC correction failed\n");
1792+
1793+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ)
1794+ printk(KERN_ERR "CSI2: ComplexIO #2 failed\n");
1795+
1796+ if (csi2_irqstatus & ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)
1797+ printk(KERN_ERR "CSI2: FIFO overflow error\n");
1798+
1799+ return;
1800+}
1801+EXPORT_SYMBOL(isp_csi2_isr);
1802+
1803+/**
1804+ * isp_csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
1805+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
1806+ **/
1807+void isp_csi2_irq_complexio1_set(int enable)
1808+{
1809+ u32 reg;
1810+ reg = ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMEXIT |
1811+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEALLULPMENTER |
1812+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM5 |
1813+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL5 |
1814+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC5 |
1815+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS5 |
1816+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS5 |
1817+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM4 |
1818+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL4 |
1819+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC4 |
1820+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS4 |
1821+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS4 |
1822+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM3 |
1823+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL3 |
1824+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC3 |
1825+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS3 |
1826+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS3 |
1827+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM2 |
1828+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL2 |
1829+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC2 |
1830+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS2 |
1831+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS2 |
1832+ ISPCSI2_COMPLEXIO1_IRQENABLE_STATEULPM1 |
1833+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRCONTROL1 |
1834+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRESC1 |
1835+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTSYNCHS1 |
1836+ ISPCSI2_COMPLEXIO1_IRQENABLE_ERRSOTHS1;
1837+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1838+ ISPCSI2_COMPLEXIO1_IRQSTATUS);
1839+ if (enable) {
1840+ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
1841+ ISPCSI2_COMPLEXIO1_IRQENABLE);
1842+ } else
1843+ reg = 0;
1844+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1845+ ISPCSI2_COMPLEXIO1_IRQENABLE);
1846+}
1847+EXPORT_SYMBOL(isp_csi2_irq_complexio1_set);
1848+
1849+/**
1850+ * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
1851+ * @enable: Enable/disable CSI2 Context interrupts
1852+ **/
1853+void isp_csi2_irq_ctx_set(int enable)
1854+{
1855+ u32 reg;
1856+ int i;
1857+
1858+ reg = ISPCSI2_CTX_IRQSTATUS_FS_IRQ | ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
1859+ for (i = 0; i < 8; i++) {
1860+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A,
1861+ ISPCSI2_CTX_IRQSTATUS(i));
1862+ if (enable) {
1863+ isp_reg_or(OMAP3_ISP_IOMEM_CSI2A,
1864+ ISPCSI2_CTX_IRQENABLE(i), reg);
1865+ } else {
1866+ isp_reg_writel(0, OMAP3_ISP_IOMEM_CSI2A,
1867+ ISPCSI2_CTX_IRQENABLE(i));
1868+ }
1869+ }
1870+
1871+}
1872+EXPORT_SYMBOL(isp_csi2_irq_ctx_set);
1873+
1874+/**
1875+ * isp_csi2_irq_status_set - Enables CSI2 Status IRQs.
1876+ * @enable: Enable/disable CSI2 Status interrupts
1877+ **/
1878+void isp_csi2_irq_status_set(int enable)
1879+{
1880+ u32 reg;
1881+ reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
1882+ ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
1883+ ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
1884+ ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
1885+ ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
1886+ ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
1887+ ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
1888+ ISPCSI2_IRQSTATUS_CONTEXT(0);
1889+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQSTATUS);
1890+ if (enable)
1891+ reg |= isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1892+ else
1893+ reg = 0;
1894+
1895+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_IRQENABLE);
1896+}
1897+EXPORT_SYMBOL(isp_csi2_irq_status_set);
1898+
1899+/**
1900+ * isp_csi2_irq_status_set - Enables main CSI2 IRQ.
1901+ * @enable: Enable/disable main CSI2 interrupt
1902+ **/
1903+void isp_csi2_irq_set(int enable)
1904+{
1905+ isp_reg_writel(IRQ0STATUS_CSIA_IRQ, OMAP3_ISP_IOMEM_MAIN,
1906+ ISP_IRQ0STATUS);
1907+ isp_reg_and_or(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE,
1908+ ~IRQ0ENABLE_CSIA_IRQ,
1909+ (enable ? IRQ0ENABLE_CSIA_IRQ : 0));
1910+}
1911+EXPORT_SYMBOL(isp_csi2_irq_set);
1912+
1913+/**
1914+ * isp_csi2_irq_all_set - Enable/disable CSI2 interrupts.
1915+ * @enable: 0-Disable, 1-Enable.
1916+ **/
1917+void isp_csi2_irq_all_set(int enable)
1918+{
1919+ if (enable) {
1920+ isp_csi2_irq_complexio1_set(enable);
1921+ isp_csi2_irq_ctx_set(enable);
1922+ isp_csi2_irq_status_set(enable);
1923+ isp_csi2_irq_set(enable);
1924+ } else {
1925+ isp_csi2_irq_set(enable);
1926+ isp_csi2_irq_status_set(enable);
1927+ isp_csi2_irq_ctx_set(enable);
1928+ isp_csi2_irq_complexio1_set(enable);
1929+ }
1930+ return;
1931+}
1932+EXPORT_SYMBOL(isp_csi2_irq_all_set);
1933+
1934+/**
1935+ * isp_csi2_reset - Resets the CSI2 module.
1936+ *
1937+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
1938+ **/
1939+int isp_csi2_reset(void)
1940+{
1941+ u32 reg;
1942+ u8 soft_reset_retries = 0;
1943+ int i;
1944+
1945+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1946+ reg |= ISPCSI2_SYSCONFIG_SOFT_RESET_RESET;
1947+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1948+
1949+ do {
1950+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSSTATUS) &
1951+ ISPCSI2_SYSSTATUS_RESET_DONE_MASK;
1952+ if (reg == ISPCSI2_SYSSTATUS_RESET_DONE_DONE)
1953+ break;
1954+ soft_reset_retries++;
1955+ if (soft_reset_retries < 5)
1956+ udelay(100);
1957+ } while (soft_reset_retries < 5);
1958+
1959+ if (soft_reset_retries == 5) {
1960+ printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
1961+ return -EBUSY;
1962+ }
1963+
1964+ reg = isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1965+ reg &= ~ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK;
1966+ reg |= ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO;
1967+ reg &= ~ISPCSI2_SYSCONFIG_AUTO_IDLE_MASK;
1968+ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_SYSCONFIG);
1969+
1970+ uses_videoport = false;
1971+ update_complexio_cfg1 = false;
1972+ update_phy_cfg0 = false;
1973+ update_phy_cfg1 = false;
1974+ for (i = 0; i < 8; i++) {
1975+ update_ctx_ctrl1[i] = false;
1976+ update_ctx_ctrl2[i] = false;
1977+ update_ctx_ctrl3[i] = false;
1978+ }
1979+ update_timing = false;
1980+ update_ctrl = false;
1981+
1982+ isp_csi2_complexio_lanes_get();
1983+ isp_csi2_ctrl_get();
1984+ isp_csi2_ctx_get_all();
1985+ isp_csi2_phy_get();
1986+ isp_csi2_timings_get_all();
1987+
1988+ isp_csi2_complexio_power_autoswitch(true);
1989+ isp_csi2_complexio_power(ISP_CSI2_POWER_ON);
1990+
1991+ isp_csi2_timings_config_forcerxmode(1, true);
1992+ isp_csi2_timings_config_stopstate_cnt(1, 0x1FF);
1993+ isp_csi2_timings_update_all(true);
1994+
1995+ return 0;
1996+}
1997+
1998+/**
1999+ * isp_csi2_enable - Enables the CSI2 module.
2000+ * @enable: Enables/disables the CSI2 module.
2001+ **/
2002+void isp_csi2_enable(int enable)
2003+{
2004+ if (enable) {
2005+ isp_csi2_ctx_config_enabled(0, true);
2006+ isp_csi2_ctx_config_eof_enabled(0, true);
2007+ isp_csi2_ctx_config_checksum_enabled(0, true);
2008+ isp_csi2_ctx_update(0, false);
2009+
2010+ isp_csi2_ctrl_config_ecc_enable(true);
2011+ isp_csi2_ctrl_config_if_enable(true);
2012+ isp_csi2_ctrl_update(false);
2013+ } else {
2014+ isp_csi2_ctx_config_enabled(0, false);
2015+ isp_csi2_ctx_config_eof_enabled(0, false);
2016+ isp_csi2_ctx_config_checksum_enabled(0, false);
2017+ isp_csi2_ctx_update(0, false);
2018+
2019+ isp_csi2_ctrl_config_ecc_enable(false);
2020+ isp_csi2_ctrl_config_if_enable(false);
2021+ isp_csi2_ctrl_update(false);
2022+ }
2023+}
2024+EXPORT_SYMBOL(isp_csi2_enable);
2025+
2026+/**
2027+ * isp_csi2_regdump - Prints CSI2 debug information.
2028+ **/
2029+void isp_csi2_regdump(void)
2030+{
2031+ printk(KERN_DEBUG "-------------Register dump-------------\n");
2032+
2033+ printk(KERN_DEBUG "ISP_CTRL: %x\n",
2034+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL));
2035+ printk(KERN_DEBUG "ISP_TCTRL_CTRL: %x\n",
2036+ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL));
2037+
2038+ printk(KERN_DEBUG "ISPCCDC_SDR_ADDR: %x\n",
2039+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR));
2040+ printk(KERN_DEBUG "ISPCCDC_SYN_MODE: %x\n",
2041+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE));
2042+ printk(KERN_DEBUG "ISPCCDC_CFG: %x\n",
2043+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG));
2044+ printk(KERN_DEBUG "ISPCCDC_FMTCFG: %x\n",
2045+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG));
2046+ printk(KERN_DEBUG "ISPCCDC_HSIZE_OFF: %x\n",
2047+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF));
2048+ printk(KERN_DEBUG "ISPCCDC_HORZ_INFO: %x\n",
2049+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO));
2050+ printk(KERN_DEBUG "ISPCCDC_VERT_START: %x\n",
2051+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
2052+ ISPCCDC_VERT_START));
2053+ printk(KERN_DEBUG "ISPCCDC_VERT_LINES: %x\n",
2054+ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC,
2055+ ISPCCDC_VERT_LINES));
2056+
2057+ printk(KERN_DEBUG "ISPCSI2_COMPLEXIO_CFG1: %x\n",
2058+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2059+ ISPCSI2_COMPLEXIO_CFG1));
2060+ printk(KERN_DEBUG "ISPCSI2_SYSSTATUS: %x\n",
2061+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2062+ ISPCSI2_SYSSTATUS));
2063+ printk(KERN_DEBUG "ISPCSI2_SYSCONFIG: %x\n",
2064+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2065+ ISPCSI2_SYSCONFIG));
2066+ printk(KERN_DEBUG "ISPCSI2_IRQENABLE: %x\n",
2067+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2068+ ISPCSI2_IRQENABLE));
2069+ printk(KERN_DEBUG "ISPCSI2_IRQSTATUS: %x\n",
2070+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2071+ ISPCSI2_IRQSTATUS));
2072+
2073+ printk(KERN_DEBUG "ISPCSI2_CTX_IRQENABLE(0): %x\n",
2074+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2075+ ISPCSI2_CTX_IRQENABLE(0)));
2076+ printk(KERN_DEBUG "ISPCSI2_CTX_IRQSTATUS(0): %x\n",
2077+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2078+ ISPCSI2_CTX_IRQSTATUS(0)));
2079+ printk(KERN_DEBUG "ISPCSI2_TIMING: %x\n",
2080+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_TIMING));
2081+ printk(KERN_DEBUG "ISPCSI2PHY_CFG0: %x\n",
2082+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
2083+ ISPCSI2PHY_CFG0));
2084+ printk(KERN_DEBUG "ISPCSI2PHY_CFG1: %x\n",
2085+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2PHY,
2086+ ISPCSI2PHY_CFG1));
2087+ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL1(0): %x\n",
2088+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2089+ ISPCSI2_CTX_CTRL1(0)));
2090+ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL2(0): %x\n",
2091+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2092+ ISPCSI2_CTX_CTRL2(0)));
2093+ printk(KERN_DEBUG "ISPCSI2_CTX_CTRL3(0): %x\n",
2094+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2095+ ISPCSI2_CTX_CTRL3(0)));
2096+ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_OFST(0): %x\n",
2097+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2098+ ISPCSI2_CTX_DAT_OFST(0)));
2099+ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PING_ADDR(0): %x\n",
2100+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2101+ ISPCSI2_CTX_DAT_PING_ADDR(0)));
2102+ printk(KERN_DEBUG "ISPCSI2_CTX_DAT_PONG_ADDR(0): %x\n",
2103+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A,
2104+ ISPCSI2_CTX_DAT_PONG_ADDR(0)));
2105+ printk(KERN_DEBUG "ISPCSI2_CTRL: %x\n",
2106+ isp_reg_readl(OMAP3_ISP_IOMEM_CSI2A, ISPCSI2_CTRL));
2107+ printk(KERN_DEBUG "---------------------------------------\n");
2108+}
2109+
2110+/**
2111+ * isp_csi2_cleanup - Routine for module driver cleanup
2112+ **/
2113+void isp_csi2_cleanup(void)
2114+{
2115+ return;
2116+}
2117+
2118+/**
2119+ * isp_csi2_init - Routine for module driver init
2120+ **/
2121+int __init isp_csi2_init(void)
2122+{
2123+ int i;
2124+
2125+ update_complexio_cfg1 = false;
2126+ update_phy_cfg0 = false;
2127+ update_phy_cfg1 = false;
2128+ for (i = 0; i < 8; i++) {
2129+ update_ctx_ctrl1[i] = false;
2130+ update_ctx_ctrl2[i] = false;
2131+ update_ctx_ctrl3[i] = false;
2132+ }
2133+ update_timing = false;
2134+ update_ctrl = false;
2135+
2136+ memset(&current_csi2_cfg, 0, sizeof(current_csi2_cfg));
2137+ memset(&current_csi2_cfg_update, 0, sizeof(current_csi2_cfg_update));
2138+ return 0;
2139+}
2140+
2141+MODULE_AUTHOR("Texas Instruments");
2142+MODULE_DESCRIPTION("ISP CSI2 Receiver Module");
2143+MODULE_LICENSE("GPL");
2144diff --git a/drivers/media/video/isp/ispcsi2.h b/drivers/media/video/isp/ispcsi2.h
2145new file mode 100644
2146index 0000000..4582c96
2147--- /dev/null
2148+++ b/drivers/media/video/isp/ispcsi2.h
2149@@ -0,0 +1,232 @@
2150+/*
2151+ * ispcsi2.h
2152+ *
2153+ * Copyright (C) 2009 Texas Instruments.
2154+ *
2155+ * Contributors:
2156+ * Sergio Aguirre <saaguirre@ti.com>
2157+ * Dominic Curran <dcurran@ti.com>
2158+ *
2159+ * This package is free software; you can redistribute it and/or modify
2160+ * it under the terms of the GNU General Public License version 2 as
2161+ * published by the Free Software Foundation.
2162+ *
2163+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2164+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2165+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2166+ */
2167+
2168+#ifndef OMAP_ISP_CSI2_API_H
2169+#define OMAP_ISP_CSI2_API_H
2170+#include <linux/videodev2.h>
2171+
2172+enum isp_csi2_irqevents {
2173+ OCP_ERR_IRQ = 0x4000,
2174+ SHORT_PACKET_IRQ = 0x2000,
2175+ ECC_CORRECTION_IRQ = 0x1000,
2176+ ECC_NO_CORRECTION_IRQ = 0x800,
2177+ COMPLEXIO2_ERR_IRQ = 0x400,
2178+ COMPLEXIO1_ERR_IRQ = 0x200,
2179+ FIFO_OVF_IRQ = 0x100,
2180+ CONTEXT7 = 0x80,
2181+ CONTEXT6 = 0x40,
2182+ CONTEXT5 = 0x20,
2183+ CONTEXT4 = 0x10,
2184+ CONTEXT3 = 0x8,
2185+ CONTEXT2 = 0x4,
2186+ CONTEXT1 = 0x2,
2187+ CONTEXT0 = 0x1,
2188+};
2189+
2190+enum isp_csi2_ctx_irqevents {
2191+ CTX_ECC_CORRECTION = 0x100,
2192+ CTX_LINE_NUMBER = 0x80,
2193+ CTX_FRAME_NUMBER = 0x40,
2194+ CTX_CS = 0x20,
2195+ CTX_LE = 0x8,
2196+ CTX_LS = 0x4,
2197+ CTX_FE = 0x2,
2198+ CTX_FS = 0x1,
2199+};
2200+
2201+enum isp_csi2_power_cmds {
2202+ ISP_CSI2_POWER_OFF,
2203+ ISP_CSI2_POWER_ON,
2204+ ISP_CSI2_POWER_ULPW,
2205+};
2206+
2207+enum isp_csi2_frame_mode {
2208+ ISP_CSI2_FRAME_IMMEDIATE,
2209+ ISP_CSI2_FRAME_AFTERFEC,
2210+};
2211+
2212+struct csi2_lanecfg {
2213+ u8 pos;
2214+ u8 pol;
2215+};
2216+
2217+struct isp_csi2_lanes_cfg {
2218+ struct csi2_lanecfg data[4];
2219+ struct csi2_lanecfg clk;
2220+};
2221+
2222+struct isp_csi2_lanes_cfg_update {
2223+ bool data[4];
2224+ bool clk;
2225+};
2226+
2227+struct isp_csi2_phy_cfg {
2228+ u8 ths_term;
2229+ u8 ths_settle;
2230+ u8 tclk_term;
2231+ unsigned tclk_miss:1;
2232+ u8 tclk_settle;
2233+};
2234+
2235+struct isp_csi2_phy_cfg_update {
2236+ bool ths_term;
2237+ bool ths_settle;
2238+ bool tclk_term;
2239+ bool tclk_miss;
2240+ bool tclk_settle;
2241+};
2242+
2243+struct isp_csi2_ctx_cfg {
2244+ u8 virtual_id;
2245+ u8 frame_count;
2246+ struct v4l2_pix_format format;
2247+ u16 alpha;
2248+ u16 data_offset;
2249+ u32 ping_addr;
2250+ u32 pong_addr;
2251+ bool eof_enabled;
2252+ bool eol_enabled;
2253+ bool checksum_enabled;
2254+ bool enabled;
2255+};
2256+
2257+struct isp_csi2_ctx_cfg_update {
2258+ bool virtual_id;
2259+ bool frame_count;
2260+ bool format;
2261+ bool alpha;
2262+ bool data_offset;
2263+ bool ping_addr;
2264+ bool pong_addr;
2265+ bool eof_enabled;
2266+ bool eol_enabled;
2267+ bool checksum_enabled;
2268+ bool enabled;
2269+};
2270+
2271+struct isp_csi2_timings_cfg {
2272+ bool force_rx_mode;
2273+ bool stop_state_16x;
2274+ bool stop_state_4x;
2275+ u16 stop_state_counter;
2276+};
2277+
2278+struct isp_csi2_timings_cfg_update {
2279+ bool force_rx_mode;
2280+ bool stop_state_16x;
2281+ bool stop_state_4x;
2282+ bool stop_state_counter;
2283+};
2284+
2285+struct isp_csi2_ctrl_cfg {
2286+ bool vp_clk_enable;
2287+ bool vp_only_enable;
2288+ u8 vp_out_ctrl;
2289+ bool debug_enable;
2290+ u8 burst_size;
2291+ enum isp_csi2_frame_mode frame_mode;
2292+ bool ecc_enable;
2293+ bool secure_mode;
2294+ bool if_enable;
2295+};
2296+
2297+struct isp_csi2_ctrl_cfg_update {
2298+ bool vp_clk_enable;
2299+ bool vp_only_enable;
2300+ bool vp_out_ctrl;
2301+ bool debug_enable;
2302+ bool burst_size;
2303+ bool frame_mode;
2304+ bool ecc_enable;
2305+ bool secure_mode;
2306+ bool if_enable;
2307+};
2308+
2309+struct isp_csi2_cfg {
2310+ struct isp_csi2_lanes_cfg lanes;
2311+ struct isp_csi2_phy_cfg phy;
2312+ struct isp_csi2_ctx_cfg contexts[8];
2313+ struct isp_csi2_timings_cfg timings[2];
2314+ struct isp_csi2_ctrl_cfg ctrl;
2315+};
2316+
2317+struct isp_csi2_cfg_update {
2318+ struct isp_csi2_lanes_cfg_update lanes;
2319+ struct isp_csi2_phy_cfg_update phy;
2320+ struct isp_csi2_ctx_cfg_update contexts[8];
2321+ struct isp_csi2_timings_cfg_update timings[2];
2322+ struct isp_csi2_ctrl_cfg_update ctrl;
2323+};
2324+
2325+int isp_csi2_complexio_lanes_config(struct isp_csi2_lanes_cfg *reqcfg);
2326+int isp_csi2_complexio_lanes_update(bool force_update);
2327+int isp_csi2_complexio_lanes_get(void);
2328+int isp_csi2_complexio_power_autoswitch(bool enable);
2329+int isp_csi2_complexio_power(enum isp_csi2_power_cmds power_cmd);
2330+int isp_csi2_ctrl_config_frame_mode(enum isp_csi2_frame_mode frame_mode);
2331+int isp_csi2_ctrl_config_vp_clk_enable(bool vp_clk_enable);
2332+int isp_csi2_ctrl_config_vp_only_enable(bool vp_only_enable);
2333+int isp_csi2_ctrl_config_debug_enable(bool debug_enable);
2334+int isp_csi2_ctrl_config_burst_size(u8 burst_size);
2335+int isp_csi2_ctrl_config_ecc_enable(bool ecc_enable);
2336+int isp_csi2_ctrl_config_secure_mode(bool secure_mode);
2337+int isp_csi2_ctrl_config_if_enable(bool if_enable);
2338+int isp_csi2_ctrl_config_vp_out_ctrl(u8 vp_out_ctrl);
2339+int isp_csi2_ctrl_update(bool force_update);
2340+int isp_csi2_ctrl_get(void);
2341+int isp_csi2_ctx_config_virtual_id(u8 ctxnum, u8 virtual_id);
2342+int isp_csi2_ctx_config_frame_count(u8 ctxnum, u8 frame_count);
2343+int isp_csi2_ctx_config_format(u8 ctxnum, u32 pixformat);
2344+int isp_csi2_ctx_config_alpha(u8 ctxnum, u16 alpha);
2345+int isp_csi2_ctx_config_data_offset(u8 ctxnum, u16 data_offset);
2346+int isp_csi2_ctx_config_ping_addr(u8 ctxnum, u32 ping_addr);
2347+int isp_csi2_ctx_config_pong_addr(u8 ctxnum, u32 pong_addr);
2348+int isp_csi2_ctx_config_eof_enabled(u8 ctxnum, bool eof_enabled);
2349+int isp_csi2_ctx_config_eol_enabled(u8 ctxnum, bool eol_enabled);
2350+int isp_csi2_ctx_config_checksum_enabled(u8 ctxnum, bool checksum_enabled);
2351+int isp_csi2_ctx_config_enabled(u8 ctxnum, bool enabled);
2352+int isp_csi2_ctx_update(u8 ctxnum, bool force_update);
2353+int isp_csi2_ctx_get(u8 ctxnum);
2354+int isp_csi2_ctx_update_all(bool force_update);
2355+int isp_csi2_ctx_get_all(void);
2356+int isp_csi2_phy_config(struct isp_csi2_phy_cfg *desiredphyconfig);
2357+int isp_csi2_calc_phy_cfg0(u32 mipiclk, u32 lbound_hs_settle,
2358+ u32 ubound_hs_settle);
2359+int isp_csi2_phy_update(bool force_update);
2360+int isp_csi2_phy_get(void);
2361+int isp_csi2_timings_config_forcerxmode(u8 io, bool force_rx_mode);
2362+int isp_csi2_timings_config_stopstate_16x(u8 io, bool stop_state_16x);
2363+int isp_csi2_timings_config_stopstate_4x(u8 io, bool stop_state_4x);
2364+int isp_csi2_timings_config_stopstate_cnt(u8 io, u16 stop_state_counter);
2365+int isp_csi2_timings_update(u8 io, bool force_update);
2366+int isp_csi2_timings_get(u8 io);
2367+int isp_csi2_timings_update_all(bool force_update);
2368+int isp_csi2_timings_get_all(void);
2369+void isp_csi2_irq_complexio1_set(int enable);
2370+void isp_csi2_irq_ctx_set(int enable);
2371+void isp_csi2_irq_status_set(int enable);
2372+void isp_csi2_irq_set(int enable);
2373+void isp_csi2_irq_all_set(int enable);
2374+
2375+void isp_csi2_isr(void);
2376+int isp_csi2_reset(void);
2377+void isp_csi2_enable(int enable);
2378+void isp_csi2_regdump(void);
2379+
2380+#endif /* OMAP_ISP_CSI2_H */
2381+
2382--
23831.5.6.5
2384
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch
new file mode 100644
index 0000000000..db023e514d
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0008-omap3isp-Add-ISP-tables.patch
@@ -0,0 +1,4018 @@
1From 5de7cb2cac5f7d76cb025ddc8fb09c99a1007e08 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:02 +0200
4Subject: [PATCH] omap3isp: Add ISP tables
5
6* Blue Gamma gain table
7* CFA gain table
8* Green Gamma gain table
9* Luma Enhancement gain table
10* Noise filter gain table
11* Red Gamma gain table
12
13TODO:
14
15- Get rid of this kind of tables. Either generate them at runtime or
16 use a user space program to fill defaults.
17
18Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
19---
20 drivers/media/video/isp/bluegamma_table.h | 1040 ++++++++++++++++++++++++++
21 drivers/media/video/isp/cfa_coef_table.h | 603 +++++++++++++++
22 drivers/media/video/isp/greengamma_table.h | 1040 ++++++++++++++++++++++++++
23 drivers/media/video/isp/luma_enhance_table.h | 144 ++++
24 drivers/media/video/isp/noise_filter_table.h | 79 ++
25 drivers/media/video/isp/redgamma_table.h | 1040 ++++++++++++++++++++++++++
26 6 files changed, 3946 insertions(+), 0 deletions(-)
27 create mode 100644 drivers/media/video/isp/bluegamma_table.h
28 create mode 100644 drivers/media/video/isp/cfa_coef_table.h
29 create mode 100644 drivers/media/video/isp/greengamma_table.h
30 create mode 100644 drivers/media/video/isp/luma_enhance_table.h
31 create mode 100644 drivers/media/video/isp/noise_filter_table.h
32 create mode 100644 drivers/media/video/isp/redgamma_table.h
33
34diff --git a/drivers/media/video/isp/bluegamma_table.h b/drivers/media/video/isp/bluegamma_table.h
35new file mode 100644
36index 0000000..301382a
37--- /dev/null
38+++ b/drivers/media/video/isp/bluegamma_table.h
39@@ -0,0 +1,1040 @@
40+/*
41+ * bluegamma_table.h
42+ *
43+ * Gamma Table values for BLUE for TI's OMAP3 Camera ISP
44+ *
45+ * Copyright (C) 2009 Texas Instruments, Inc.
46+ *
47+ * This package is free software; you can redistribute it and/or modify
48+ * it under the terms of the GNU General Public License version 2 as
49+ * published by the Free Software Foundation.
50+ *
51+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
52+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
53+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
54+ */
55+
56+0,
57+0,
58+1,
59+2,
60+3,
61+3,
62+4,
63+5,
64+6,
65+8,
66+10,
67+12,
68+14,
69+16,
70+18,
71+20,
72+22,
73+23,
74+25,
75+26,
76+28,
77+29,
78+31,
79+32,
80+34,
81+35,
82+36,
83+37,
84+39,
85+40,
86+41,
87+42,
88+43,
89+44,
90+45,
91+46,
92+47,
93+48,
94+49,
95+50,
96+51,
97+52,
98+52,
99+53,
100+54,
101+55,
102+56,
103+57,
104+58,
105+59,
106+60,
107+61,
108+62,
109+63,
110+63,
111+64,
112+65,
113+66,
114+66,
115+67,
116+68,
117+69,
118+69,
119+70,
120+71,
121+72,
122+72,
123+73,
124+74,
125+75,
126+75,
127+76,
128+77,
129+78,
130+78,
131+79,
132+80,
133+81,
134+81,
135+82,
136+83,
137+84,
138+84,
139+85,
140+86,
141+87,
142+88,
143+88,
144+89,
145+90,
146+91,
147+91,
148+92,
149+93,
150+94,
151+94,
152+95,
153+96,
154+97,
155+97,
156+98,
157+98,
158+99,
159+99,
160+100,
161+100,
162+101,
163+101,
164+102,
165+103,
166+104,
167+104,
168+105,
169+106,
170+107,
171+108,
172+108,
173+109,
174+110,
175+111,
176+111,
177+112,
178+113,
179+114,
180+114,
181+115,
182+116,
183+117,
184+117,
185+118,
186+119,
187+119,
188+120,
189+120,
190+121,
191+121,
192+122,
193+122,
194+123,
195+123,
196+124,
197+124,
198+125,
199+125,
200+126,
201+126,
202+127,
203+127,
204+128,
205+128,
206+129,
207+129,
208+130,
209+130,
210+131,
211+131,
212+132,
213+132,
214+133,
215+133,
216+134,
217+134,
218+135,
219+135,
220+136,
221+136,
222+137,
223+137,
224+138,
225+138,
226+139,
227+139,
228+140,
229+140,
230+141,
231+141,
232+142,
233+142,
234+143,
235+143,
236+144,
237+144,
238+145,
239+145,
240+146,
241+146,
242+147,
243+147,
244+148,
245+148,
246+149,
247+149,
248+150,
249+150,
250+151,
251+151,
252+152,
253+152,
254+153,
255+153,
256+153,
257+153,
258+154,
259+154,
260+154,
261+154,
262+155,
263+155,
264+156,
265+156,
266+157,
267+157,
268+158,
269+158,
270+158,
271+159,
272+159,
273+159,
274+160,
275+160,
276+160,
277+161,
278+161,
279+162,
280+162,
281+163,
282+163,
283+164,
284+164,
285+164,
286+164,
287+165,
288+165,
289+165,
290+165,
291+166,
292+166,
293+167,
294+167,
295+168,
296+168,
297+169,
298+169,
299+170,
300+170,
301+170,
302+170,
303+171,
304+171,
305+171,
306+171,
307+172,
308+172,
309+173,
310+173,
311+174,
312+174,
313+175,
314+175,
315+176,
316+176,
317+176,
318+176,
319+177,
320+177,
321+177,
322+177,
323+178,
324+178,
325+178,
326+178,
327+179,
328+179,
329+179,
330+179,
331+180,
332+180,
333+180,
334+180,
335+181,
336+181,
337+181,
338+181,
339+182,
340+182,
341+182,
342+182,
343+183,
344+183,
345+183,
346+183,
347+184,
348+184,
349+184,
350+184,
351+185,
352+185,
353+185,
354+185,
355+186,
356+186,
357+186,
358+186,
359+187,
360+187,
361+187,
362+187,
363+188,
364+188,
365+188,
366+188,
367+189,
368+189,
369+189,
370+189,
371+190,
372+190,
373+190,
374+190,
375+191,
376+191,
377+191,
378+191,
379+192,
380+192,
381+192,
382+192,
383+193,
384+193,
385+193,
386+193,
387+194,
388+194,
389+194,
390+194,
391+195,
392+195,
393+195,
394+195,
395+196,
396+196,
397+196,
398+196,
399+197,
400+197,
401+197,
402+197,
403+198,
404+198,
405+198,
406+198,
407+199,
408+199,
409+199,
410+199,
411+200,
412+200,
413+200,
414+200,
415+201,
416+201,
417+201,
418+201,
419+202,
420+202,
421+202,
422+203,
423+203,
424+203,
425+203,
426+204,
427+204,
428+204,
429+204,
430+205,
431+205,
432+205,
433+205,
434+206,
435+206,
436+206,
437+206,
438+207,
439+207,
440+207,
441+207,
442+208,
443+208,
444+208,
445+208,
446+209,
447+209,
448+209,
449+209,
450+210,
451+210,
452+210,
453+210,
454+210,
455+210,
456+210,
457+210,
458+210,
459+210,
460+210,
461+210,
462+211,
463+211,
464+211,
465+211,
466+211,
467+211,
468+211,
469+211,
470+211,
471+211,
472+211,
473+212,
474+212,
475+212,
476+212,
477+213,
478+213,
479+213,
480+213,
481+213,
482+213,
483+213,
484+213,
485+213,
486+213,
487+213,
488+213,
489+214,
490+214,
491+214,
492+214,
493+215,
494+215,
495+215,
496+215,
497+215,
498+215,
499+215,
500+215,
501+215,
502+215,
503+215,
504+216,
505+216,
506+216,
507+216,
508+217,
509+217,
510+217,
511+217,
512+218,
513+218,
514+218,
515+218,
516+219,
517+219,
518+219,
519+219,
520+219,
521+219,
522+219,
523+219,
524+219,
525+219,
526+219,
527+219,
528+220,
529+220,
530+220,
531+220,
532+221,
533+221,
534+221,
535+221,
536+221,
537+221,
538+221,
539+221,
540+221,
541+221,
542+221,
543+222,
544+222,
545+222,
546+222,
547+223,
548+223,
549+223,
550+223,
551+223,
552+223,
553+223,
554+223,
555+223,
556+223,
557+223,
558+223,
559+224,
560+224,
561+224,
562+224,
563+225,
564+225,
565+225,
566+225,
567+225,
568+225,
569+225,
570+225,
571+225,
572+225,
573+225,
574+225,
575+225,
576+225,
577+225,
578+225,
579+225,
580+225,
581+225,
582+226,
583+226,
584+226,
585+226,
586+227,
587+227,
588+227,
589+227,
590+227,
591+227,
592+227,
593+227,
594+227,
595+227,
596+227,
597+227,
598+228,
599+228,
600+228,
601+229,
602+229,
603+229,
604+229,
605+229,
606+229,
607+229,
608+229,
609+229,
610+229,
611+229,
612+229,
613+230,
614+230,
615+230,
616+230,
617+231,
618+231,
619+231,
620+231,
621+231,
622+231,
623+231,
624+231,
625+231,
626+231,
627+231,
628+231,
629+232,
630+232,
631+232,
632+232,
633+232,
634+232,
635+232,
636+232,
637+232,
638+232,
639+232,
640+232,
641+232,
642+232,
643+232,
644+232,
645+232,
646+232,
647+232,
648+233,
649+233,
650+233,
651+233,
652+234,
653+234,
654+234,
655+234,
656+234,
657+234,
658+234,
659+234,
660+234,
661+234,
662+234,
663+235,
664+235,
665+235,
666+235,
667+236,
668+236,
669+236,
670+236,
671+236,
672+236,
673+236,
674+236,
675+236,
676+236,
677+236,
678+236,
679+236,
680+236,
681+236,
682+236,
683+236,
684+236,
685+236,
686+237,
687+237,
688+237,
689+237,
690+238,
691+238,
692+238,
693+238,
694+238,
695+238,
696+238,
697+238,
698+238,
699+238,
700+238,
701+238,
702+238,
703+238,
704+238,
705+238,
706+238,
707+238,
708+238,
709+238,
710+238,
711+238,
712+238,
713+238,
714+238,
715+238,
716+238,
717+239,
718+239,
719+239,
720+239,
721+240,
722+240,
723+240,
724+240,
725+240,
726+240,
727+240,
728+240,
729+240,
730+240,
731+240,
732+240,
733+240,
734+240,
735+240,
736+240,
737+240,
738+240,
739+240,
740+240,
741+240,
742+240,
743+240,
744+240,
745+240,
746+240,
747+240,
748+241,
749+241,
750+241,
751+241,
752+242,
753+242,
754+242,
755+242,
756+242,
757+242,
758+242,
759+242,
760+242,
761+242,
762+242,
763+242,
764+242,
765+242,
766+242,
767+242,
768+242,
769+242,
770+242,
771+242,
772+242,
773+242,
774+242,
775+242,
776+242,
777+242,
778+243,
779+243,
780+243,
781+243,
782+244,
783+244,
784+244,
785+244,
786+244,
787+244,
788+244,
789+244,
790+244,
791+244,
792+244,
793+244,
794+244,
795+244,
796+244,
797+244,
798+244,
799+244,
800+244,
801+244,
802+244,
803+244,
804+244,
805+244,
806+244,
807+244,
808+244,
809+245,
810+245,
811+245,
812+245,
813+246,
814+246,
815+246,
816+246,
817+246,
818+246,
819+246,
820+246,
821+246,
822+246,
823+246,
824+246,
825+246,
826+246,
827+246,
828+246,
829+246,
830+246,
831+246,
832+246,
833+246,
834+246,
835+246,
836+246,
837+246,
838+246,
839+246,
840+246,
841+246,
842+246,
843+246,
844+246,
845+246,
846+246,
847+247,
848+247,
849+247,
850+247,
851+248,
852+248,
853+248,
854+248,
855+248,
856+248,
857+248,
858+248,
859+248,
860+248,
861+248,
862+248,
863+248,
864+248,
865+248,
866+248,
867+248,
868+248,
869+248,
870+248,
871+248,
872+248,
873+248,
874+248,
875+248,
876+248,
877+248,
878+249,
879+249,
880+249,
881+249,
882+250,
883+250,
884+250,
885+250,
886+250,
887+250,
888+250,
889+250,
890+250,
891+250,
892+250,
893+250,
894+250,
895+250,
896+250,
897+250,
898+250,
899+250,
900+250,
901+250,
902+250,
903+250,
904+250,
905+250,
906+250,
907+250,
908+250,
909+250,
910+250,
911+250,
912+250,
913+250,
914+250,
915+250,
916+250,
917+250,
918+250,
919+250,
920+250,
921+250,
922+250,
923+250,
924+251,
925+251,
926+251,
927+251,
928+252,
929+252,
930+252,
931+252,
932+252,
933+252,
934+252,
935+252,
936+252,
937+252,
938+252,
939+252,
940+252,
941+252,
942+252,
943+252,
944+252,
945+252,
946+252,
947+252,
948+252,
949+252,
950+252,
951+252,
952+252,
953+252,
954+252,
955+252,
956+252,
957+252,
958+252,
959+252,
960+252,
961+252,
962+252,
963+252,
964+252,
965+252,
966+252,
967+252,
968+252,
969+252,
970+252,
971+252,
972+252,
973+252,
974+252,
975+252,
976+252,
977+252,
978+252,
979+252,
980+252,
981+252,
982+252,
983+252,
984+252,
985+252,
986+252,
987+252,
988+252,
989+252,
990+252,
991+252,
992+253,
993+253,
994+253,
995+253,
996+253,
997+253,
998+253,
999+253,
1000+253,
1001+253,
1002+253,
1003+253,
1004+253,
1005+253,
1006+253,
1007+253,
1008+253,
1009+253,
1010+253,
1011+253,
1012+253,
1013+253,
1014+253,
1015+253,
1016+253,
1017+253,
1018+253,
1019+253,
1020+253,
1021+253,
1022+253,
1023+253,
1024+253,
1025+253,
1026+253,
1027+253,
1028+253,
1029+253,
1030+253,
1031+253,
1032+253,
1033+253,
1034+253,
1035+253,
1036+253,
1037+253,
1038+253,
1039+253,
1040+253,
1041+253,
1042+253,
1043+253,
1044+253,
1045+253,
1046+253,
1047+253,
1048+253,
1049+254,
1050+254,
1051+254,
1052+254,
1053+255,
1054+255,
1055+255,
1056+255,
1057+255,
1058+255,
1059+255,
1060+255,
1061+255,
1062+255,
1063+255,
1064+255,
1065+255,
1066+255,
1067+255,
1068+255,
1069+255,
1070+255,
1071+255,
1072+255,
1073+255,
1074+255,
1075+255,
1076+255,
1077+255,
1078+255,
1079+255
1080diff --git a/drivers/media/video/isp/cfa_coef_table.h b/drivers/media/video/isp/cfa_coef_table.h
1081new file mode 100644
1082index 0000000..8cafa1f
1083--- /dev/null
1084+++ b/drivers/media/video/isp/cfa_coef_table.h
1085@@ -0,0 +1,603 @@
1086+/*
1087+ * cfa_coef_table.h
1088+ *
1089+ * Copyright (C) 2009 Nokia Corporation
1090+ *
1091+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
1092+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
1093+ *
1094+ * Written by Gjorgji Rosikopulos
1095+ *
1096+ * This program is free software; you can redistribute it and/or
1097+ * modify it under the terms of the GNU General Public License
1098+ * version 2 as published by the Free Software Foundation.
1099+ *
1100+ * This program is distributed in the hope that it will be useful, but
1101+ * WITHOUT ANY WARRANTY; without even the implied warranty of
1102+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1103+ * General Public License for more details.
1104+ *
1105+ * You should have received a copy of the GNU General Public License
1106+ * along with this program; if not, write to the Free Software
1107+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1108+ * 02110-1301 USA
1109+ *
1110+ */
1111+
1112+244,
1113+0,
1114+247,
1115+0,
1116+12,
1117+27,
1118+36,
1119+247,
1120+250,
1121+0,
1122+27,
1123+0,
1124+4,
1125+250,
1126+12,
1127+244,
1128+248,
1129+0,
1130+0,
1131+0,
1132+0,
1133+40,
1134+0,
1135+0,
1136+244,
1137+12,
1138+250,
1139+4,
1140+0,
1141+27,
1142+0,
1143+250,
1144+247,
1145+36,
1146+27,
1147+12,
1148+0,
1149+247,
1150+0,
1151+244,
1152+0,
1153+0,
1154+40,
1155+0,
1156+0,
1157+0,
1158+0,
1159+248,
1160+244,
1161+0,
1162+247,
1163+0,
1164+12,
1165+27,
1166+36,
1167+247,
1168+250,
1169+0,
1170+27,
1171+0,
1172+4,
1173+250,
1174+12,
1175+244,
1176+248,
1177+0,
1178+0,
1179+0,
1180+0,
1181+40,
1182+0,
1183+0,
1184+244,
1185+12,
1186+250,
1187+4,
1188+0,
1189+27,
1190+0,
1191+250,
1192+247,
1193+36,
1194+27,
1195+12,
1196+0,
1197+247,
1198+0,
1199+244,
1200+0,
1201+0,
1202+40,
1203+0,
1204+0,
1205+0,
1206+0,
1207+248,
1208+244,
1209+0,
1210+247,
1211+0,
1212+12,
1213+27,
1214+36,
1215+247,
1216+250,
1217+0,
1218+27,
1219+0,
1220+4,
1221+250,
1222+12,
1223+244,
1224+248,
1225+0,
1226+0,
1227+0,
1228+0,
1229+40,
1230+0,
1231+0,
1232+244,
1233+12,
1234+250,
1235+4,
1236+0,
1237+27,
1238+0,
1239+250,
1240+247,
1241+36,
1242+27,
1243+12,
1244+0,
1245+247,
1246+0,
1247+244,
1248+0,
1249+0,
1250+40,
1251+0,
1252+0,
1253+0,
1254+0,
1255+248,
1256+0,
1257+247,
1258+0,
1259+244,
1260+247,
1261+36,
1262+27,
1263+12,
1264+0,
1265+27,
1266+0,
1267+250,
1268+244,
1269+12,
1270+250,
1271+4,
1272+0,
1273+0,
1274+0,
1275+248,
1276+0,
1277+0,
1278+40,
1279+0,
1280+4,
1281+250,
1282+12,
1283+244,
1284+250,
1285+0,
1286+27,
1287+0,
1288+12,
1289+27,
1290+36,
1291+247,
1292+244,
1293+0,
1294+247,
1295+0,
1296+0,
1297+40,
1298+0,
1299+0,
1300+248,
1301+0,
1302+0,
1303+0,
1304+0,
1305+247,
1306+0,
1307+244,
1308+247,
1309+36,
1310+27,
1311+12,
1312+0,
1313+27,
1314+0,
1315+250,
1316+244,
1317+12,
1318+250,
1319+4,
1320+0,
1321+0,
1322+0,
1323+248,
1324+0,
1325+0,
1326+40,
1327+0,
1328+4,
1329+250,
1330+12,
1331+244,
1332+250,
1333+0,
1334+27,
1335+0,
1336+12,
1337+27,
1338+36,
1339+247,
1340+244,
1341+0,
1342+247,
1343+0,
1344+0,
1345+40,
1346+0,
1347+0,
1348+248,
1349+0,
1350+0,
1351+0,
1352+0,
1353+247,
1354+0,
1355+244,
1356+247,
1357+36,
1358+27,
1359+12,
1360+0,
1361+27,
1362+0,
1363+250,
1364+244,
1365+12,
1366+250,
1367+4,
1368+0,
1369+0,
1370+0,
1371+248,
1372+0,
1373+0,
1374+40,
1375+0,
1376+4,
1377+250,
1378+12,
1379+244,
1380+250,
1381+0,
1382+27,
1383+0,
1384+12,
1385+27,
1386+36,
1387+247,
1388+244,
1389+0,
1390+247,
1391+0,
1392+0,
1393+40,
1394+0,
1395+0,
1396+248,
1397+0,
1398+0,
1399+0,
1400+4,
1401+250,
1402+12,
1403+244,
1404+250,
1405+0,
1406+27,
1407+0,
1408+12,
1409+27,
1410+36,
1411+247,
1412+244,
1413+0,
1414+247,
1415+0,
1416+0,
1417+0,
1418+0,
1419+248,
1420+0,
1421+0,
1422+40,
1423+0,
1424+0,
1425+247,
1426+0,
1427+244,
1428+247,
1429+36,
1430+27,
1431+12,
1432+0,
1433+27,
1434+0,
1435+250,
1436+244,
1437+12,
1438+250,
1439+4,
1440+0,
1441+40,
1442+0,
1443+0,
1444+248,
1445+0,
1446+0,
1447+0,
1448+4,
1449+250,
1450+12,
1451+244,
1452+250,
1453+0,
1454+27,
1455+0,
1456+12,
1457+27,
1458+36,
1459+247,
1460+244,
1461+0,
1462+247,
1463+0,
1464+0,
1465+0,
1466+0,
1467+248,
1468+0,
1469+0,
1470+40,
1471+0,
1472+0,
1473+247,
1474+0,
1475+244,
1476+247,
1477+36,
1478+27,
1479+12,
1480+0,
1481+27,
1482+0,
1483+250,
1484+244,
1485+12,
1486+250,
1487+4,
1488+0,
1489+40,
1490+0,
1491+0,
1492+248,
1493+0,
1494+0,
1495+0,
1496+4,
1497+250,
1498+12,
1499+244,
1500+250,
1501+0,
1502+27,
1503+0,
1504+12,
1505+27,
1506+36,
1507+247,
1508+244,
1509+0,
1510+247,
1511+0,
1512+0,
1513+0,
1514+0,
1515+248,
1516+0,
1517+0,
1518+40,
1519+0,
1520+0,
1521+247,
1522+0,
1523+244,
1524+247,
1525+36,
1526+27,
1527+12,
1528+0,
1529+27,
1530+0,
1531+250,
1532+244,
1533+12,
1534+250,
1535+4,
1536+0,
1537+40,
1538+0,
1539+0,
1540+248,
1541+0,
1542+0,
1543+0,
1544+244,
1545+12,
1546+250,
1547+4,
1548+0,
1549+27,
1550+0,
1551+250,
1552+247,
1553+36,
1554+27,
1555+12,
1556+0,
1557+247,
1558+0,
1559+244,
1560+248,
1561+0,
1562+0,
1563+0,
1564+0,
1565+40,
1566+0,
1567+0,
1568+244,
1569+0,
1570+247,
1571+0,
1572+12,
1573+27,
1574+36,
1575+247,
1576+250,
1577+0,
1578+27,
1579+0,
1580+4,
1581+250,
1582+12,
1583+244,
1584+0,
1585+0,
1586+40,
1587+0,
1588+0,
1589+0,
1590+0,
1591+248,
1592+244,
1593+12,
1594+250,
1595+4,
1596+0,
1597+27,
1598+0,
1599+250,
1600+247,
1601+36,
1602+27,
1603+12,
1604+0,
1605+247,
1606+0,
1607+244,
1608+248,
1609+0,
1610+0,
1611+0,
1612+0,
1613+40,
1614+0,
1615+0,
1616+244,
1617+0,
1618+247,
1619+0,
1620+12,
1621+27,
1622+36,
1623+247,
1624+250,
1625+0,
1626+27,
1627+0,
1628+4,
1629+250,
1630+12,
1631+244,
1632+0,
1633+0,
1634+40,
1635+0,
1636+0,
1637+0,
1638+0,
1639+248,
1640+244,
1641+12,
1642+250,
1643+4,
1644+0,
1645+27,
1646+0,
1647+250,
1648+247,
1649+36,
1650+27,
1651+12,
1652+0,
1653+247,
1654+0,
1655+244,
1656+248,
1657+0,
1658+0,
1659+0,
1660+0,
1661+40,
1662+0,
1663+0,
1664+244,
1665+0,
1666+247,
1667+0,
1668+12,
1669+27,
1670+36,
1671+247,
1672+250,
1673+0,
1674+27,
1675+0,
1676+4,
1677+250,
1678+12,
1679+244,
1680+0,
1681+0,
1682+40,
1683+0,
1684+0,
1685+0,
1686+0,
1687+248
1688+
1689diff --git a/drivers/media/video/isp/greengamma_table.h b/drivers/media/video/isp/greengamma_table.h
1690new file mode 100644
1691index 0000000..0f5c5e4
1692--- /dev/null
1693+++ b/drivers/media/video/isp/greengamma_table.h
1694@@ -0,0 +1,1040 @@
1695+/*
1696+ * greengamma_table.h
1697+ *
1698+ * Gamma Table values for GREEN for TI's OMAP3 Camera ISP
1699+ *
1700+ * Copyright (C) 2009 Texas Instruments, Inc.
1701+ *
1702+ * This package is free software; you can redistribute it and/or modify
1703+ * it under the terms of the GNU General Public License version 2 as
1704+ * published by the Free Software Foundation.
1705+ *
1706+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1707+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1708+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1709+ */
1710+
1711+0,
1712+0,
1713+1,
1714+2,
1715+3,
1716+3,
1717+4,
1718+5,
1719+6,
1720+8,
1721+10,
1722+12,
1723+14,
1724+16,
1725+18,
1726+20,
1727+22,
1728+23,
1729+25,
1730+26,
1731+28,
1732+29,
1733+31,
1734+32,
1735+34,
1736+35,
1737+36,
1738+37,
1739+39,
1740+40,
1741+41,
1742+42,
1743+43,
1744+44,
1745+45,
1746+46,
1747+47,
1748+48,
1749+49,
1750+50,
1751+51,
1752+52,
1753+52,
1754+53,
1755+54,
1756+55,
1757+56,
1758+57,
1759+58,
1760+59,
1761+60,
1762+61,
1763+62,
1764+63,
1765+63,
1766+64,
1767+65,
1768+66,
1769+66,
1770+67,
1771+68,
1772+69,
1773+69,
1774+70,
1775+71,
1776+72,
1777+72,
1778+73,
1779+74,
1780+75,
1781+75,
1782+76,
1783+77,
1784+78,
1785+78,
1786+79,
1787+80,
1788+81,
1789+81,
1790+82,
1791+83,
1792+84,
1793+84,
1794+85,
1795+86,
1796+87,
1797+88,
1798+88,
1799+89,
1800+90,
1801+91,
1802+91,
1803+92,
1804+93,
1805+94,
1806+94,
1807+95,
1808+96,
1809+97,
1810+97,
1811+98,
1812+98,
1813+99,
1814+99,
1815+100,
1816+100,
1817+101,
1818+101,
1819+102,
1820+103,
1821+104,
1822+104,
1823+105,
1824+106,
1825+107,
1826+108,
1827+108,
1828+109,
1829+110,
1830+111,
1831+111,
1832+112,
1833+113,
1834+114,
1835+114,
1836+115,
1837+116,
1838+117,
1839+117,
1840+118,
1841+119,
1842+119,
1843+120,
1844+120,
1845+121,
1846+121,
1847+122,
1848+122,
1849+123,
1850+123,
1851+124,
1852+124,
1853+125,
1854+125,
1855+126,
1856+126,
1857+127,
1858+127,
1859+128,
1860+128,
1861+129,
1862+129,
1863+130,
1864+130,
1865+131,
1866+131,
1867+132,
1868+132,
1869+133,
1870+133,
1871+134,
1872+134,
1873+135,
1874+135,
1875+136,
1876+136,
1877+137,
1878+137,
1879+138,
1880+138,
1881+139,
1882+139,
1883+140,
1884+140,
1885+141,
1886+141,
1887+142,
1888+142,
1889+143,
1890+143,
1891+144,
1892+144,
1893+145,
1894+145,
1895+146,
1896+146,
1897+147,
1898+147,
1899+148,
1900+148,
1901+149,
1902+149,
1903+150,
1904+150,
1905+151,
1906+151,
1907+152,
1908+152,
1909+153,
1910+153,
1911+153,
1912+153,
1913+154,
1914+154,
1915+154,
1916+154,
1917+155,
1918+155,
1919+156,
1920+156,
1921+157,
1922+157,
1923+158,
1924+158,
1925+158,
1926+159,
1927+159,
1928+159,
1929+160,
1930+160,
1931+160,
1932+161,
1933+161,
1934+162,
1935+162,
1936+163,
1937+163,
1938+164,
1939+164,
1940+164,
1941+164,
1942+165,
1943+165,
1944+165,
1945+165,
1946+166,
1947+166,
1948+167,
1949+167,
1950+168,
1951+168,
1952+169,
1953+169,
1954+170,
1955+170,
1956+170,
1957+170,
1958+171,
1959+171,
1960+171,
1961+171,
1962+172,
1963+172,
1964+173,
1965+173,
1966+174,
1967+174,
1968+175,
1969+175,
1970+176,
1971+176,
1972+176,
1973+176,
1974+177,
1975+177,
1976+177,
1977+177,
1978+178,
1979+178,
1980+178,
1981+178,
1982+179,
1983+179,
1984+179,
1985+179,
1986+180,
1987+180,
1988+180,
1989+180,
1990+181,
1991+181,
1992+181,
1993+181,
1994+182,
1995+182,
1996+182,
1997+182,
1998+183,
1999+183,
2000+183,
2001+183,
2002+184,
2003+184,
2004+184,
2005+184,
2006+185,
2007+185,
2008+185,
2009+185,
2010+186,
2011+186,
2012+186,
2013+186,
2014+187,
2015+187,
2016+187,
2017+187,
2018+188,
2019+188,
2020+188,
2021+188,
2022+189,
2023+189,
2024+189,
2025+189,
2026+190,
2027+190,
2028+190,
2029+190,
2030+191,
2031+191,
2032+191,
2033+191,
2034+192,
2035+192,
2036+192,
2037+192,
2038+193,
2039+193,
2040+193,
2041+193,
2042+194,
2043+194,
2044+194,
2045+194,
2046+195,
2047+195,
2048+195,
2049+195,
2050+196,
2051+196,
2052+196,
2053+196,
2054+197,
2055+197,
2056+197,
2057+197,
2058+198,
2059+198,
2060+198,
2061+198,
2062+199,
2063+199,
2064+199,
2065+199,
2066+200,
2067+200,
2068+200,
2069+200,
2070+201,
2071+201,
2072+201,
2073+201,
2074+202,
2075+202,
2076+202,
2077+203,
2078+203,
2079+203,
2080+203,
2081+204,
2082+204,
2083+204,
2084+204,
2085+205,
2086+205,
2087+205,
2088+205,
2089+206,
2090+206,
2091+206,
2092+206,
2093+207,
2094+207,
2095+207,
2096+207,
2097+208,
2098+208,
2099+208,
2100+208,
2101+209,
2102+209,
2103+209,
2104+209,
2105+210,
2106+210,
2107+210,
2108+210,
2109+210,
2110+210,
2111+210,
2112+210,
2113+210,
2114+210,
2115+210,
2116+210,
2117+211,
2118+211,
2119+211,
2120+211,
2121+211,
2122+211,
2123+211,
2124+211,
2125+211,
2126+211,
2127+211,
2128+212,
2129+212,
2130+212,
2131+212,
2132+213,
2133+213,
2134+213,
2135+213,
2136+213,
2137+213,
2138+213,
2139+213,
2140+213,
2141+213,
2142+213,
2143+213,
2144+214,
2145+214,
2146+214,
2147+214,
2148+215,
2149+215,
2150+215,
2151+215,
2152+215,
2153+215,
2154+215,
2155+215,
2156+215,
2157+215,
2158+215,
2159+216,
2160+216,
2161+216,
2162+216,
2163+217,
2164+217,
2165+217,
2166+217,
2167+218,
2168+218,
2169+218,
2170+218,
2171+219,
2172+219,
2173+219,
2174+219,
2175+219,
2176+219,
2177+219,
2178+219,
2179+219,
2180+219,
2181+219,
2182+219,
2183+220,
2184+220,
2185+220,
2186+220,
2187+221,
2188+221,
2189+221,
2190+221,
2191+221,
2192+221,
2193+221,
2194+221,
2195+221,
2196+221,
2197+221,
2198+222,
2199+222,
2200+222,
2201+222,
2202+223,
2203+223,
2204+223,
2205+223,
2206+223,
2207+223,
2208+223,
2209+223,
2210+223,
2211+223,
2212+223,
2213+223,
2214+224,
2215+224,
2216+224,
2217+224,
2218+225,
2219+225,
2220+225,
2221+225,
2222+225,
2223+225,
2224+225,
2225+225,
2226+225,
2227+225,
2228+225,
2229+225,
2230+225,
2231+225,
2232+225,
2233+225,
2234+225,
2235+225,
2236+225,
2237+226,
2238+226,
2239+226,
2240+226,
2241+227,
2242+227,
2243+227,
2244+227,
2245+227,
2246+227,
2247+227,
2248+227,
2249+227,
2250+227,
2251+227,
2252+227,
2253+228,
2254+228,
2255+228,
2256+229,
2257+229,
2258+229,
2259+229,
2260+229,
2261+229,
2262+229,
2263+229,
2264+229,
2265+229,
2266+229,
2267+229,
2268+230,
2269+230,
2270+230,
2271+230,
2272+231,
2273+231,
2274+231,
2275+231,
2276+231,
2277+231,
2278+231,
2279+231,
2280+231,
2281+231,
2282+231,
2283+231,
2284+232,
2285+232,
2286+232,
2287+232,
2288+232,
2289+232,
2290+232,
2291+232,
2292+232,
2293+232,
2294+232,
2295+232,
2296+232,
2297+232,
2298+232,
2299+232,
2300+232,
2301+232,
2302+232,
2303+233,
2304+233,
2305+233,
2306+233,
2307+234,
2308+234,
2309+234,
2310+234,
2311+234,
2312+234,
2313+234,
2314+234,
2315+234,
2316+234,
2317+234,
2318+235,
2319+235,
2320+235,
2321+235,
2322+236,
2323+236,
2324+236,
2325+236,
2326+236,
2327+236,
2328+236,
2329+236,
2330+236,
2331+236,
2332+236,
2333+236,
2334+236,
2335+236,
2336+236,
2337+236,
2338+236,
2339+236,
2340+236,
2341+237,
2342+237,
2343+237,
2344+237,
2345+238,
2346+238,
2347+238,
2348+238,
2349+238,
2350+238,
2351+238,
2352+238,
2353+238,
2354+238,
2355+238,
2356+238,
2357+238,
2358+238,
2359+238,
2360+238,
2361+238,
2362+238,
2363+238,
2364+238,
2365+238,
2366+238,
2367+238,
2368+238,
2369+238,
2370+238,
2371+238,
2372+239,
2373+239,
2374+239,
2375+239,
2376+240,
2377+240,
2378+240,
2379+240,
2380+240,
2381+240,
2382+240,
2383+240,
2384+240,
2385+240,
2386+240,
2387+240,
2388+240,
2389+240,
2390+240,
2391+240,
2392+240,
2393+240,
2394+240,
2395+240,
2396+240,
2397+240,
2398+240,
2399+240,
2400+240,
2401+240,
2402+240,
2403+241,
2404+241,
2405+241,
2406+241,
2407+242,
2408+242,
2409+242,
2410+242,
2411+242,
2412+242,
2413+242,
2414+242,
2415+242,
2416+242,
2417+242,
2418+242,
2419+242,
2420+242,
2421+242,
2422+242,
2423+242,
2424+242,
2425+242,
2426+242,
2427+242,
2428+242,
2429+242,
2430+242,
2431+242,
2432+242,
2433+243,
2434+243,
2435+243,
2436+243,
2437+244,
2438+244,
2439+244,
2440+244,
2441+244,
2442+244,
2443+244,
2444+244,
2445+244,
2446+244,
2447+244,
2448+244,
2449+244,
2450+244,
2451+244,
2452+244,
2453+244,
2454+244,
2455+244,
2456+244,
2457+244,
2458+244,
2459+244,
2460+244,
2461+244,
2462+244,
2463+244,
2464+245,
2465+245,
2466+245,
2467+245,
2468+246,
2469+246,
2470+246,
2471+246,
2472+246,
2473+246,
2474+246,
2475+246,
2476+246,
2477+246,
2478+246,
2479+246,
2480+246,
2481+246,
2482+246,
2483+246,
2484+246,
2485+246,
2486+246,
2487+246,
2488+246,
2489+246,
2490+246,
2491+246,
2492+246,
2493+246,
2494+246,
2495+246,
2496+246,
2497+246,
2498+246,
2499+246,
2500+246,
2501+246,
2502+247,
2503+247,
2504+247,
2505+247,
2506+248,
2507+248,
2508+248,
2509+248,
2510+248,
2511+248,
2512+248,
2513+248,
2514+248,
2515+248,
2516+248,
2517+248,
2518+248,
2519+248,
2520+248,
2521+248,
2522+248,
2523+248,
2524+248,
2525+248,
2526+248,
2527+248,
2528+248,
2529+248,
2530+248,
2531+248,
2532+248,
2533+249,
2534+249,
2535+249,
2536+249,
2537+250,
2538+250,
2539+250,
2540+250,
2541+250,
2542+250,
2543+250,
2544+250,
2545+250,
2546+250,
2547+250,
2548+250,
2549+250,
2550+250,
2551+250,
2552+250,
2553+250,
2554+250,
2555+250,
2556+250,
2557+250,
2558+250,
2559+250,
2560+250,
2561+250,
2562+250,
2563+250,
2564+250,
2565+250,
2566+250,
2567+250,
2568+250,
2569+250,
2570+250,
2571+250,
2572+250,
2573+250,
2574+250,
2575+250,
2576+250,
2577+250,
2578+250,
2579+251,
2580+251,
2581+251,
2582+251,
2583+252,
2584+252,
2585+252,
2586+252,
2587+252,
2588+252,
2589+252,
2590+252,
2591+252,
2592+252,
2593+252,
2594+252,
2595+252,
2596+252,
2597+252,
2598+252,
2599+252,
2600+252,
2601+252,
2602+252,
2603+252,
2604+252,
2605+252,
2606+252,
2607+252,
2608+252,
2609+252,
2610+252,
2611+252,
2612+252,
2613+252,
2614+252,
2615+252,
2616+252,
2617+252,
2618+252,
2619+252,
2620+252,
2621+252,
2622+252,
2623+252,
2624+252,
2625+252,
2626+252,
2627+252,
2628+252,
2629+252,
2630+252,
2631+252,
2632+252,
2633+252,
2634+252,
2635+252,
2636+252,
2637+252,
2638+252,
2639+252,
2640+252,
2641+252,
2642+252,
2643+252,
2644+252,
2645+252,
2646+252,
2647+253,
2648+253,
2649+253,
2650+253,
2651+253,
2652+253,
2653+253,
2654+253,
2655+253,
2656+253,
2657+253,
2658+253,
2659+253,
2660+253,
2661+253,
2662+253,
2663+253,
2664+253,
2665+253,
2666+253,
2667+253,
2668+253,
2669+253,
2670+253,
2671+253,
2672+253,
2673+253,
2674+253,
2675+253,
2676+253,
2677+253,
2678+253,
2679+253,
2680+253,
2681+253,
2682+253,
2683+253,
2684+253,
2685+253,
2686+253,
2687+253,
2688+253,
2689+253,
2690+253,
2691+253,
2692+253,
2693+253,
2694+253,
2695+253,
2696+253,
2697+253,
2698+253,
2699+253,
2700+253,
2701+253,
2702+253,
2703+253,
2704+254,
2705+254,
2706+254,
2707+254,
2708+255,
2709+255,
2710+255,
2711+255,
2712+255,
2713+255,
2714+255,
2715+255,
2716+255,
2717+255,
2718+255,
2719+255,
2720+255,
2721+255,
2722+255,
2723+255,
2724+255,
2725+255,
2726+255,
2727+255,
2728+255,
2729+255,
2730+255,
2731+255,
2732+255,
2733+255,
2734+255
2735diff --git a/drivers/media/video/isp/luma_enhance_table.h b/drivers/media/video/isp/luma_enhance_table.h
2736new file mode 100644
2737index 0000000..99c8b05
2738--- /dev/null
2739+++ b/drivers/media/video/isp/luma_enhance_table.h
2740@@ -0,0 +1,144 @@
2741+/*
2742+ * luma_enhance_table.h
2743+ *
2744+ * Luminance Enhancement table values for TI's OMAP3 Camera ISP
2745+ *
2746+ * Copyright (C) 2009 Texas Instruments, Inc.
2747+ *
2748+ * This package is free software; you can redistribute it and/or modify
2749+ * it under the terms of the GNU General Public License version 2 as
2750+ * published by the Free Software Foundation.
2751+ *
2752+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2753+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2754+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2755+ */
2756+
2757+1047552,
2758+1047552,
2759+1047552,
2760+1047552,
2761+1047552,
2762+1047552,
2763+1047552,
2764+1047552,
2765+1047552,
2766+1047552,
2767+1047552,
2768+1047552,
2769+1047552,
2770+1047552,
2771+1047552,
2772+1047552,
2773+1047552,
2774+1047552,
2775+1047552,
2776+1047552,
2777+1047552,
2778+1047552,
2779+1047552,
2780+1047552,
2781+1047552,
2782+1047552,
2783+1047552,
2784+1047552,
2785+1048575,
2786+1047551,
2787+1046527,
2788+1045503,
2789+1044479,
2790+1043455,
2791+1042431,
2792+1041407,
2793+1040383,
2794+1039359,
2795+1038335,
2796+1037311,
2797+1036287,
2798+1035263,
2799+1034239,
2800+1033215,
2801+1032191,
2802+1031167,
2803+1030143,
2804+1028096,
2805+1028096,
2806+1028096,
2807+1028096,
2808+1028096,
2809+1028096,
2810+1028096,
2811+1028096,
2812+1028096,
2813+1028096,
2814+1028100,
2815+1032196,
2816+1036292,
2817+1040388,
2818+1044484,
2819+0,
2820+0,
2821+0,
2822+5,
2823+5125,
2824+10245,
2825+15365,
2826+20485,
2827+25605,
2828+30720,
2829+30720,
2830+30720,
2831+30720,
2832+30720,
2833+30720,
2834+30720,
2835+30720,
2836+30720,
2837+30720,
2838+30720,
2839+31743,
2840+30719,
2841+29695,
2842+28671,
2843+27647,
2844+26623,
2845+25599,
2846+24575,
2847+23551,
2848+22527,
2849+21503,
2850+20479,
2851+19455,
2852+18431,
2853+17407,
2854+16383,
2855+15359,
2856+14335,
2857+13311,
2858+12287,
2859+11263,
2860+10239,
2861+9215,
2862+8191,
2863+7167,
2864+6143,
2865+5119,
2866+4095,
2867+3071,
2868+1024,
2869+1024,
2870+1024,
2871+1024,
2872+1024,
2873+1024,
2874+1024,
2875+1024,
2876+1024,
2877+1024,
2878+1024,
2879+1024,
2880+1024,
2881+1024,
2882+1024,
2883+1024,
2884+1024
2885diff --git a/drivers/media/video/isp/noise_filter_table.h b/drivers/media/video/isp/noise_filter_table.h
2886new file mode 100644
2887index 0000000..7345f90
2888--- /dev/null
2889+++ b/drivers/media/video/isp/noise_filter_table.h
2890@@ -0,0 +1,79 @@
2891+/*
2892+ * noise_filter_table.h
2893+ *
2894+ * Noise Filter Table values for TI's OMAP3 Camera ISP
2895+ *
2896+ * Copyright (C) 2009 Texas Instruments, Inc.
2897+ *
2898+ * This package is free software; you can redistribute it and/or modify
2899+ * it under the terms of the GNU General Public License version 2 as
2900+ * published by the Free Software Foundation.
2901+ *
2902+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2903+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2904+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2905+ */
2906+16,
2907+16,
2908+16,
2909+16,
2910+16,
2911+16,
2912+16,
2913+16,
2914+16,
2915+16,
2916+16,
2917+16,
2918+16,
2919+16,
2920+16,
2921+16,
2922+16,
2923+16,
2924+16,
2925+16,
2926+16,
2927+16,
2928+16,
2929+16,
2930+16,
2931+16,
2932+16,
2933+16,
2934+16,
2935+16,
2936+16,
2937+16,
2938+31,
2939+31,
2940+31,
2941+31,
2942+31,
2943+31,
2944+31,
2945+31,
2946+31,
2947+31,
2948+31,
2949+31,
2950+31,
2951+31,
2952+31,
2953+31,
2954+31,
2955+31,
2956+31,
2957+31,
2958+31,
2959+31,
2960+31,
2961+31,
2962+31,
2963+31,
2964+31,
2965+31,
2966+31,
2967+31,
2968+31,
2969+31
2970diff --git a/drivers/media/video/isp/redgamma_table.h b/drivers/media/video/isp/redgamma_table.h
2971new file mode 100644
2972index 0000000..ad0232a
2973--- /dev/null
2974+++ b/drivers/media/video/isp/redgamma_table.h
2975@@ -0,0 +1,1040 @@
2976+/*
2977+ * redgamma_table.h
2978+ *
2979+ * Gamma Table values for RED for TI's OMAP3 Camera ISP
2980+ *
2981+ * Copyright (C) 2009 Texas Instruments, Inc.
2982+ *
2983+ * This package is free software; you can redistribute it and/or modify
2984+ * it under the terms of the GNU General Public License version 2 as
2985+ * published by the Free Software Foundation.
2986+ *
2987+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2988+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2989+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2990+ */
2991+
2992+0,
2993+0,
2994+1,
2995+2,
2996+3,
2997+3,
2998+4,
2999+5,
3000+6,
3001+8,
3002+10,
3003+12,
3004+14,
3005+16,
3006+18,
3007+20,
3008+22,
3009+23,
3010+25,
3011+26,
3012+28,
3013+29,
3014+31,
3015+32,
3016+34,
3017+35,
3018+36,
3019+37,
3020+39,
3021+40,
3022+41,
3023+42,
3024+43,
3025+44,
3026+45,
3027+46,
3028+47,
3029+48,
3030+49,
3031+50,
3032+51,
3033+52,
3034+52,
3035+53,
3036+54,
3037+55,
3038+56,
3039+57,
3040+58,
3041+59,
3042+60,
3043+61,
3044+62,
3045+63,
3046+63,
3047+64,
3048+65,
3049+66,
3050+66,
3051+67,
3052+68,
3053+69,
3054+69,
3055+70,
3056+71,
3057+72,
3058+72,
3059+73,
3060+74,
3061+75,
3062+75,
3063+76,
3064+77,
3065+78,
3066+78,
3067+79,
3068+80,
3069+81,
3070+81,
3071+82,
3072+83,
3073+84,
3074+84,
3075+85,
3076+86,
3077+87,
3078+88,
3079+88,
3080+89,
3081+90,
3082+91,
3083+91,
3084+92,
3085+93,
3086+94,
3087+94,
3088+95,
3089+96,
3090+97,
3091+97,
3092+98,
3093+98,
3094+99,
3095+99,
3096+100,
3097+100,
3098+101,
3099+101,
3100+102,
3101+103,
3102+104,
3103+104,
3104+105,
3105+106,
3106+107,
3107+108,
3108+108,
3109+109,
3110+110,
3111+111,
3112+111,
3113+112,
3114+113,
3115+114,
3116+114,
3117+115,
3118+116,
3119+117,
3120+117,
3121+118,
3122+119,
3123+119,
3124+120,
3125+120,
3126+121,
3127+121,
3128+122,
3129+122,
3130+123,
3131+123,
3132+124,
3133+124,
3134+125,
3135+125,
3136+126,
3137+126,
3138+127,
3139+127,
3140+128,
3141+128,
3142+129,
3143+129,
3144+130,
3145+130,
3146+131,
3147+131,
3148+132,
3149+132,
3150+133,
3151+133,
3152+134,
3153+134,
3154+135,
3155+135,
3156+136,
3157+136,
3158+137,
3159+137,
3160+138,
3161+138,
3162+139,
3163+139,
3164+140,
3165+140,
3166+141,
3167+141,
3168+142,
3169+142,
3170+143,
3171+143,
3172+144,
3173+144,
3174+145,
3175+145,
3176+146,
3177+146,
3178+147,
3179+147,
3180+148,
3181+148,
3182+149,
3183+149,
3184+150,
3185+150,
3186+151,
3187+151,
3188+152,
3189+152,
3190+153,
3191+153,
3192+153,
3193+153,
3194+154,
3195+154,
3196+154,
3197+154,
3198+155,
3199+155,
3200+156,
3201+156,
3202+157,
3203+157,
3204+158,
3205+158,
3206+158,
3207+159,
3208+159,
3209+159,
3210+160,
3211+160,
3212+160,
3213+161,
3214+161,
3215+162,
3216+162,
3217+163,
3218+163,
3219+164,
3220+164,
3221+164,
3222+164,
3223+165,
3224+165,
3225+165,
3226+165,
3227+166,
3228+166,
3229+167,
3230+167,
3231+168,
3232+168,
3233+169,
3234+169,
3235+170,
3236+170,
3237+170,
3238+170,
3239+171,
3240+171,
3241+171,
3242+171,
3243+172,
3244+172,
3245+173,
3246+173,
3247+174,
3248+174,
3249+175,
3250+175,
3251+176,
3252+176,
3253+176,
3254+176,
3255+177,
3256+177,
3257+177,
3258+177,
3259+178,
3260+178,
3261+178,
3262+178,
3263+179,
3264+179,
3265+179,
3266+179,
3267+180,
3268+180,
3269+180,
3270+180,
3271+181,
3272+181,
3273+181,
3274+181,
3275+182,
3276+182,
3277+182,
3278+182,
3279+183,
3280+183,
3281+183,
3282+183,
3283+184,
3284+184,
3285+184,
3286+184,
3287+185,
3288+185,
3289+185,
3290+185,
3291+186,
3292+186,
3293+186,
3294+186,
3295+187,
3296+187,
3297+187,
3298+187,
3299+188,
3300+188,
3301+188,
3302+188,
3303+189,
3304+189,
3305+189,
3306+189,
3307+190,
3308+190,
3309+190,
3310+190,
3311+191,
3312+191,
3313+191,
3314+191,
3315+192,
3316+192,
3317+192,
3318+192,
3319+193,
3320+193,
3321+193,
3322+193,
3323+194,
3324+194,
3325+194,
3326+194,
3327+195,
3328+195,
3329+195,
3330+195,
3331+196,
3332+196,
3333+196,
3334+196,
3335+197,
3336+197,
3337+197,
3338+197,
3339+198,
3340+198,
3341+198,
3342+198,
3343+199,
3344+199,
3345+199,
3346+199,
3347+200,
3348+200,
3349+200,
3350+200,
3351+201,
3352+201,
3353+201,
3354+201,
3355+202,
3356+202,
3357+202,
3358+203,
3359+203,
3360+203,
3361+203,
3362+204,
3363+204,
3364+204,
3365+204,
3366+205,
3367+205,
3368+205,
3369+205,
3370+206,
3371+206,
3372+206,
3373+206,
3374+207,
3375+207,
3376+207,
3377+207,
3378+208,
3379+208,
3380+208,
3381+208,
3382+209,
3383+209,
3384+209,
3385+209,
3386+210,
3387+210,
3388+210,
3389+210,
3390+210,
3391+210,
3392+210,
3393+210,
3394+210,
3395+210,
3396+210,
3397+210,
3398+211,
3399+211,
3400+211,
3401+211,
3402+211,
3403+211,
3404+211,
3405+211,
3406+211,
3407+211,
3408+211,
3409+212,
3410+212,
3411+212,
3412+212,
3413+213,
3414+213,
3415+213,
3416+213,
3417+213,
3418+213,
3419+213,
3420+213,
3421+213,
3422+213,
3423+213,
3424+213,
3425+214,
3426+214,
3427+214,
3428+214,
3429+215,
3430+215,
3431+215,
3432+215,
3433+215,
3434+215,
3435+215,
3436+215,
3437+215,
3438+215,
3439+215,
3440+216,
3441+216,
3442+216,
3443+216,
3444+217,
3445+217,
3446+217,
3447+217,
3448+218,
3449+218,
3450+218,
3451+218,
3452+219,
3453+219,
3454+219,
3455+219,
3456+219,
3457+219,
3458+219,
3459+219,
3460+219,
3461+219,
3462+219,
3463+219,
3464+220,
3465+220,
3466+220,
3467+220,
3468+221,
3469+221,
3470+221,
3471+221,
3472+221,
3473+221,
3474+221,
3475+221,
3476+221,
3477+221,
3478+221,
3479+222,
3480+222,
3481+222,
3482+222,
3483+223,
3484+223,
3485+223,
3486+223,
3487+223,
3488+223,
3489+223,
3490+223,
3491+223,
3492+223,
3493+223,
3494+223,
3495+224,
3496+224,
3497+224,
3498+224,
3499+225,
3500+225,
3501+225,
3502+225,
3503+225,
3504+225,
3505+225,
3506+225,
3507+225,
3508+225,
3509+225,
3510+225,
3511+225,
3512+225,
3513+225,
3514+225,
3515+225,
3516+225,
3517+225,
3518+226,
3519+226,
3520+226,
3521+226,
3522+227,
3523+227,
3524+227,
3525+227,
3526+227,
3527+227,
3528+227,
3529+227,
3530+227,
3531+227,
3532+227,
3533+227,
3534+228,
3535+228,
3536+228,
3537+229,
3538+229,
3539+229,
3540+229,
3541+229,
3542+229,
3543+229,
3544+229,
3545+229,
3546+229,
3547+229,
3548+229,
3549+230,
3550+230,
3551+230,
3552+230,
3553+231,
3554+231,
3555+231,
3556+231,
3557+231,
3558+231,
3559+231,
3560+231,
3561+231,
3562+231,
3563+231,
3564+231,
3565+232,
3566+232,
3567+232,
3568+232,
3569+232,
3570+232,
3571+232,
3572+232,
3573+232,
3574+232,
3575+232,
3576+232,
3577+232,
3578+232,
3579+232,
3580+232,
3581+232,
3582+232,
3583+232,
3584+233,
3585+233,
3586+233,
3587+233,
3588+234,
3589+234,
3590+234,
3591+234,
3592+234,
3593+234,
3594+234,
3595+234,
3596+234,
3597+234,
3598+234,
3599+235,
3600+235,
3601+235,
3602+235,
3603+236,
3604+236,
3605+236,
3606+236,
3607+236,
3608+236,
3609+236,
3610+236,
3611+236,
3612+236,
3613+236,
3614+236,
3615+236,
3616+236,
3617+236,
3618+236,
3619+236,
3620+236,
3621+236,
3622+237,
3623+237,
3624+237,
3625+237,
3626+238,
3627+238,
3628+238,
3629+238,
3630+238,
3631+238,
3632+238,
3633+238,
3634+238,
3635+238,
3636+238,
3637+238,
3638+238,
3639+238,
3640+238,
3641+238,
3642+238,
3643+238,
3644+238,
3645+238,
3646+238,
3647+238,
3648+238,
3649+238,
3650+238,
3651+238,
3652+238,
3653+239,
3654+239,
3655+239,
3656+239,
3657+240,
3658+240,
3659+240,
3660+240,
3661+240,
3662+240,
3663+240,
3664+240,
3665+240,
3666+240,
3667+240,
3668+240,
3669+240,
3670+240,
3671+240,
3672+240,
3673+240,
3674+240,
3675+240,
3676+240,
3677+240,
3678+240,
3679+240,
3680+240,
3681+240,
3682+240,
3683+240,
3684+241,
3685+241,
3686+241,
3687+241,
3688+242,
3689+242,
3690+242,
3691+242,
3692+242,
3693+242,
3694+242,
3695+242,
3696+242,
3697+242,
3698+242,
3699+242,
3700+242,
3701+242,
3702+242,
3703+242,
3704+242,
3705+242,
3706+242,
3707+242,
3708+242,
3709+242,
3710+242,
3711+242,
3712+242,
3713+242,
3714+243,
3715+243,
3716+243,
3717+243,
3718+244,
3719+244,
3720+244,
3721+244,
3722+244,
3723+244,
3724+244,
3725+244,
3726+244,
3727+244,
3728+244,
3729+244,
3730+244,
3731+244,
3732+244,
3733+244,
3734+244,
3735+244,
3736+244,
3737+244,
3738+244,
3739+244,
3740+244,
3741+244,
3742+244,
3743+244,
3744+244,
3745+245,
3746+245,
3747+245,
3748+245,
3749+246,
3750+246,
3751+246,
3752+246,
3753+246,
3754+246,
3755+246,
3756+246,
3757+246,
3758+246,
3759+246,
3760+246,
3761+246,
3762+246,
3763+246,
3764+246,
3765+246,
3766+246,
3767+246,
3768+246,
3769+246,
3770+246,
3771+246,
3772+246,
3773+246,
3774+246,
3775+246,
3776+246,
3777+246,
3778+246,
3779+246,
3780+246,
3781+246,
3782+246,
3783+247,
3784+247,
3785+247,
3786+247,
3787+248,
3788+248,
3789+248,
3790+248,
3791+248,
3792+248,
3793+248,
3794+248,
3795+248,
3796+248,
3797+248,
3798+248,
3799+248,
3800+248,
3801+248,
3802+248,
3803+248,
3804+248,
3805+248,
3806+248,
3807+248,
3808+248,
3809+248,
3810+248,
3811+248,
3812+248,
3813+248,
3814+249,
3815+249,
3816+249,
3817+249,
3818+250,
3819+250,
3820+250,
3821+250,
3822+250,
3823+250,
3824+250,
3825+250,
3826+250,
3827+250,
3828+250,
3829+250,
3830+250,
3831+250,
3832+250,
3833+250,
3834+250,
3835+250,
3836+250,
3837+250,
3838+250,
3839+250,
3840+250,
3841+250,
3842+250,
3843+250,
3844+250,
3845+250,
3846+250,
3847+250,
3848+250,
3849+250,
3850+250,
3851+250,
3852+250,
3853+250,
3854+250,
3855+250,
3856+250,
3857+250,
3858+250,
3859+250,
3860+251,
3861+251,
3862+251,
3863+251,
3864+252,
3865+252,
3866+252,
3867+252,
3868+252,
3869+252,
3870+252,
3871+252,
3872+252,
3873+252,
3874+252,
3875+252,
3876+252,
3877+252,
3878+252,
3879+252,
3880+252,
3881+252,
3882+252,
3883+252,
3884+252,
3885+252,
3886+252,
3887+252,
3888+252,
3889+252,
3890+252,
3891+252,
3892+252,
3893+252,
3894+252,
3895+252,
3896+252,
3897+252,
3898+252,
3899+252,
3900+252,
3901+252,
3902+252,
3903+252,
3904+252,
3905+252,
3906+252,
3907+252,
3908+252,
3909+252,
3910+252,
3911+252,
3912+252,
3913+252,
3914+252,
3915+252,
3916+252,
3917+252,
3918+252,
3919+252,
3920+252,
3921+252,
3922+252,
3923+252,
3924+252,
3925+252,
3926+252,
3927+252,
3928+253,
3929+253,
3930+253,
3931+253,
3932+253,
3933+253,
3934+253,
3935+253,
3936+253,
3937+253,
3938+253,
3939+253,
3940+253,
3941+253,
3942+253,
3943+253,
3944+253,
3945+253,
3946+253,
3947+253,
3948+253,
3949+253,
3950+253,
3951+253,
3952+253,
3953+253,
3954+253,
3955+253,
3956+253,
3957+253,
3958+253,
3959+253,
3960+253,
3961+253,
3962+253,
3963+253,
3964+253,
3965+253,
3966+253,
3967+253,
3968+253,
3969+253,
3970+253,
3971+253,
3972+253,
3973+253,
3974+253,
3975+253,
3976+253,
3977+253,
3978+253,
3979+253,
3980+253,
3981+253,
3982+253,
3983+253,
3984+253,
3985+254,
3986+254,
3987+254,
3988+254,
3989+255,
3990+255,
3991+255,
3992+255,
3993+255,
3994+255,
3995+255,
3996+255,
3997+255,
3998+255,
3999+255,
4000+255,
4001+255,
4002+255,
4003+255,
4004+255,
4005+255,
4006+255,
4007+255,
4008+255,
4009+255,
4010+255,
4011+255,
4012+255,
4013+255,
4014+255,
4015+255
4016--
40171.5.6.5
4018
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
new file mode 100644
index 0000000000..22074be148
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0009-omap34xxcam-Add-camera-driver.patch
@@ -0,0 +1,2249 @@
1From 0edf5a50dc0164db5bc71b1a5d1aa8bb1838262c Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
3Date: Tue, 10 Mar 2009 10:49:03 +0200
4Subject: [PATCH] omap34xxcam: Add camera driver
5
6This is the camera driver for the OMAP 3 camera ISP and v4l2-int-device
7sensors, lenses and (led) flashes. There are a few connections to OMAP
83 left but after those have been broken this is hardware independent.
9Namely, the OMAP 3 ISP must offer a standard interface through
10v4l2_subdev (or v4l2-int-device) first.
11
12This driver has originated from the omap24xxcam camera driver written
13specifically for OMAP 2.
14
15TODO:
16
17- Convert to use v4l2_subdev instead of v4l2-int-device.
18
19Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
20---
21 drivers/media/video/Kconfig | 9 +
22 drivers/media/video/Makefile | 2 +
23 drivers/media/video/omap34xxcam.c | 1966 +++++++++++++++++++++++++++++++++++++
24 drivers/media/video/omap34xxcam.h | 207 ++++
25 4 files changed, 2184 insertions(+), 0 deletions(-)
26 create mode 100644 drivers/media/video/omap34xxcam.c
27 create mode 100644 drivers/media/video/omap34xxcam.h
28
29diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
30index 19cf3b8..3cdb5a4 100644
31--- a/drivers/media/video/Kconfig
32+++ b/drivers/media/video/Kconfig
33@@ -711,6 +711,15 @@ config VIDEO_CAFE_CCIC
34 CMOS camera controller. This is the controller found on first-
35 generation OLPC systems.
36
37+config VIDEO_OMAP3
38+ tristate "OMAP 3 Camera support"
39+ select VIDEOBUF_GEN
40+ select VIDEOBUF_DMA_SG
41+ select OMAP_IOMMU
42+ depends on VIDEO_V4L2 && ARCH_OMAP34XX
43+ ---help---
44+ Driver for an OMAP 3 camera controller.
45+
46 config SOC_CAMERA
47 tristate "SoC camera support"
48 depends on VIDEO_V4L2 && HAS_DMA
49diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
50index e654270..74a684e 100644
51--- a/drivers/media/video/Makefile
52+++ b/drivers/media/video/Makefile
53@@ -108,6 +108,8 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
54
55 obj-y += isp/
56
57+obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o
58+
59 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
60
61 obj-$(CONFIG_USB_DABUSB) += dabusb.o
62diff --git a/drivers/media/video/omap34xxcam.c b/drivers/media/video/omap34xxcam.c
63new file mode 100644
64index 0000000..00fdbf2
65--- /dev/null
66+++ b/drivers/media/video/omap34xxcam.c
67@@ -0,0 +1,1966 @@
68+/*
69+ * omap34xxcam.c
70+ *
71+ * Copyright (C) 2006--2009 Nokia Corporation
72+ * Copyright (C) 2007--2009 Texas Instruments
73+ *
74+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
75+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
76+ *
77+ * Originally based on the OMAP 2 camera driver.
78+ *
79+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
80+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
81+ * Sergio Aguirre <saaguirre@ti.com>
82+ * Mohit Jalori
83+ * Sameer Venkatraman
84+ * Leonides Martinez
85+ *
86+ * This program is free software; you can redistribute it and/or
87+ * modify it under the terms of the GNU General Public License
88+ * version 2 as published by the Free Software Foundation.
89+ *
90+ * This program is distributed in the hope that it will be useful, but
91+ * WITHOUT ANY WARRANTY; without even the implied warranty of
92+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
93+ * General Public License for more details.
94+ *
95+ * You should have received a copy of the GNU General Public License
96+ * along with this program; if not, write to the Free Software
97+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
98+ * 02110-1301 USA
99+ *
100+ */
101+
102+#include <linux/io.h>
103+#include <linux/clk.h>
104+#include <linux/pci.h> /* needed for videobufs */
105+#include <linux/delay.h>
106+#include <linux/kernel.h>
107+#include <linux/interrupt.h>
108+#include <linux/videodev2.h>
109+#include <linux/version.h>
110+#include <linux/platform_device.h>
111+
112+#include <media/v4l2-common.h>
113+#include <media/v4l2-ioctl.h>
114+
115+#include "omap34xxcam.h"
116+#include "isp/isp.h"
117+#include "isp/ispmmu.h"
118+#include "isp/ispreg.h"
119+#include "isp/ispccdc.h"
120+#include "isp/isph3a.h"
121+#include "isp/isp_af.h"
122+#include "isp/isphist.h"
123+#include "isp/isppreview.h"
124+#include "isp/ispresizer.h"
125+
126+#define OMAP34XXCAM_VERSION KERNEL_VERSION(0, 0, 0)
127+
128+/* global variables */
129+static struct omap34xxcam_device *omap34xxcam;
130+
131+/*
132+ *
133+ * Sensor handling.
134+ *
135+ */
136+
137+/**
138+ * omap34xxcam_slave_power_set - set slave power state
139+ * @vdev: per-video device data structure
140+ * @power: new power state
141+ */
142+static int omap34xxcam_slave_power_set(struct omap34xxcam_videodev *vdev,
143+ enum v4l2_power power,
144+ int mask)
145+{
146+ int rval = 0, i = 0;
147+
148+ BUG_ON(!mutex_is_locked(&vdev->mutex));
149+
150+#ifdef OMAP34XXCAM_POWEROFF_DELAY
151+ vdev->power_state_wish = -1;
152+#endif
153+
154+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
155+ if (vdev->slave[i] == v4l2_int_device_dummy())
156+ continue;
157+
158+ if (!(mask & (1 << i))
159+ || power == vdev->power_state[i])
160+ continue;
161+
162+ rval = vidioc_int_s_power(vdev->slave[i], power);
163+
164+ if (rval && power != V4L2_POWER_OFF) {
165+ power = V4L2_POWER_OFF;
166+ goto out;
167+ }
168+
169+ vdev->power_state[i] = power;
170+ }
171+
172+ return 0;
173+
174+out:
175+ for (i--; i >= 0; i--) {
176+ if (vdev->slave[i] == v4l2_int_device_dummy())
177+ continue;
178+
179+ if (!(mask & (1 << i)))
180+ continue;
181+
182+ vidioc_int_s_power(vdev->slave[i], power);
183+ vdev->power_state[i] = power;
184+ }
185+
186+ return rval;
187+}
188+
189+#ifdef OMAP34XXCAM_POWEROFF_DELAY
190+static void omap34xxcam_slave_power_work(struct work_struct *work)
191+{
192+ struct omap34xxcam_videodev *vdev =
193+ container_of(work, struct omap34xxcam_videodev, poweroff_work);
194+
195+ mutex_lock(&vdev->mutex);
196+
197+ if (vdev->power_state_wish != -1)
198+ omap34xxcam_slave_power_set(vdev, vdev->power_state_wish,
199+ vdev->power_state_mask);
200+
201+ mutex_unlock(&vdev->mutex);
202+}
203+
204+static void omap34xxcam_slave_power_timer(unsigned long ptr)
205+{
206+ struct omap34xxcam_videodev *vdev = (void *)ptr;
207+
208+ schedule_work(&vdev->poweroff_work);
209+}
210+
211+/**
212+ * omap34xxcam_slave_power_suggest - delayed power state change
213+ *
214+ * @vdev: per-video device data structure
215+ * @power: new power state
216+ */
217+static void omap34xxcam_slave_power_suggest(struct omap34xxcam_videodev *vdev,
218+ enum v4l2_power power,
219+ int mask)
220+{
221+ BUG_ON(!mutex_is_locked(&vdev->mutex));
222+
223+ del_timer(&vdev->poweroff_timer);
224+
225+ vdev->power_state_wish = power;
226+ vdev->power_state_mask = mask;
227+
228+ mod_timer(&vdev->poweroff_timer, jiffies + OMAP34XXCAM_POWEROFF_DELAY);
229+}
230+#else /* OMAP34XXCAM_POWEROFF_DELAY */
231+#define omap34xxcam_slave_power_suggest(a, b, c) do {} while (0)
232+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
233+
234+/**
235+ * omap34xxcam_update_vbq - Updates VBQ with completed input buffer
236+ * @vb: ptr. to standard V4L2 video buffer structure
237+ *
238+ * Updates video buffer queue with completed buffer passed as
239+ * input parameter. Also updates ISP H3A timestamp and field count
240+ * statistics.
241+ */
242+void omap34xxcam_vbq_complete(struct videobuf_buffer *vb, void *priv)
243+{
244+ struct omap34xxcam_fh *fh = priv;
245+
246+ do_gettimeofday(&vb->ts);
247+ vb->field_count = atomic_add_return(2, &fh->field_count);
248+
249+ wake_up(&vb->done);
250+}
251+
252+/**
253+ * omap34xxcam_vbq_setup - Calcs size and num of buffs allowed in queue
254+ * @vbq: ptr. to standard V4L2 video buffer queue structure
255+ * @cnt: ptr to location to hold the count of buffers to be in the queue
256+ * @size: ptr to location to hold the size of a frame
257+ *
258+ * Calculates the number of buffers of current image size that can be
259+ * supported by the available capture memory.
260+ */
261+static int omap34xxcam_vbq_setup(struct videobuf_queue *vbq, unsigned int *cnt,
262+ unsigned int *size)
263+{
264+ struct omap34xxcam_fh *fh = vbq->priv_data;
265+ struct omap34xxcam_videodev *vdev = fh->vdev;
266+
267+ if (*cnt <= 0)
268+ *cnt = VIDEO_MAX_FRAME; /* supply a default number of buffers */
269+
270+ if (*cnt > VIDEO_MAX_FRAME)
271+ *cnt = VIDEO_MAX_FRAME;
272+
273+ *size = vdev->pix.sizeimage;
274+
275+ while (*size * *cnt > fh->vdev->vdev_sensor_config.capture_mem)
276+ (*cnt)--;
277+
278+ return isp_vbq_setup(vbq, cnt, size);
279+}
280+
281+/**
282+ * omap34xxcam_vbq_release - Free resources for input VBQ and VB
283+ * @vbq: ptr. to standard V4L2 video buffer queue structure
284+ * @vb: ptr to standard V4L2 video buffer structure
285+ *
286+ * Unmap and free all memory associated with input VBQ and VB, also
287+ * unmap the address in ISP MMU. Reset the VB state.
288+ */
289+static void omap34xxcam_vbq_release(struct videobuf_queue *vbq,
290+ struct videobuf_buffer *vb)
291+{
292+ if (!vbq->streaming) {
293+ isp_vbq_release(vbq, vb);
294+ videobuf_dma_unmap(vbq, videobuf_to_dma(vb));
295+ videobuf_dma_free(videobuf_to_dma(vb));
296+ vb->state = VIDEOBUF_NEEDS_INIT;
297+ }
298+ return;
299+}
300+
301+/**
302+ * omap34xxcam_vbq_prepare - V4L2 video ops buf_prepare handler
303+ * @vbq: ptr. to standard V4L2 video buffer queue structure
304+ * @vb: ptr to standard V4L2 video buffer structure
305+ * @field: standard V4L2 field enum
306+ *
307+ * Verifies there is sufficient locked memory for the requested
308+ * buffer, or if there is not, allocates, locks and initializes
309+ * it.
310+ */
311+static int omap34xxcam_vbq_prepare(struct videobuf_queue *vbq,
312+ struct videobuf_buffer *vb,
313+ enum v4l2_field field)
314+{
315+ struct omap34xxcam_fh *fh = vbq->priv_data;
316+ struct omap34xxcam_videodev *vdev = fh->vdev;
317+ int err = 0;
318+
319+ /*
320+ * Accessing pix here is okay since it's constant while
321+ * streaming is on (and we only get called then).
322+ */
323+ if (vb->baddr) {
324+ /* This is a userspace buffer. */
325+ if (vdev->pix.sizeimage > vb->bsize)
326+ /* The buffer isn't big enough. */
327+ return -EINVAL;
328+ } else {
329+ if (vb->state != VIDEOBUF_NEEDS_INIT
330+ && vdev->pix.sizeimage > vb->bsize)
331+ /*
332+ * We have a kernel bounce buffer that has
333+ * already been allocated.
334+ */
335+ omap34xxcam_vbq_release(vbq, vb);
336+ }
337+
338+ vb->size = vdev->pix.bytesperline * vdev->pix.height;
339+ vb->width = vdev->pix.width;
340+ vb->height = vdev->pix.height;
341+ vb->field = field;
342+
343+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
344+ err = videobuf_iolock(vbq, vb, NULL);
345+ if (!err) {
346+ /* isp_addr will be stored locally inside isp code */
347+ err = isp_vbq_prepare(vbq, vb, field);
348+ }
349+ }
350+
351+ if (!err)
352+ vb->state = VIDEOBUF_PREPARED;
353+ else
354+ omap34xxcam_vbq_release(vbq, vb);
355+
356+ return err;
357+}
358+
359+/**
360+ * omap34xxcam_vbq_queue - V4L2 video ops buf_queue handler
361+ * @vbq: ptr. to standard V4L2 video buffer queue structure
362+ * @vb: ptr to standard V4L2 video buffer structure
363+ *
364+ * Maps the video buffer to sgdma and through the isp, sets
365+ * the isp buffer done callback and sets the video buffer state
366+ * to active.
367+ */
368+static void omap34xxcam_vbq_queue(struct videobuf_queue *vbq,
369+ struct videobuf_buffer *vb)
370+{
371+ struct omap34xxcam_fh *fh = vbq->priv_data;
372+
373+ vb->state = VIDEOBUF_ACTIVE;
374+
375+ isp_buf_queue(vb, omap34xxcam_vbq_complete, (void *)fh);
376+}
377+
378+static struct videobuf_queue_ops omap34xxcam_vbq_ops = {
379+ .buf_setup = omap34xxcam_vbq_setup,
380+ .buf_prepare = omap34xxcam_vbq_prepare,
381+ .buf_queue = omap34xxcam_vbq_queue,
382+ .buf_release = omap34xxcam_vbq_release,
383+};
384+
385+/*
386+ *
387+ * IOCTL interface.
388+ *
389+ */
390+
391+/**
392+ * vidioc_querycap - V4L2 query capabilities IOCTL handler
393+ * @file: ptr. to system file structure
394+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
395+ * @cap: ptr to standard V4L2 capability structure
396+ *
397+ * Fill in the V4L2 capabliity structure for the camera device
398+ */
399+static int vidioc_querycap(struct file *file, void *fh,
400+ struct v4l2_capability *cap)
401+{
402+ struct omap34xxcam_fh *ofh = fh;
403+ struct omap34xxcam_videodev *vdev = ofh->vdev;
404+
405+ strlcpy(cap->driver, CAM_SHORT_NAME, sizeof(cap->driver));
406+ strlcpy(cap->card, vdev->vfd->name, sizeof(cap->card));
407+ cap->version = OMAP34XXCAM_VERSION;
408+ if (vdev->vdev_sensor != v4l2_int_device_dummy())
409+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
410+
411+ return 0;
412+}
413+
414+/**
415+ * vidioc_enum_fmt_vid_cap - V4L2 enumerate format capabilities IOCTL handler
416+ * @file: ptr. to system file structure
417+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
418+ * @f: ptr to standard V4L2 format description structure
419+ *
420+ * Fills in enumerate format capabilities information for sensor (if SOC
421+ * sensor attached) or ISP (if raw sensor attached).
422+ */
423+static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
424+ struct v4l2_fmtdesc *f)
425+{
426+ struct omap34xxcam_fh *ofh = fh;
427+ struct omap34xxcam_videodev *vdev = ofh->vdev;
428+ int rval;
429+
430+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
431+ return -EINVAL;
432+
433+ if (vdev->vdev_sensor_config.sensor_isp)
434+ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, f);
435+ else
436+ rval = isp_enum_fmt_cap(f);
437+
438+ return rval;
439+}
440+
441+/**
442+ * vidioc_g_fmt_vid_cap - V4L2 get format capabilities IOCTL handler
443+ * @file: ptr. to system file structure
444+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
445+ * @f: ptr to standard V4L2 format structure
446+ *
447+ * Fills in format capabilities for sensor (if SOC sensor attached) or ISP
448+ * (if raw sensor attached).
449+ */
450+static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
451+ struct v4l2_format *f)
452+{
453+ struct omap34xxcam_fh *ofh = fh;
454+ struct omap34xxcam_videodev *vdev = ofh->vdev;
455+
456+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
457+ return -EINVAL;
458+
459+ mutex_lock(&vdev->mutex);
460+ f->fmt.pix = vdev->pix;
461+ mutex_unlock(&vdev->mutex);
462+
463+ return 0;
464+}
465+
466+static int try_pix_parm(struct omap34xxcam_videodev *vdev,
467+ struct v4l2_pix_format *best_pix_in,
468+ struct v4l2_pix_format *wanted_pix_out,
469+ struct v4l2_fract *best_ival)
470+{
471+ int fps;
472+ int fmtd_index;
473+ int rval;
474+ struct v4l2_pix_format best_pix_out;
475+
476+ if (best_ival->numerator == 0
477+ || best_ival->denominator == 0)
478+ *best_ival = vdev->vdev_sensor_config.ival_default;
479+
480+ fps = best_ival->denominator / best_ival->numerator;
481+
482+ best_ival->denominator = 0;
483+ best_pix_out.height = INT_MAX >> 1;
484+ best_pix_out.width = best_pix_out.height;
485+
486+ for (fmtd_index = 0; ; fmtd_index++) {
487+ int size_index;
488+ struct v4l2_fmtdesc fmtd;
489+
490+ fmtd.index = fmtd_index;
491+ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
492+ rval = vidioc_int_enum_fmt_cap(vdev->vdev_sensor, &fmtd);
493+ if (rval)
494+ break;
495+ dev_info(&vdev->vfd->dev, "trying fmt %8.8x (%d)\n",
496+ fmtd.pixelformat, fmtd_index);
497+ /*
498+ * Get supported resolutions.
499+ */
500+ for (size_index = 0; ; size_index++) {
501+ struct v4l2_frmsizeenum frms;
502+ struct v4l2_pix_format pix_tmp_in, pix_tmp_out;
503+ int ival_index;
504+
505+ frms.index = size_index;
506+ frms.pixel_format = fmtd.pixelformat;
507+
508+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor,
509+ &frms);
510+ if (rval)
511+ break;
512+
513+ pix_tmp_in.pixelformat = frms.pixel_format;
514+ pix_tmp_in.width = frms.discrete.width;
515+ pix_tmp_in.height = frms.discrete.height;
516+ pix_tmp_out = *wanted_pix_out;
517+ /* Don't do upscaling. */
518+ if (pix_tmp_out.width > pix_tmp_in.width)
519+ pix_tmp_out.width = pix_tmp_in.width;
520+ if (pix_tmp_out.height > pix_tmp_in.height)
521+ pix_tmp_out.height = pix_tmp_in.height;
522+ rval = isp_try_fmt_cap(&pix_tmp_in, &pix_tmp_out);
523+ if (rval)
524+ return rval;
525+
526+ dev_info(&vdev->vfd->dev, "this w %d\th %d\tfmt %8.8x\t"
527+ "-> w %d\th %d\t fmt %8.8x"
528+ "\twanted w %d\th %d\t fmt %8.8x\n",
529+ pix_tmp_in.width, pix_tmp_in.height,
530+ pix_tmp_in.pixelformat,
531+ pix_tmp_out.width, pix_tmp_out.height,
532+ pix_tmp_out.pixelformat,
533+ wanted_pix_out->width, wanted_pix_out->height,
534+ wanted_pix_out->pixelformat);
535+
536+#define IS_SMALLER_OR_EQUAL(pix1, pix2) \
537+ ((pix1)->width + (pix1)->height \
538+ < (pix2)->width + (pix2)->height)
539+#define SIZE_DIFF(pix1, pix2) \
540+ (abs((pix1)->width - (pix2)->width) \
541+ + abs((pix1)->height - (pix2)->height))
542+
543+ /*
544+ * Don't use modes that are farther from wanted size
545+ * that what we already got.
546+ */
547+ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
548+ > SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
549+ dev_info(&vdev->vfd->dev, "size diff bigger: "
550+ "w %d\th %d\tw %d\th %d\n",
551+ pix_tmp_out.width, pix_tmp_out.height,
552+ best_pix_out.width,
553+ best_pix_out.height);
554+ continue;
555+ }
556+
557+ /*
558+ * There's an input mode that can provide output
559+ * closer to wanted.
560+ */
561+ if (SIZE_DIFF(&pix_tmp_out, wanted_pix_out)
562+ < SIZE_DIFF(&best_pix_out, wanted_pix_out)) {
563+ /* Force renegotation of fps etc. */
564+ best_ival->denominator = 0;
565+ dev_info(&vdev->vfd->dev, "renegotiate: "
566+ "w %d\th %d\tw %d\th %d\n",
567+ pix_tmp_out.width, pix_tmp_out.height,
568+ best_pix_out.width,
569+ best_pix_out.height);
570+ }
571+
572+ for (ival_index = 0; ; ival_index++) {
573+ struct v4l2_frmivalenum frmi;
574+
575+ frmi.index = ival_index;
576+ frmi.pixel_format = frms.pixel_format;
577+ frmi.width = frms.discrete.width;
578+ frmi.height = frms.discrete.height;
579+ /* FIXME: try to fix standard... */
580+ frmi.reserved[0] = 0xdeafbeef;
581+
582+ rval = vidioc_int_enum_frameintervals(
583+ vdev->vdev_sensor, &frmi);
584+ if (rval)
585+ break;
586+
587+ dev_info(&vdev->vfd->dev, "fps %d\n",
588+ frmi.discrete.denominator
589+ / frmi.discrete.numerator);
590+
591+ if (best_ival->denominator == 0)
592+ goto do_it_now;
593+
594+ /*
595+ * We aim to use maximum resolution
596+ * from the sensor, provided that the
597+ * fps is at least as close as on the
598+ * current mode.
599+ */
600+#define FPS_ABS_DIFF(fps, ival) abs(fps - (ival).denominator / (ival).numerator)
601+
602+ /* Select mode with closest fps. */
603+ if (FPS_ABS_DIFF(fps, frmi.discrete)
604+ < FPS_ABS_DIFF(fps, *best_ival)) {
605+ dev_info(&vdev->vfd->dev, "closer fps: "
606+ "fps %d\t fps %d\n",
607+ FPS_ABS_DIFF(fps,
608+ frmi.discrete),
609+ FPS_ABS_DIFF(fps, *best_ival));
610+ goto do_it_now;
611+ }
612+
613+ /*
614+ * Select bigger resolution if it's available
615+ * at same fps.
616+ */
617+ if (frmi.width + frmi.height
618+ > best_pix_in->width + best_pix_in->height
619+ && FPS_ABS_DIFF(fps, frmi.discrete)
620+ <= FPS_ABS_DIFF(fps, *best_ival)) {
621+ dev_info(&vdev->vfd->dev, "bigger res, "
622+ "same fps: "
623+ "w %d\th %d\tw %d\th %d\n",
624+ frmi.width, frmi.height,
625+ best_pix_in->width,
626+ best_pix_in->height);
627+ goto do_it_now;
628+ }
629+
630+ dev_info(&vdev->vfd->dev, "falling through\n");
631+
632+ continue;
633+
634+do_it_now:
635+ *best_ival = frmi.discrete;
636+ best_pix_out = pix_tmp_out;
637+ best_pix_in->width = frmi.width;
638+ best_pix_in->height = frmi.height;
639+ best_pix_in->pixelformat = frmi.pixel_format;
640+
641+ dev_info(&vdev->vfd->dev,
642+ "best_pix_in: w %d\th %d\tfmt %8.8x"
643+ "\tival %d/%d\n",
644+ best_pix_in->width,
645+ best_pix_in->height,
646+ best_pix_in->pixelformat,
647+ best_ival->numerator,
648+ best_ival->denominator);
649+ }
650+ }
651+ }
652+
653+ if (best_ival->denominator == 0)
654+ return -EINVAL;
655+
656+ *wanted_pix_out = best_pix_out;
657+
658+ dev_info(&vdev->vfd->dev, "w %d, h %d, fmt %8.8x -> w %d, h %d\n",
659+ best_pix_in->width, best_pix_in->height,
660+ best_pix_in->pixelformat,
661+ best_pix_out.width, best_pix_out.height);
662+
663+ return isp_try_fmt_cap(best_pix_in, wanted_pix_out);
664+}
665+
666+static int s_pix_parm(struct omap34xxcam_videodev *vdev,
667+ struct v4l2_pix_format *best_pix,
668+ struct v4l2_pix_format *pix,
669+ struct v4l2_fract *best_ival)
670+{
671+ struct v4l2_streamparm a;
672+ struct v4l2_format fmt;
673+ int rval;
674+
675+ rval = try_pix_parm(vdev, best_pix, pix, best_ival);
676+ if (rval)
677+ return rval;
678+
679+ rval = isp_s_fmt_cap(best_pix, pix);
680+ if (rval)
681+ return rval;
682+
683+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
684+ fmt.fmt.pix = *best_pix;
685+ rval = vidioc_int_s_fmt_cap(vdev->vdev_sensor, &fmt);
686+ if (rval)
687+ return rval;
688+
689+ a.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
690+ a.parm.capture.timeperframe = *best_ival;
691+ rval = vidioc_int_s_parm(vdev->vdev_sensor, &a);
692+
693+ return rval;
694+}
695+
696+/**
697+ * vidioc_s_fmt_vid_cap - V4L2 set format capabilities IOCTL handler
698+ * @file: ptr. to system file structure
699+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
700+ * @f: ptr to standard V4L2 format structure
701+ *
702+ * Attempts to set input format with the sensor driver (first) and then the
703+ * ISP. Returns the return code from vidioc_g_fmt_vid_cap().
704+ */
705+static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
706+ struct v4l2_format *f)
707+{
708+ struct omap34xxcam_fh *ofh = fh;
709+ struct omap34xxcam_videodev *vdev = ofh->vdev;
710+ struct v4l2_pix_format pix_tmp;
711+ struct v4l2_fract timeperframe;
712+ int rval;
713+
714+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
715+ return -EINVAL;
716+
717+ mutex_lock(&vdev->mutex);
718+ if (vdev->streaming) {
719+ rval = -EBUSY;
720+ goto out;
721+ }
722+
723+ vdev->want_pix = f->fmt.pix;
724+
725+ timeperframe = vdev->want_timeperframe;
726+
727+ rval = s_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
728+ if (!rval)
729+ vdev->pix = f->fmt.pix;
730+
731+out:
732+ mutex_unlock(&vdev->mutex);
733+
734+ return rval;
735+}
736+
737+/**
738+ * vidioc_try_fmt_vid_cap - V4L2 try format capabilities IOCTL handler
739+ * @file: ptr. to system file structure
740+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
741+ * @f: ptr to standard V4L2 format structure
742+ *
743+ * Checks if the given format is supported by the sensor driver and
744+ * by the ISP.
745+ */
746+static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
747+ struct v4l2_format *f)
748+{
749+ struct omap34xxcam_fh *ofh = fh;
750+ struct omap34xxcam_videodev *vdev = ofh->vdev;
751+ struct v4l2_pix_format pix_tmp;
752+ struct v4l2_fract timeperframe;
753+ int rval;
754+
755+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
756+ return -EINVAL;
757+
758+ mutex_lock(&vdev->mutex);
759+
760+ timeperframe = vdev->want_timeperframe;
761+
762+ rval = try_pix_parm(vdev, &pix_tmp, &f->fmt.pix, &timeperframe);
763+
764+ mutex_unlock(&vdev->mutex);
765+
766+ return rval;
767+}
768+
769+/**
770+ * vidioc_reqbufs - V4L2 request buffers IOCTL handler
771+ * @file: ptr. to system file structure
772+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
773+ * @b: ptr to standard V4L2 request buffers structure
774+ *
775+ * Attempts to get a buffer from the buffer queue associated with the
776+ * fh through the video buffer library API.
777+ */
778+static int vidioc_reqbufs(struct file *file, void *fh,
779+ struct v4l2_requestbuffers *b)
780+{
781+ struct omap34xxcam_fh *ofh = fh;
782+ struct omap34xxcam_videodev *vdev = ofh->vdev;
783+ int rval;
784+
785+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
786+ return -EINVAL;
787+
788+ mutex_lock(&vdev->mutex);
789+ if (vdev->streaming) {
790+ mutex_unlock(&vdev->mutex);
791+ return -EBUSY;
792+ }
793+
794+ rval = videobuf_reqbufs(&ofh->vbq, b);
795+
796+ mutex_unlock(&vdev->mutex);
797+
798+ /*
799+ * Either videobuf_reqbufs failed or the buffers are not
800+ * memory-mapped (which would need special attention).
801+ */
802+ if (rval < 0 || b->memory != V4L2_MEMORY_MMAP)
803+ goto out;
804+
805+out:
806+ return rval;
807+}
808+
809+/**
810+ * vidioc_querybuf - V4L2 query buffer IOCTL handler
811+ * @file: ptr. to system file structure
812+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
813+ * @b: ptr to standard V4L2 buffer structure
814+ *
815+ * Attempts to fill in the v4l2_buffer structure for the buffer queue
816+ * associated with the fh through the video buffer library API.
817+ */
818+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
819+{
820+ struct omap34xxcam_fh *ofh = fh;
821+
822+ return videobuf_querybuf(&ofh->vbq, b);
823+}
824+
825+/**
826+ * vidioc_qbuf - V4L2 queue buffer IOCTL handler
827+ * @file: ptr. to system file structure
828+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
829+ * @b: ptr to standard V4L2 buffer structure
830+ *
831+ * Attempts to queue the v4l2_buffer on the buffer queue
832+ * associated with the fh through the video buffer library API.
833+ */
834+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
835+{
836+ struct omap34xxcam_fh *ofh = fh;
837+
838+ return videobuf_qbuf(&ofh->vbq, b);
839+}
840+
841+/**
842+ * vidioc_dqbuf - V4L2 dequeue buffer IOCTL handler
843+ * @file: ptr. to system file structure
844+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
845+ * @b: ptr to standard V4L2 buffer structure
846+ *
847+ * Attempts to dequeue the v4l2_buffer from the buffer queue
848+ * associated with the fh through the video buffer library API. If the
849+ * buffer is a user space buffer, then this function will also requeue it,
850+ * as user does not expect to do this.
851+ */
852+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
853+{
854+ struct omap34xxcam_fh *ofh = fh;
855+ int rval;
856+
857+videobuf_dqbuf_again:
858+ rval = videobuf_dqbuf(&ofh->vbq, b, file->f_flags & O_NONBLOCK);
859+
860+ /*
861+ * This is a hack. We don't want to show -EIO to the user
862+ * space. Requeue the buffer and try again if we're not doing
863+ * this in non-blocking mode.
864+ */
865+ if (rval == -EIO) {
866+ videobuf_qbuf(&ofh->vbq, b);
867+ if (!(file->f_flags & O_NONBLOCK))
868+ goto videobuf_dqbuf_again;
869+ /*
870+ * We don't have a videobuf_buffer now --- maybe next
871+ * time...
872+ */
873+ rval = -EAGAIN;
874+ }
875+
876+ return rval;
877+}
878+
879+/**
880+ * vidioc_streamon - V4L2 streamon IOCTL handler
881+ * @file: ptr. to system file structure
882+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
883+ * @i: V4L2 buffer type
884+ *
885+ * Attempts to start streaming by enabling the sensor interface and turning
886+ * on video buffer streaming through the video buffer library API. Upon
887+ * success the function returns 0, otherwise an error code is returned.
888+ */
889+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
890+{
891+ struct omap34xxcam_fh *ofh = fh;
892+ struct omap34xxcam_videodev *vdev = ofh->vdev;
893+ int rval;
894+
895+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
896+ return -EINVAL;
897+
898+ mutex_lock(&vdev->mutex);
899+ if (vdev->streaming) {
900+ rval = -EBUSY;
901+ goto out;
902+ }
903+
904+ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
905+ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
906+ if (rval) {
907+ dev_dbg(&vdev->vfd->dev,
908+ "omap34xxcam_slave_power_set failed\n");
909+ goto out;
910+ }
911+
912+ rval = videobuf_streamon(&ofh->vbq);
913+ if (rval)
914+ omap34xxcam_slave_power_set(
915+ vdev, V4L2_POWER_OFF,
916+ OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS);
917+ else
918+ vdev->streaming = file;
919+
920+out:
921+ mutex_unlock(&vdev->mutex);
922+
923+ return rval;
924+}
925+
926+/**
927+ * vidioc_streamoff - V4L2 streamoff IOCTL handler
928+ * @file: ptr. to system file structure
929+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
930+ * @i: V4L2 buffer type
931+ *
932+ * Attempts to stop streaming by flushing all scheduled work, waiting on
933+ * any queued buffers to complete and then stopping the ISP and turning
934+ * off video buffer streaming through the video buffer library API. Upon
935+ * success the function returns 0, otherwise an error code is returned.
936+ */
937+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
938+{
939+ struct omap34xxcam_fh *ofh = fh;
940+ struct omap34xxcam_videodev *vdev = ofh->vdev;
941+ struct videobuf_queue *q = &ofh->vbq;
942+ int rval;
943+
944+ mutex_lock(&vdev->mutex);
945+
946+ if (vdev->streaming == file)
947+ isp_stop();
948+
949+ rval = videobuf_streamoff(q);
950+ if (!rval) {
951+ vdev->streaming = NULL;
952+
953+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_STANDBY,
954+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
955+ omap34xxcam_slave_power_suggest(vdev, V4L2_POWER_STANDBY,
956+ OMAP34XXCAM_SLAVE_POWER_LENS);
957+ }
958+
959+ mutex_unlock(&vdev->mutex);
960+
961+ return rval;
962+}
963+
964+/**
965+ * vidioc_enum_input - V4L2 enumerate input IOCTL handler
966+ * @file: ptr. to system file structure
967+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
968+ * @inp: V4L2 input type information structure
969+ *
970+ * Fills in v4l2_input structure. Returns 0.
971+ */
972+static int vidioc_enum_input(struct file *file, void *fh,
973+ struct v4l2_input *inp)
974+{
975+ if (inp->index > 0)
976+ return -EINVAL;
977+
978+ strlcpy(inp->name, "camera", sizeof(inp->name));
979+ inp->type = V4L2_INPUT_TYPE_CAMERA;
980+
981+ return 0;
982+}
983+
984+/**
985+ * vidioc_g_input - V4L2 get input IOCTL handler
986+ * @file: ptr. to system file structure
987+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
988+ * @i: address to hold index of input supported
989+ *
990+ * Sets index to 0.
991+ */
992+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
993+{
994+ *i = 0;
995+
996+ return 0;
997+}
998+
999+/**
1000+ * vidioc_s_input - V4L2 set input IOCTL handler
1001+ * @file: ptr. to system file structure
1002+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1003+ * @i: index of input selected
1004+ *
1005+ * 0 is only index supported.
1006+ */
1007+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
1008+{
1009+ if (i > 0)
1010+ return -EINVAL;
1011+
1012+ return 0;
1013+}
1014+
1015+/**
1016+ * vidioc_queryctrl - V4L2 query control IOCTL handler
1017+ * @file: ptr. to system file structure
1018+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1019+ * @a: standard V4L2 query control ioctl structure
1020+ *
1021+ * If the requested control is supported, returns the control information
1022+ * in the v4l2_queryctrl structure. Otherwise, returns -EINVAL if the
1023+ * control is not supported. If the sensor being used is a "smart sensor",
1024+ * this request is passed to the sensor driver, otherwise the ISP is
1025+ * queried and if it does not support the requested control, the request
1026+ * is forwarded to the "raw" sensor driver to see if it supports it.
1027+ */
1028+static int vidioc_queryctrl(struct file *file, void *fh,
1029+ struct v4l2_queryctrl *a)
1030+{
1031+ struct omap34xxcam_fh *ofh = fh;
1032+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1033+ struct v4l2_queryctrl a_tmp;
1034+ int best_slave = -1;
1035+ u32 best_ctrl = (u32)-1;
1036+ int i;
1037+
1038+ if (vdev->vdev_sensor_config.sensor_isp)
1039+ return vidioc_int_queryctrl(vdev->vdev_sensor, a);
1040+
1041+ /* No next flags: try slaves directly. */
1042+ if (!(a->id & V4L2_CTRL_FLAG_NEXT_CTRL)) {
1043+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1044+ if (!vidioc_int_queryctrl(vdev->slave[i], a))
1045+ return 0;
1046+ }
1047+ return isp_queryctrl(a);
1048+ }
1049+
1050+ /* Find slave with smallest next control id. */
1051+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1052+ a_tmp = *a;
1053+
1054+ if (vidioc_int_queryctrl(vdev->slave[i], &a_tmp))
1055+ continue;
1056+
1057+ if (a_tmp.id < best_ctrl) {
1058+ best_slave = i;
1059+ best_ctrl = a_tmp.id;
1060+ }
1061+ }
1062+
1063+ a_tmp = *a;
1064+ if (!isp_queryctrl(&a_tmp)) {
1065+ if (a_tmp.id < best_ctrl) {
1066+ *a = a_tmp;
1067+
1068+ return 0;
1069+ }
1070+ }
1071+
1072+ if (best_slave == -1)
1073+ return -EINVAL;
1074+
1075+ a->id = best_ctrl;
1076+ return vidioc_int_queryctrl(vdev->slave[best_slave], a);
1077+}
1078+
1079+/**
1080+ * vidioc_querymenu - V4L2 query menu IOCTL handler
1081+ * @file: ptr. to system file structure
1082+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1083+ * @a: standard V4L2 query menu ioctl structure
1084+ *
1085+ * If the requested control is supported, returns the menu information
1086+ * in the v4l2_querymenu structure. Otherwise, returns -EINVAL if the
1087+ * control is not supported or is not a menu. If the sensor being used
1088+ * is a "smart sensor", this request is passed to the sensor driver,
1089+ * otherwise the ISP is queried and if it does not support the requested
1090+ * menu control, the request is forwarded to the "raw" sensor driver to
1091+ * see if it supports it.
1092+ */
1093+static int vidioc_querymenu(struct file *file, void *fh,
1094+ struct v4l2_querymenu *a)
1095+{
1096+ struct omap34xxcam_fh *ofh = fh;
1097+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1098+ int i;
1099+
1100+ if (vdev->vdev_sensor_config.sensor_isp)
1101+ return vidioc_int_querymenu(vdev->vdev_sensor, a);
1102+
1103+ /* Try slaves directly. */
1104+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1105+ if (!vidioc_int_querymenu(vdev->slave[i], a))
1106+ return 0;
1107+ }
1108+ return isp_querymenu(a);
1109+}
1110+
1111+static int vidioc_g_ext_ctrls(struct file *file, void *fh,
1112+ struct v4l2_ext_controls *a)
1113+{
1114+ struct omap34xxcam_fh *ofh = fh;
1115+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1116+ int i, ctrl_idx, rval = 0;
1117+
1118+ mutex_lock(&vdev->mutex);
1119+
1120+ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
1121+ struct v4l2_control ctrl;
1122+
1123+ ctrl.id = a->controls[ctrl_idx].id;
1124+
1125+ if (vdev->vdev_sensor_config.sensor_isp) {
1126+ rval = vidioc_int_g_ctrl(vdev->vdev_sensor, &ctrl);
1127+ } else {
1128+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1129+ rval = vidioc_int_g_ctrl(vdev->slave[i], &ctrl);
1130+ if (!rval)
1131+ break;
1132+ }
1133+ }
1134+
1135+ if (rval)
1136+ rval = isp_g_ctrl(&ctrl);
1137+
1138+ if (rval) {
1139+ a->error_idx = ctrl_idx;
1140+ break;
1141+ }
1142+
1143+ a->controls[ctrl_idx].value = ctrl.value;
1144+ }
1145+
1146+ mutex_unlock(&vdev->mutex);
1147+
1148+ return rval;
1149+}
1150+
1151+static int vidioc_s_ext_ctrls(struct file *file, void *fh,
1152+ struct v4l2_ext_controls *a)
1153+{
1154+ struct omap34xxcam_fh *ofh = fh;
1155+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1156+ int i, ctrl_idx, rval = 0;
1157+
1158+ mutex_lock(&vdev->mutex);
1159+
1160+ for (ctrl_idx = 0; ctrl_idx < a->count; ctrl_idx++) {
1161+ struct v4l2_control ctrl;
1162+
1163+ ctrl.id = a->controls[ctrl_idx].id;
1164+ ctrl.value = a->controls[ctrl_idx].value;
1165+
1166+ if (vdev->vdev_sensor_config.sensor_isp) {
1167+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor, &ctrl);
1168+ } else {
1169+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1170+ rval = vidioc_int_s_ctrl(vdev->slave[i], &ctrl);
1171+ if (!rval)
1172+ break;
1173+ }
1174+ }
1175+
1176+ if (rval)
1177+ rval = isp_s_ctrl(&ctrl);
1178+
1179+ if (rval) {
1180+ a->error_idx = ctrl_idx;
1181+ break;
1182+ }
1183+
1184+ a->controls[ctrl_idx].value = ctrl.value;
1185+ }
1186+
1187+ mutex_unlock(&vdev->mutex);
1188+
1189+ return rval;
1190+}
1191+
1192+/**
1193+ * vidioc_g_parm - V4L2 get parameters IOCTL handler
1194+ * @file: ptr. to system file structure
1195+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1196+ * @a: standard V4L2 stream parameters structure
1197+ *
1198+ * If request is for video capture buffer type, handles request by
1199+ * forwarding to sensor driver.
1200+ */
1201+static int vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1202+{
1203+ struct omap34xxcam_fh *ofh = fh;
1204+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1205+ int rval;
1206+
1207+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1208+ return -EINVAL;
1209+
1210+ mutex_lock(&vdev->mutex);
1211+ rval = vidioc_int_g_parm(vdev->vdev_sensor, a);
1212+ mutex_unlock(&vdev->mutex);
1213+
1214+ return rval;
1215+}
1216+
1217+/**
1218+ * vidioc_s_parm - V4L2 set parameters IOCTL handler
1219+ * @file: ptr. to system file structure
1220+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1221+ * @a: standard V4L2 stream parameters structure
1222+ *
1223+ * If request is for video capture buffer type, handles request by
1224+ * first getting current stream parameters from sensor, then forwarding
1225+ * request to set new parameters to sensor driver. It then attempts to
1226+ * enable the sensor interface with the new parameters. If this fails, it
1227+ * reverts back to the previous parameters.
1228+ */
1229+static int vidioc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
1230+{
1231+ struct omap34xxcam_fh *ofh = fh;
1232+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1233+ struct v4l2_pix_format pix_tmp_sensor, pix_tmp;
1234+ int rval;
1235+
1236+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1237+ return -EINVAL;
1238+
1239+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1240+ return -EINVAL;
1241+
1242+ mutex_lock(&vdev->mutex);
1243+ if (vdev->streaming) {
1244+ rval = -EBUSY;
1245+ goto out;
1246+ }
1247+
1248+ vdev->want_timeperframe = a->parm.capture.timeperframe;
1249+
1250+ pix_tmp = vdev->want_pix;
1251+
1252+ rval = s_pix_parm(vdev, &pix_tmp_sensor, &pix_tmp,
1253+ &a->parm.capture.timeperframe);
1254+
1255+out:
1256+ mutex_unlock(&vdev->mutex);
1257+
1258+ return rval;
1259+}
1260+
1261+/**
1262+ * vidioc_cropcap - V4L2 crop capture IOCTL handler
1263+ * @file: ptr. to system file structure
1264+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1265+ * @a: standard V4L2 crop capture structure
1266+ *
1267+ * If using a "smart" sensor, just forwards request to the sensor driver,
1268+ * otherwise fills in the v4l2_cropcap values locally.
1269+ */
1270+static int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
1271+{
1272+ struct omap34xxcam_fh *ofh = fh;
1273+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1274+ struct v4l2_cropcap *cropcap = a;
1275+ int rval;
1276+
1277+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1278+ return -EINVAL;
1279+
1280+ mutex_lock(&vdev->mutex);
1281+
1282+ rval = vidioc_int_cropcap(vdev->vdev_sensor, a);
1283+
1284+ if (rval && !vdev->vdev_sensor_config.sensor_isp) {
1285+ struct v4l2_format f;
1286+
1287+ /* cropcap failed, try to do this via g_fmt_cap */
1288+ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &f);
1289+ if (!rval) {
1290+ cropcap->bounds.top = 0;
1291+ cropcap->bounds.left = 0;
1292+ cropcap->bounds.width = f.fmt.pix.width;
1293+ cropcap->bounds.height = f.fmt.pix.height;
1294+ cropcap->defrect = cropcap->bounds;
1295+ cropcap->pixelaspect.numerator = 1;
1296+ cropcap->pixelaspect.denominator = 1;
1297+ }
1298+ }
1299+
1300+ mutex_unlock(&vdev->mutex);
1301+
1302+ return rval;
1303+}
1304+
1305+/**
1306+ * vidioc_g_crop - V4L2 get capture crop IOCTL handler
1307+ * @file: ptr. to system file structure
1308+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1309+ * @a: standard V4L2 crop structure
1310+ *
1311+ * If using a "smart" sensor, just forwards request to the sensor driver,
1312+ * otherwise calls the isp functions to fill in current crop values.
1313+ */
1314+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
1315+{
1316+ struct omap34xxcam_fh *ofh = fh;
1317+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1318+ int rval = 0;
1319+
1320+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1321+ return -EINVAL;
1322+
1323+ mutex_lock(&vdev->mutex);
1324+
1325+ if (vdev->vdev_sensor_config.sensor_isp)
1326+ rval = vidioc_int_g_crop(vdev->vdev_sensor, a);
1327+ else
1328+ rval = isp_g_crop(a);
1329+
1330+ mutex_unlock(&vdev->mutex);
1331+
1332+ return rval;
1333+}
1334+
1335+/**
1336+ * vidioc_s_crop - V4L2 set capture crop IOCTL handler
1337+ * @file: ptr. to system file structure
1338+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1339+ * @a: standard V4L2 crop structure
1340+ *
1341+ * If using a "smart" sensor, just forwards request to the sensor driver,
1342+ * otherwise calls the isp functions to set the current crop values.
1343+ */
1344+static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
1345+{
1346+ struct omap34xxcam_fh *ofh = fh;
1347+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1348+ int rval = 0;
1349+
1350+ if (vdev->vdev_sensor == v4l2_int_device_dummy())
1351+ return -EINVAL;
1352+
1353+ mutex_lock(&vdev->mutex);
1354+
1355+ if (vdev->vdev_sensor_config.sensor_isp)
1356+ rval = vidioc_int_s_crop(vdev->vdev_sensor, a);
1357+ else
1358+ rval = isp_s_crop(a, &vdev->pix);
1359+
1360+ mutex_unlock(&vdev->mutex);
1361+
1362+ return rval;
1363+}
1364+
1365+static int vidioc_enum_framesizes(struct file *file, void *fh,
1366+ struct v4l2_frmsizeenum *frms)
1367+{
1368+ struct omap34xxcam_fh *ofh = fh;
1369+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1370+ u32 pixel_format;
1371+ int rval;
1372+
1373+ mutex_lock(&vdev->mutex);
1374+
1375+ if (vdev->vdev_sensor_config.sensor_isp) {
1376+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
1377+ } else {
1378+ pixel_format = frms->pixel_format;
1379+ frms->pixel_format = -1; /* ISP does format conversion */
1380+ rval = vidioc_int_enum_framesizes(vdev->vdev_sensor, frms);
1381+ frms->pixel_format = pixel_format;
1382+ }
1383+
1384+ mutex_unlock(&vdev->mutex);
1385+ return rval;
1386+}
1387+
1388+static int vidioc_enum_frameintervals(struct file *file, void *fh,
1389+ struct v4l2_frmivalenum *frmi)
1390+{
1391+ struct omap34xxcam_fh *ofh = fh;
1392+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1393+ u32 pixel_format;
1394+ int rval;
1395+
1396+ mutex_lock(&vdev->mutex);
1397+
1398+ if (vdev->vdev_sensor_config.sensor_isp) {
1399+ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
1400+ } else {
1401+ pixel_format = frmi->pixel_format;
1402+ frmi->pixel_format = -1; /* ISP does format conversion */
1403+ rval = vidioc_int_enum_frameintervals(vdev->vdev_sensor, frmi);
1404+ frmi->pixel_format = pixel_format;
1405+ }
1406+
1407+ mutex_unlock(&vdev->mutex);
1408+ return rval;
1409+}
1410+
1411+/**
1412+ * vidioc_default - private IOCTL handler
1413+ * @file: ptr. to system file structure
1414+ * @fh: ptr to hold address of omap34xxcam_fh struct (per-filehandle data)
1415+ * @cmd: ioctl cmd value
1416+ * @arg: ioctl arg value
1417+ *
1418+ * If the sensor being used is a "smart sensor", this request is returned to
1419+ * caller with -EINVAL err code. Otherwise if the control id is the private
1420+ * VIDIOC_PRIVATE_ISP_AEWB_REQ to update the analog gain or exposure,
1421+ * then this request is forwared directly to the sensor to incorporate the
1422+ * feedback. The request is then passed on to the ISP private IOCTL handler,
1423+ * isp_handle_private()
1424+ */
1425+static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
1426+{
1427+ struct omap34xxcam_fh *ofh = file->private_data;
1428+ struct omap34xxcam_videodev *vdev = ofh->vdev;
1429+ int rval;
1430+
1431+ if (vdev->vdev_sensor_config.sensor_isp) {
1432+ rval = -EINVAL;
1433+ } else {
1434+ switch (cmd) {
1435+ case VIDIOC_PRIVATE_ISP_AEWB_REQ:
1436+ {
1437+ /* Need to update sensor first */
1438+ struct isph3a_aewb_data *data;
1439+ struct v4l2_control vc;
1440+
1441+ data = (struct isph3a_aewb_data *) arg;
1442+ if (data->update & SET_EXPOSURE) {
1443+ dev_info(&vdev->vfd->dev, "using "
1444+ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
1445+ "exposure is deprecated!\n");
1446+ vc.id = V4L2_CID_EXPOSURE;
1447+ vc.value = data->shutter;
1448+ mutex_lock(&vdev->mutex);
1449+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
1450+ &vc);
1451+ mutex_unlock(&vdev->mutex);
1452+ if (rval)
1453+ goto out;
1454+ }
1455+ if (data->update & SET_ANALOG_GAIN) {
1456+ dev_info(&vdev->vfd->dev, "using "
1457+ "VIDIOC_PRIVATE_ISP_AEWB_REQ to set "
1458+ "gain is deprecated!\n");
1459+ vc.id = V4L2_CID_GAIN;
1460+ vc.value = data->gain;
1461+ mutex_lock(&vdev->mutex);
1462+ rval = vidioc_int_s_ctrl(vdev->vdev_sensor,
1463+ &vc);
1464+ mutex_unlock(&vdev->mutex);
1465+ if (rval)
1466+ goto out;
1467+ }
1468+ }
1469+ break;
1470+ case VIDIOC_PRIVATE_ISP_AF_REQ: {
1471+ /* Need to update lens first */
1472+ struct isp_af_data *data;
1473+ struct v4l2_control vc;
1474+
1475+ if (!vdev->vdev_lens) {
1476+ rval = -EINVAL;
1477+ goto out;
1478+ }
1479+ data = (struct isp_af_data *) arg;
1480+ if (data->update & LENS_DESIRED_POSITION) {
1481+ dev_info(&vdev->vfd->dev, "using "
1482+ "VIDIOC_PRIVATE_ISP_AF_REQ to set "
1483+ "lens position is deprecated!\n");
1484+ vc.id = V4L2_CID_FOCUS_ABSOLUTE;
1485+ vc.value = data->desired_lens_direction;
1486+ mutex_lock(&vdev->mutex);
1487+ rval = vidioc_int_s_ctrl(vdev->vdev_lens, &vc);
1488+ mutex_unlock(&vdev->mutex);
1489+ if (rval)
1490+ goto out;
1491+ }
1492+ }
1493+ break;
1494+ }
1495+
1496+ mutex_lock(&vdev->mutex);
1497+ rval = isp_handle_private(cmd, arg);
1498+ mutex_unlock(&vdev->mutex);
1499+ }
1500+out:
1501+ return rval;
1502+}
1503+
1504+/*
1505+ *
1506+ * File operations.
1507+ *
1508+ */
1509+
1510+/**
1511+ * omap34xxcam_poll - file operations poll handler
1512+ * @file: ptr. to system file structure
1513+ * @wait: system poll table structure
1514+ *
1515+ */
1516+static unsigned int omap34xxcam_poll(struct file *file,
1517+ struct poll_table_struct *wait)
1518+{
1519+ struct omap34xxcam_fh *fh = file->private_data;
1520+ struct omap34xxcam_videodev *vdev = fh->vdev;
1521+ struct videobuf_buffer *vb;
1522+
1523+ mutex_lock(&vdev->mutex);
1524+ if (vdev->streaming != file) {
1525+ mutex_unlock(&vdev->mutex);
1526+ return POLLERR;
1527+ }
1528+ mutex_unlock(&vdev->mutex);
1529+
1530+ mutex_lock(&fh->vbq.vb_lock);
1531+ if (list_empty(&fh->vbq.stream)) {
1532+ mutex_unlock(&fh->vbq.vb_lock);
1533+ return POLLERR;
1534+ }
1535+ vb = list_entry(fh->vbq.stream.next, struct videobuf_buffer, stream);
1536+ mutex_unlock(&fh->vbq.vb_lock);
1537+
1538+ poll_wait(file, &vb->done, wait);
1539+
1540+ if (vb->state == VIDEOBUF_DONE || vb->state == VIDEOBUF_ERROR)
1541+ return POLLIN | POLLRDNORM;
1542+
1543+ return 0;
1544+}
1545+
1546+/**
1547+ * omap34xxcam_mmap - file operations mmap handler
1548+ * @file: ptr. to system file structure
1549+ * @vma: system virt. mem. area structure
1550+ *
1551+ * Maps a virtual memory area via the video buffer API
1552+ */
1553+static int omap34xxcam_mmap(struct file *file, struct vm_area_struct *vma)
1554+{
1555+ struct omap34xxcam_fh *fh = file->private_data;
1556+ return videobuf_mmap_mapper(&fh->vbq, vma);
1557+}
1558+
1559+/**
1560+ * omap34xxcam_open - file operations open handler
1561+ * @inode: ptr. to system inode structure
1562+ * @file: ptr. to system file structure
1563+ *
1564+ * Allocates and initializes the per-filehandle data (omap34xxcam_fh),
1565+ * enables the sensor, opens/initializes the ISP interface and the
1566+ * video buffer queue. Note that this function will allow multiple
1567+ * file handles to be open simultaneously, however only the first
1568+ * handle opened will initialize the ISP. It is the application
1569+ * responsibility to only use one handle for streaming and the others
1570+ * for control only.
1571+ * This function returns 0 upon success and -ENODEV upon error.
1572+ */
1573+static int omap34xxcam_open(struct file *file)
1574+{
1575+ int rval = 0;
1576+ struct omap34xxcam_videodev *vdev = NULL;
1577+ struct omap34xxcam_device *cam = omap34xxcam;
1578+ struct omap34xxcam_fh *fh;
1579+ struct v4l2_format format;
1580+ int i;
1581+
1582+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1583+ if (cam->vdevs[i].vfd
1584+ && cam->vdevs[i].vfd->minor ==
1585+ iminor(file->f_dentry->d_inode)) {
1586+ vdev = &cam->vdevs[i];
1587+ break;
1588+ }
1589+ }
1590+
1591+ if (!vdev || !vdev->vfd)
1592+ return -ENODEV;
1593+
1594+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1595+ if (fh == NULL)
1596+ return -ENOMEM;
1597+
1598+ mutex_lock(&vdev->mutex);
1599+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1600+ if (vdev->slave[i] != v4l2_int_device_dummy()
1601+ && !try_module_get(vdev->slave[i]->module)) {
1602+ mutex_unlock(&vdev->mutex);
1603+ dev_err(&vdev->vfd->dev, "can't try_module_get %s\n",
1604+ vdev->slave[i]->name);
1605+ rval = -ENODEV;
1606+ goto out_try_module_get;
1607+ }
1608+ }
1609+
1610+ if (atomic_inc_return(&vdev->users) == 1) {
1611+ rval = isp_get();
1612+ if (rval < 0) {
1613+ dev_err(&vdev->vfd->dev, "can't get isp\n");
1614+ goto out_isp_get;
1615+ }
1616+ if (omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
1617+ OMAP34XXCAM_SLAVE_POWER_ALL)) {
1618+ dev_err(&vdev->vfd->dev, "can't power up slaves\n");
1619+ rval = -EBUSY;
1620+ goto out_slave_power_set_standby;
1621+ }
1622+ omap34xxcam_slave_power_set(
1623+ vdev, V4L2_POWER_STANDBY,
1624+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
1625+ omap34xxcam_slave_power_suggest(
1626+ vdev, V4L2_POWER_STANDBY,
1627+ OMAP34XXCAM_SLAVE_POWER_LENS);
1628+ }
1629+
1630+ fh->vdev = vdev;
1631+
1632+ if (!vdev->pix.width
1633+ && vdev->vdev_sensor != v4l2_int_device_dummy()) {
1634+ memset(&format, 0, sizeof(format));
1635+ if (vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format)) {
1636+ dev_err(&vdev->vfd->dev,
1637+ "can't get current pix from sensor!\n");
1638+ goto out_vidioc_int_g_fmt_cap;
1639+ }
1640+ if (!vdev->vdev_sensor_config.sensor_isp) {
1641+ struct v4l2_pix_format pix = format.fmt.pix;
1642+ if (isp_s_fmt_cap(&pix, &format.fmt.pix)) {
1643+ dev_err(&vdev->vfd->dev,
1644+ "isp doesn't like the sensor!\n");
1645+ goto out_isp_s_fmt_cap;
1646+ }
1647+ }
1648+ vdev->pix = format.fmt.pix;
1649+ }
1650+
1651+ mutex_unlock(&vdev->mutex);
1652+
1653+ file->private_data = fh;
1654+
1655+ spin_lock_init(&fh->vbq_lock);
1656+
1657+ videobuf_queue_sg_init(&fh->vbq, &omap34xxcam_vbq_ops, NULL,
1658+ &fh->vbq_lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
1659+ V4L2_FIELD_NONE,
1660+ sizeof(struct videobuf_buffer), fh);
1661+
1662+ return 0;
1663+
1664+out_isp_s_fmt_cap:
1665+out_vidioc_int_g_fmt_cap:
1666+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
1667+ OMAP34XXCAM_SLAVE_POWER_ALL);
1668+out_slave_power_set_standby:
1669+ isp_put();
1670+
1671+out_isp_get:
1672+ atomic_dec(&vdev->users);
1673+ mutex_unlock(&vdev->mutex);
1674+
1675+out_try_module_get:
1676+ for (i--; i >= 0; i--)
1677+ if (vdev->slave[i] != v4l2_int_device_dummy())
1678+ module_put(vdev->slave[i]->module);
1679+
1680+ kfree(fh);
1681+
1682+ return rval;
1683+}
1684+
1685+/**
1686+ * omap34xxcam_release - file operations release handler
1687+ * @inode: ptr. to system inode structure
1688+ * @file: ptr. to system file structure
1689+ *
1690+ * Complement of omap34xxcam_open. This function will flush any scheduled
1691+ * work, disable the sensor, close the ISP interface, stop the
1692+ * video buffer queue from streaming and free the per-filehandle data
1693+ * (omap34xxcam_fh). Note that because multiple open file handles
1694+ * are allowed, this function will only close the ISP and disable the
1695+ * sensor when the last open file handle (by count) is closed.
1696+ * This function returns 0.
1697+ */
1698+static int omap34xxcam_release(struct file *file)
1699+{
1700+ struct omap34xxcam_fh *fh = file->private_data;
1701+ struct omap34xxcam_videodev *vdev = fh->vdev;
1702+ int i;
1703+
1704+ mutex_lock(&vdev->mutex);
1705+ if (vdev->streaming == file) {
1706+ isp_stop();
1707+ videobuf_streamoff(&fh->vbq);
1708+ omap34xxcam_slave_power_set(
1709+ vdev, V4L2_POWER_STANDBY,
1710+ OMAP34XXCAM_SLAVE_POWER_SENSOR);
1711+ omap34xxcam_slave_power_suggest(
1712+ vdev, V4L2_POWER_STANDBY,
1713+ OMAP34XXCAM_SLAVE_POWER_LENS);
1714+ vdev->streaming = NULL;
1715+ }
1716+
1717+ if (atomic_dec_return(&vdev->users) == 0) {
1718+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF,
1719+ OMAP34XXCAM_SLAVE_POWER_ALL);
1720+ isp_put();
1721+ }
1722+ mutex_unlock(&vdev->mutex);
1723+
1724+ file->private_data = NULL;
1725+
1726+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++)
1727+ if (vdev->slave[i] != v4l2_int_device_dummy())
1728+ module_put(vdev->slave[i]->module);
1729+
1730+ kfree(fh);
1731+
1732+ return 0;
1733+}
1734+
1735+static struct v4l2_file_operations omap34xxcam_fops = {
1736+ .owner = THIS_MODULE,
1737+ .unlocked_ioctl = video_ioctl2,
1738+ .poll = omap34xxcam_poll,
1739+ .mmap = omap34xxcam_mmap,
1740+ .open = omap34xxcam_open,
1741+ .release = omap34xxcam_release,
1742+};
1743+
1744+static void omap34xxcam_vfd_name_update(struct omap34xxcam_videodev *vdev)
1745+{
1746+ struct video_device *vfd = vdev->vfd;
1747+ int i;
1748+
1749+ strlcpy(vfd->name, CAM_SHORT_NAME, sizeof(vfd->name));
1750+ for (i = 0; i <= OMAP34XXCAM_SLAVE_FLASH; i++) {
1751+ strlcat(vfd->name, "/", sizeof(vfd->name));
1752+ if (vdev->slave[i] == v4l2_int_device_dummy())
1753+ continue;
1754+ strlcat(vfd->name, vdev->slave[i]->name, sizeof(vfd->name));
1755+ }
1756+ dev_info(&vdev->vfd->dev, "video%d is now %s\n", vfd->num, vfd->name);
1757+}
1758+
1759+/**
1760+ * omap34xxcam_device_unregister - V4L2 detach handler
1761+ * @s: ptr. to standard V4L2 device information structure
1762+ *
1763+ * Detach sensor and unregister and release the video device.
1764+ */
1765+static void omap34xxcam_device_unregister(struct v4l2_int_device *s)
1766+{
1767+ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
1768+ struct omap34xxcam_hw_config hwc;
1769+
1770+ BUG_ON(vidioc_int_g_priv(s, &hwc) < 0);
1771+
1772+ mutex_lock(&vdev->mutex);
1773+
1774+ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy()) {
1775+ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
1776+ vdev->slaves--;
1777+ omap34xxcam_vfd_name_update(vdev);
1778+ }
1779+
1780+ if (vdev->slaves == 0 && vdev->vfd) {
1781+ if (vdev->vfd->minor == -1) {
1782+ /*
1783+ * The device was never registered, so release the
1784+ * video_device struct directly.
1785+ */
1786+ video_device_release(vdev->vfd);
1787+ } else {
1788+ /*
1789+ * The unregister function will release the
1790+ * video_device struct as well as
1791+ * unregistering it.
1792+ */
1793+ video_unregister_device(vdev->vfd);
1794+ }
1795+ vdev->vfd = NULL;
1796+ }
1797+
1798+ mutex_unlock(&vdev->mutex);
1799+}
1800+
1801+static const struct v4l2_ioctl_ops omap34xxcam_ioctl_ops = {
1802+ .vidioc_querycap = vidioc_querycap,
1803+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1804+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1805+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1806+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1807+ .vidioc_reqbufs = vidioc_reqbufs,
1808+ .vidioc_querybuf = vidioc_querybuf,
1809+ .vidioc_qbuf = vidioc_qbuf,
1810+ .vidioc_dqbuf = vidioc_dqbuf,
1811+ .vidioc_streamon = vidioc_streamon,
1812+ .vidioc_streamoff = vidioc_streamoff,
1813+ .vidioc_enum_input = vidioc_enum_input,
1814+ .vidioc_g_input = vidioc_g_input,
1815+ .vidioc_s_input = vidioc_s_input,
1816+ .vidioc_queryctrl = vidioc_queryctrl,
1817+ .vidioc_querymenu = vidioc_querymenu,
1818+ .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1819+ .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1820+ .vidioc_g_parm = vidioc_g_parm,
1821+ .vidioc_s_parm = vidioc_s_parm,
1822+ .vidioc_cropcap = vidioc_cropcap,
1823+ .vidioc_g_crop = vidioc_g_crop,
1824+ .vidioc_s_crop = vidioc_s_crop,
1825+ .vidioc_enum_framesizes = vidioc_enum_framesizes,
1826+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
1827+ .vidioc_default = vidioc_default,
1828+};
1829+
1830+/**
1831+ * omap34xxcam_device_register - V4L2 attach handler
1832+ * @s: ptr. to standard V4L2 device information structure
1833+ *
1834+ * Allocates and initializes the V4L2 video_device structure, initializes
1835+ * the sensor, and finally
1836+ registers the device with V4L2 based on the
1837+ * video_device structure.
1838+ *
1839+ * Returns 0 on success, otherwise an appropriate error code on
1840+ * failure.
1841+ */
1842+static int omap34xxcam_device_register(struct v4l2_int_device *s)
1843+{
1844+ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
1845+ struct omap34xxcam_hw_config hwc;
1846+ int rval;
1847+
1848+ /* We need to check rval just once. The place is here. */
1849+ if (vidioc_int_g_priv(s, &hwc))
1850+ return -ENODEV;
1851+
1852+ if (vdev->index != hwc.dev_index)
1853+ return -ENODEV;
1854+
1855+ if (hwc.dev_type < 0 || hwc.dev_type > OMAP34XXCAM_SLAVE_FLASH)
1856+ return -EINVAL;
1857+
1858+ if (vdev->slave[hwc.dev_type] != v4l2_int_device_dummy())
1859+ return -EBUSY;
1860+
1861+ mutex_lock(&vdev->mutex);
1862+ if (atomic_read(&vdev->users)) {
1863+ printk(KERN_ERR "%s: we're open (%d), can't register\n",
1864+ __func__, atomic_read(&vdev->users));
1865+ mutex_unlock(&vdev->mutex);
1866+ return -EBUSY;
1867+ }
1868+
1869+ vdev->slaves++;
1870+ vdev->slave[hwc.dev_type] = s;
1871+ vdev->slave_config[hwc.dev_type] = hwc;
1872+
1873+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
1874+ rval = isp_get();
1875+ if (rval < 0) {
1876+ printk(KERN_ERR "%s: can't get ISP, "
1877+ "sensor init failed\n", __func__);
1878+ goto err;
1879+ }
1880+ }
1881+ rval = omap34xxcam_slave_power_set(vdev, V4L2_POWER_ON,
1882+ 1 << hwc.dev_type);
1883+ if (rval)
1884+ goto err_omap34xxcam_slave_power_set;
1885+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR) {
1886+ struct v4l2_format format;
1887+
1888+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1889+ rval = vidioc_int_g_fmt_cap(vdev->vdev_sensor, &format);
1890+ if (rval)
1891+ rval = -EBUSY;
1892+
1893+ vdev->want_pix = format.fmt.pix;
1894+ }
1895+ omap34xxcam_slave_power_set(vdev, V4L2_POWER_OFF, 1 << hwc.dev_type);
1896+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
1897+ isp_put();
1898+
1899+ if (rval)
1900+ goto err;
1901+
1902+ /* Are we the first slave? */
1903+ if (vdev->slaves == 1) {
1904+ /* initialize the video_device struct */
1905+ vdev->vfd = video_device_alloc();
1906+ if (!vdev->vfd) {
1907+ printk(KERN_ERR "%s: could not allocate "
1908+ "video device struct\n", __func__);
1909+ rval = -ENOMEM;
1910+ goto err;
1911+ }
1912+ vdev->vfd->release = video_device_release;
1913+ vdev->vfd->minor = -1;
1914+ vdev->vfd->fops = &omap34xxcam_fops;
1915+ vdev->vfd->ioctl_ops = &omap34xxcam_ioctl_ops;
1916+ video_set_drvdata(vdev->vfd, vdev);
1917+
1918+ if (video_register_device(vdev->vfd, VFL_TYPE_GRABBER,
1919+ hwc.dev_minor) < 0) {
1920+ printk(KERN_ERR "%s: could not register V4L device\n",
1921+ __func__);
1922+ vdev->vfd->minor = -1;
1923+ rval = -EBUSY;
1924+ goto err;
1925+ }
1926+ }
1927+
1928+ omap34xxcam_vfd_name_update(vdev);
1929+
1930+ mutex_unlock(&vdev->mutex);
1931+
1932+ return 0;
1933+
1934+err_omap34xxcam_slave_power_set:
1935+ if (hwc.dev_type == OMAP34XXCAM_SLAVE_SENSOR)
1936+ isp_put();
1937+
1938+err:
1939+ if (s == vdev->slave[hwc.dev_type]) {
1940+ vdev->slave[hwc.dev_type] = v4l2_int_device_dummy();
1941+ vdev->slaves--;
1942+ }
1943+
1944+ mutex_unlock(&vdev->mutex);
1945+ omap34xxcam_device_unregister(s);
1946+
1947+ return rval;
1948+}
1949+
1950+static struct v4l2_int_master omap34xxcam_master = {
1951+ .attach = omap34xxcam_device_register,
1952+ .detach = omap34xxcam_device_unregister,
1953+};
1954+
1955+/*
1956+ *
1957+ * Module initialisation and deinitialisation
1958+ *
1959+ */
1960+
1961+static void omap34xxcam_exit(void)
1962+{
1963+ struct omap34xxcam_device *cam = omap34xxcam;
1964+ int i;
1965+
1966+ if (!cam)
1967+ return;
1968+
1969+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1970+ if (cam->vdevs[i].cam == NULL)
1971+ continue;
1972+
1973+ v4l2_int_device_unregister(&cam->vdevs[i].master);
1974+ cam->vdevs[i].cam = NULL;
1975+ }
1976+
1977+ omap34xxcam = NULL;
1978+
1979+ kfree(cam);
1980+}
1981+
1982+static int __init omap34xxcam_init(void)
1983+{
1984+ struct omap34xxcam_device *cam;
1985+ int i;
1986+
1987+ cam = kzalloc(sizeof(*cam), GFP_KERNEL);
1988+ if (!cam) {
1989+ printk(KERN_ERR "%s: could not allocate memory\n", __func__);
1990+ return -ENOMEM;
1991+ }
1992+
1993+ omap34xxcam = cam;
1994+
1995+ for (i = 0; i < OMAP34XXCAM_VIDEODEVS; i++) {
1996+ struct omap34xxcam_videodev *vdev = &cam->vdevs[i];
1997+ struct v4l2_int_device *m = &vdev->master;
1998+
1999+ m->module = THIS_MODULE;
2000+ strlcpy(m->name, CAM_NAME, sizeof(m->name));
2001+ m->type = v4l2_int_type_master;
2002+ m->u.master = &omap34xxcam_master;
2003+ m->priv = vdev;
2004+
2005+ mutex_init(&vdev->mutex);
2006+ vdev->index = i;
2007+ vdev->cam = cam;
2008+ vdev->vdev_sensor =
2009+ vdev->vdev_lens =
2010+ vdev->vdev_flash = v4l2_int_device_dummy();
2011+#ifdef OMAP34XXCAM_POWEROFF_DELAY
2012+ setup_timer(&vdev->poweroff_timer,
2013+ omap34xxcam_slave_power_timer, (unsigned long)vdev);
2014+ INIT_WORK(&vdev->poweroff_work, omap34xxcam_slave_power_work);
2015+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
2016+
2017+ if (v4l2_int_device_register(m))
2018+ goto err;
2019+ }
2020+
2021+ return 0;
2022+
2023+err:
2024+ omap34xxcam_exit();
2025+ return -ENODEV;
2026+}
2027+
2028+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
2029+MODULE_DESCRIPTION("OMAP34xx Video for Linux camera driver");
2030+MODULE_LICENSE("GPL");
2031+
2032+late_initcall(omap34xxcam_init);
2033+module_exit(omap34xxcam_exit);
2034diff --git a/drivers/media/video/omap34xxcam.h b/drivers/media/video/omap34xxcam.h
2035new file mode 100644
2036index 0000000..9859d15
2037--- /dev/null
2038+++ b/drivers/media/video/omap34xxcam.h
2039@@ -0,0 +1,207 @@
2040+/*
2041+ * omap34xxcam.h
2042+ *
2043+ * Copyright (C) 2006--2009 Nokia Corporation
2044+ * Copyright (C) 2007--2009 Texas Instruments
2045+ *
2046+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
2047+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2048+ *
2049+ * Originally based on the OMAP 2 camera driver.
2050+ *
2051+ * Written by Sakari Ailus <sakari.ailus@nokia.com>
2052+ * Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
2053+ * Sergio Aguirre <saaguirre@ti.com>
2054+ * Mohit Jalori
2055+ * Sameer Venkatraman
2056+ * Leonides Martinez
2057+ *
2058+ * This program is free software; you can redistribute it and/or
2059+ * modify it under the terms of the GNU General Public License
2060+ * version 2 as published by the Free Software Foundation.
2061+ *
2062+ * This program is distributed in the hope that it will be useful, but
2063+ * WITHOUT ANY WARRANTY; without even the implied warranty of
2064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2065+ * General Public License for more details.
2066+ *
2067+ * You should have received a copy of the GNU General Public License
2068+ * along with this program; if not, write to the Free Software
2069+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
2070+ * 02110-1301 USA
2071+ *
2072+ */
2073+
2074+#ifndef OMAP34XXCAM_H
2075+#define OMAP34XXCAM_H
2076+
2077+#include <media/v4l2-int-device.h>
2078+#include "isp/isp.h"
2079+
2080+#define CAM_NAME "omap34xxcam"
2081+#define CAM_SHORT_NAME "omap3"
2082+
2083+#define OMAP_ISP_AF (1 << 4)
2084+#define OMAP_ISP_HIST (1 << 5)
2085+#define OMAP34XXCAM_XCLK_NONE -1
2086+#define OMAP34XXCAM_XCLK_A 0
2087+#define OMAP34XXCAM_XCLK_B 1
2088+
2089+#define OMAP34XXCAM_SLAVE_SENSOR 0
2090+#define OMAP34XXCAM_SLAVE_LENS 1
2091+#define OMAP34XXCAM_SLAVE_FLASH 2 /* This is the last slave! */
2092+
2093+/* mask for omap34xxcam_slave_power_set */
2094+#define OMAP34XXCAM_SLAVE_POWER_SENSOR (1 << OMAP34XXCAM_SLAVE_SENSOR)
2095+#define OMAP34XXCAM_SLAVE_POWER_LENS (1 << OMAP34XXCAM_SLAVE_LENS)
2096+#define OMAP34XXCAM_SLAVE_POWER_SENSOR_LENS \
2097+ (OMAP34XXCAM_SLAVE_POWER_SENSOR | OMAP34XXCAM_SLAVE_POWER_LENS)
2098+#define OMAP34XXCAM_SLAVE_POWER_FLASH (1 << OMAP34XXCAM_SLAVE_FLASH)
2099+#define OMAP34XXCAM_SLAVE_POWER_ALL -1
2100+
2101+#define OMAP34XXCAM_VIDEODEVS 4
2102+
2103+/* #define OMAP34XXCAM_POWEROFF_DELAY (2 * HZ) */
2104+
2105+struct omap34xxcam_device;
2106+struct omap34xxcam_videodev;
2107+
2108+struct omap34xxcam_sensor_config {
2109+ int xclk;
2110+ int sensor_isp;
2111+ u32 capture_mem;
2112+ struct v4l2_fract ival_default;
2113+};
2114+
2115+struct omap34xxcam_lens_config {
2116+};
2117+
2118+struct omap34xxcam_flash_config {
2119+};
2120+
2121+/**
2122+ * struct omap34xxcam_hw_config - struct for vidioc_int_g_priv ioctl
2123+ * @xclk: OMAP34XXCAM_XCLK_A or OMAP34XXCAM_XCLK_B
2124+ * @sensor_isp: Is sensor smart/SOC or raw
2125+ * @s_pix_sparm: Access function to set pix and sparm.
2126+ * Pix will override sparm
2127+ */
2128+struct omap34xxcam_hw_config {
2129+ int dev_index; /* Index in omap34xxcam_sensors */
2130+ int dev_minor; /* Video device minor number */
2131+ int dev_type; /* OMAP34XXCAM_SLAVE_* */
2132+ union {
2133+ struct omap34xxcam_sensor_config sensor;
2134+ struct omap34xxcam_lens_config lens;
2135+ struct omap34xxcam_flash_config flash;
2136+ } u;
2137+};
2138+
2139+/**
2140+ * struct omap34xxcam_videodev - per /dev/video* structure
2141+ * @mutex: serialises access to this structure
2142+ * @cam: pointer to cam hw structure
2143+ * @master: we are v4l2_int_device master
2144+ * @sensor: sensor device
2145+ * @lens: lens device
2146+ * @flash: flash device
2147+ * @slaves: how many slaves we have at the moment
2148+ * @vfd: our video device
2149+ * @capture_mem: maximum kernel-allocated capture memory
2150+ * @if_u: sensor interface stuff
2151+ * @index: index of this structure in cam->vdevs
2152+ * @users: how many users we have
2153+ * @power_state: Current power state
2154+ * @power_state_wish: New power state when poweroff_timer expires
2155+ * @power_state_mask: Bitmask of devices to set the new power state
2156+ * @poweroff_timer: Timer for dispatching poweroff_work
2157+ * @poweroff_work: Work for slave power state change
2158+ * @sensor_config: ISP-speicific sensor configuration
2159+ * @lens_config: ISP-speicific lens configuration
2160+ * @flash_config: ISP-speicific flash configuration
2161+ * @want_timeperframe: Desired timeperframe
2162+ * @want_pix: Desired pix
2163+ * @pix: Current pix
2164+ * @streaming: streaming file handle, if streaming is enabled
2165+ */
2166+struct omap34xxcam_videodev {
2167+ struct mutex mutex; /* serialises access to this structure */
2168+
2169+ struct omap34xxcam_device *cam;
2170+ struct v4l2_int_device master;
2171+
2172+#define vdev_sensor slave[OMAP34XXCAM_SLAVE_SENSOR]
2173+#define vdev_lens slave[OMAP34XXCAM_SLAVE_LENS]
2174+#define vdev_flash slave[OMAP34XXCAM_SLAVE_FLASH]
2175+ struct v4l2_int_device *slave[OMAP34XXCAM_SLAVE_FLASH + 1];
2176+
2177+ /* number of slaves attached */
2178+ int slaves;
2179+
2180+ /*** video device parameters ***/
2181+ struct video_device *vfd;
2182+ int capture_mem;
2183+
2184+ /*** general driver state information ***/
2185+ int index;
2186+ atomic_t users;
2187+ enum v4l2_power power_state[OMAP34XXCAM_SLAVE_FLASH + 1];
2188+#ifdef OMAP34XXCAM_POWEROFF_DELAY
2189+ enum v4l2_power power_state_wish;
2190+ int power_state_mask;
2191+ struct timer_list poweroff_timer;
2192+ struct work_struct poweroff_work;
2193+#endif /* OMAP34XXCAM_POWEROFF_DELAY */
2194+
2195+#define vdev_sensor_config slave_config[OMAP34XXCAM_SLAVE_SENSOR].u.sensor
2196+#define vdev_lens_config slave_config[OMAP34XXCAM_SLAVE_LENS].u.lens
2197+#define vdev_flash_config slave_config[OMAP34XXCAM_SLAVE_FLASH].u.flash
2198+ struct omap34xxcam_hw_config slave_config[OMAP34XXCAM_SLAVE_FLASH + 1];
2199+
2200+ /*** capture data ***/
2201+ struct file *streaming;
2202+ struct v4l2_fract want_timeperframe;
2203+ struct v4l2_pix_format want_pix;
2204+ spinlock_t pix_lock;
2205+ struct v4l2_pix_format pix;
2206+};
2207+
2208+/**
2209+ * struct omap34xxcam_device - per-device data structure
2210+ * @mutex: mutex serialises access to this structure
2211+ * @sgdma_in_queue: Number or sgdma requests in scatter-gather queue,
2212+ * protected by the lock above.
2213+ * @sgdma: ISP sgdma subsystem information structure
2214+ * @dma_notify: DMA notify flag
2215+ * @dev: device structure
2216+ * @vdevs: /dev/video specific structures
2217+ * @fck: camera module fck clock information
2218+ * @ick: camera module ick clock information
2219+ */
2220+struct omap34xxcam_device {
2221+ struct mutex mutex; /* serialises access to this structure */
2222+
2223+ /*** interfaces and device ***/
2224+ struct omap34xxcam_videodev vdevs[OMAP34XXCAM_VIDEODEVS];
2225+
2226+ /*** camera module clocks ***/
2227+ struct clk *fck;
2228+ struct clk *ick;
2229+ bool sensor_if_enabled;
2230+};
2231+
2232+/**
2233+ * struct omap34xxcam_fh - per-filehandle data structure
2234+ * @vbq_lock: spinlock for the videobuf queue
2235+ * @vbq: V4L2 video buffer queue structure
2236+ * @field_count: field counter for videobuf_buffer
2237+ * @vdev: our /dev/video specific structure
2238+ */
2239+struct omap34xxcam_fh {
2240+ spinlock_t vbq_lock; /* spinlock for the videobuf queue */
2241+ struct videobuf_queue vbq;
2242+ atomic_t field_count;
2243+ struct omap34xxcam_videodev *vdev;
2244+};
2245+
2246+#endif /* ifndef OMAP34XXCAM_H */
2247--
22481.5.6.5
2249
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch
new file mode 100644
index 0000000000..f796ce8346
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0001-Resizer-and-Previewer-driver-added-to-commit.patch
@@ -0,0 +1,2915 @@
1From 3041daa54b49bcb6ab444c7b9e14bc6a1ade6236 Mon Sep 17 00:00:00 2001
2From: Vaibhav Hiremath <hvaibhav@ti.com>
3Date: Fri, 13 Feb 2009 14:44:20 +0530
4Subject: [PATCH 1/2] Resizer and Previewer driver added to commit
5
6The Resizer and Previewer driver added to the commit
7from the patch submitted by Sergio on 12 Dec 2008.
8
9The new WTBU code base and Nokia fixes package doesn't contain
10standalone resizer driver support.
11
12Following major changes done -
13
14 - Added stand-alone resizer driver support
15 in isp.c file.
16 - Seperate Kconfig file created
17 - hardware access of resizer module fixed as per new
18 isp.c
19
20Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
21---
22 drivers/media/video/Kconfig | 5 +-
23 drivers/media/video/isp/Kconfig | 16 +
24 drivers/media/video/isp/Makefile | 7 +
25 drivers/media/video/isp/isp.c | 12 +
26 drivers/media/video/isp/ispmmu.c | 1 +
27 drivers/media/video/isp/omap_previewer.c | 825 +++++++++++++++
28 drivers/media/video/isp/omap_previewer.h | 162 +++
29 drivers/media/video/isp/omap_resizer.c | 1634 ++++++++++++++++++++++++++++++
30 include/linux/omap_resizer.h | 136 +++
31 9 files changed, 2794 insertions(+), 4 deletions(-)
32 create mode 100644 drivers/media/video/isp/Kconfig
33 create mode 100644 drivers/media/video/isp/omap_previewer.c
34 create mode 100644 drivers/media/video/isp/omap_previewer.h
35 create mode 100644 drivers/media/video/isp/omap_resizer.c
36 create mode 100644 include/linux/omap_resizer.h
37
38diff --git a/drivers/media/video/isp/Kconfig b/drivers/media/video/isp/Kconfig
39new file mode 100644
40index 0000000..acda63b
41--- /dev/null
42+++ b/drivers/media/video/isp/Kconfig
43@@ -0,0 +1,16 @@
44+# Kconfig for OMAP3 ISP driver
45+
46+config VIDEO_OMAP3_ISP
47+ tristate
48+ select VIDEOBUF_GEN
49+ select VIDEOBUF_DMA_SG
50+
51+config VIDEO_OMAP34XX_ISP_PREVIEWER
52+ tristate "OMAP ISP Previewer"
53+ depends on !ARCH_OMAP3410
54+ select VIDEO_OMAP3_ISP
55+
56+config VIDEO_OMAP34XX_ISP_RESIZER
57+ tristate "OMAP ISP Resizer"
58+ depends on !ARCH_OMAP3410
59+ select VIDEO_OMAP3_ISP
60diff --git a/drivers/media/video/isp/Makefile b/drivers/media/video/isp/Makefile
61index 0f9301c..ed10a51 100644
62--- a/drivers/media/video/isp/Makefile
63+++ b/drivers/media/video/isp/Makefile
64@@ -7,6 +7,13 @@ else
65 isp-mod-objs += \
66 isp.o ispccdc.o ispmmu.o \
67 isppreview.o ispresizer.o isph3a.o isphist.o isp_af.o ispcsi2.o
68+
69+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER) += \
70+ omap_previewer.o
71+
72+obj-$(CONFIG_VIDEO_OMAP34XX_ISP_RESIZER) += \
73+ omap_resizer.o
74+
75 endif
76
77 obj-$(CONFIG_VIDEO_OMAP3_ISP) += isp-mod.o
78diff --git a/drivers/media/video/isp/isp.c b/drivers/media/video/isp/isp.c
79index 6034a56..09a1792 100644
80--- a/drivers/media/video/isp/isp.c
81+++ b/drivers/media/video/isp/isp.c
82@@ -521,6 +521,13 @@ int isp_set_callback(enum isp_callback_type type, isp_callback_t callback,
83 OMAP3_ISP_IOMEM_MAIN,
84 ISP_IRQ0ENABLE);
85 break;
86+ case CBK_RESZ_DONE:
87+ isp_reg_writel(IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
88+ ISP_IRQ0STATUS);
89+ isp_reg_writel(isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE) |
90+ IRQ0ENABLE_RSZ_DONE_IRQ, OMAP3_ISP_IOMEM_MAIN,
91+ ISP_IRQ0ENABLE);
92+ break;
93 default:
94 break;
95 }
96@@ -996,6 +1003,11 @@ static irqreturn_t omap34xx_isp_isr(int irq, void *_isp)
97 if (!ispresizer_busy())
98 ispresizer_config_shadow_registers();
99 isp_buf_process(bufs);
100+ } else {
101+ if (irqdis->isp_callbk[CBK_RESZ_DONE])
102+ irqdis->isp_callbk[CBK_RESZ_DONE](RESZ_DONE,
103+ irqdis->isp_callbk_arg1[CBK_RESZ_DONE],
104+ irqdis->isp_callbk_arg2[CBK_RESZ_DONE]);
105 }
106 }
107
108diff --git a/drivers/media/video/isp/ispmmu.c b/drivers/media/video/isp/ispmmu.c
109index 076aea1..b943d5b 100644
110--- a/drivers/media/video/isp/ispmmu.c
111+++ b/drivers/media/video/isp/ispmmu.c
112@@ -289,6 +289,7 @@ int ispmmu_get_mapeable_space(void)
113 return (L2P_TABLE_NR - no_of_l2p_alloted) * ISPMMU_TTB_ENTRIES_NR *
114 ISPMMU_L2D_ENTRIES_NR;
115 }
116+EXPORT_SYMBOL_GPL(ispmmu_get_mapeable_space);
117
118 /**
119 * ispmmu_map - Map a physically contiguous buffer to ISP space.
120diff --git a/drivers/media/video/isp/omap_previewer.c b/drivers/media/video/isp/omap_previewer.c
121new file mode 100644
122index 0000000..634a056
123--- /dev/null
124+++ b/drivers/media/video/isp/omap_previewer.c
125@@ -0,0 +1,825 @@
126+/*
127+ * drivers/media/video/isp/omap_previewer.c
128+ *
129+ * Wrapper for Preview module in TI's OMAP3430 ISP
130+ *
131+ * Copyright (C) 2008 Texas Instruments, Inc.
132+ *
133+ * Contributors:
134+ * Leonides Martinez <leonides.martinez@ti.com>
135+ * Sergio Aguirre <saaguirre@ti.com>
136+ *
137+ * This package is free software; you can redistribute it and/or modify
138+ * it under the terms of the GNU General Public License version 2 as
139+ * published by the Free Software Foundation.
140+ *
141+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
142+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
143+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
144+ */
145+
146+#include <linux/mutex.h>
147+#include <linux/cdev.h>
148+#include <linux/device.h>
149+#include <linux/delay.h>
150+#include <linux/fs.h>
151+#include <linux/mm.h>
152+#include <linux/module.h>
153+#include <linux/platform_device.h>
154+#include <linux/uaccess.h>
155+#include <linux/io.h>
156+#include <media/v4l2-dev.h>
157+#include <asm/cacheflush.h>
158+
159+#include "isp.h"
160+#include "ispmmu.h"
161+#include "ispreg.h"
162+#include "omap_previewer.h"
163+
164+#define OMAP_PREV_NAME "omap-previewer"
165+
166+static int prev_major = -1;
167+static struct device *prev_dev;
168+static struct class *prev_class;
169+static struct prev_device *prevdevice;
170+static struct platform_driver omap_previewer_driver;
171+
172+static u32 prev_bufsize;
173+
174+/**
175+ * prev_calculate_crop - Calculate crop size according to device parameters
176+ * @device: Structure containing ISP preview wrapper global information
177+ * @crop: Structure containing crop size
178+ *
179+ * This function is used to calculate frame size reduction depending on
180+ * the features enabled by the application.
181+ **/
182+static void prev_calculate_crop(struct prev_device *device,
183+ struct prev_cropsize *crop)
184+{
185+ dev_dbg(prev_dev, "prev_calculate_crop E\n");
186+
187+ if (!device || !crop) {
188+ dev_err(prev_dev, "\nErron in argument");
189+ return;
190+ }
191+
192+ isppreview_try_size(device->params->size_params.hsize,
193+ device->params->size_params.vsize,
194+ &crop->hcrop, &crop->vcrop);
195+ crop->hcrop &= PREV_16PIX_ALIGN_MASK;
196+ dev_dbg(prev_dev, "prev_calculate_crop L\n");
197+}
198+
199+/**
200+ * prev_get_status - Get status of ISP preview module
201+ * @status: Structure containing the busy state.
202+ *
203+ * Checks if the ISP preview module is busy.
204+ *
205+ * Returns 0 if successful, or -EINVAL if the status parameter is invalid.
206+ **/
207+static int prev_get_status(struct prev_status *status)
208+{
209+ if (!status) {
210+ dev_err(prev_dev, "get_status: invalid parameter\n");
211+ return -EINVAL;
212+ }
213+ status->hw_busy = (char)isppreview_busy();
214+ return 0;
215+}
216+
217+/**
218+ * prev_hw_setup - Stores the desired configuration in the proper HW registers
219+ * @config: Structure containing the desired configuration for ISP preview
220+ * module.
221+ *
222+ * Reads the structure sent, and modifies the desired registers.
223+ *
224+ * Always returns 0.
225+ **/
226+static int prev_hw_setup(struct prev_params *config)
227+{
228+ dev_dbg(prev_dev, "prev_hw_setup E\n");
229+
230+ if (config->features & PREV_AVERAGER)
231+ isppreview_config_averager(config->average);
232+ else
233+ isppreview_config_averager(0);
234+
235+ if (config->features & PREV_INVERSE_ALAW)
236+ isppreview_enable_invalaw(1);
237+ else
238+ isppreview_enable_invalaw(0);
239+
240+ if (config->features & PREV_HORZ_MEDIAN_FILTER) {
241+ isppreview_config_hmed(config->hmf_params);
242+ isppreview_enable_hmed(1);
243+ } else
244+ isppreview_enable_hmed(0);
245+
246+ if (config->features & PREV_DARK_FRAME_SUBTRACT) {
247+ isppreview_set_darkaddr(config->drkf_params.addr);
248+ isppreview_config_darklineoffset(config->drkf_params.offset);
249+ isppreview_enable_drkframe(1);
250+ } else
251+ isppreview_enable_drkframe(0);
252+
253+ if (config->features & PREV_LENS_SHADING) {
254+ isppreview_config_drkf_shadcomp(config->lens_shading_shift);
255+ isppreview_enable_shadcomp(1);
256+ } else
257+ isppreview_enable_shadcomp(0);
258+
259+ dev_dbg(prev_dev, "prev_hw_setup L\n");
260+ return 0;
261+}
262+
263+/**
264+ * prev_validate_params - Validate configuration parameters for Preview Wrapper
265+ * @params: Structure containing configuration parameters
266+ *
267+ * Validate configuration parameters for Preview Wrapper
268+ *
269+ * Returns 0 if successful, or -EINVAL if a parameter value is invalid.
270+ **/
271+static int prev_validate_params(struct prev_params *params)
272+{
273+ if (!params) {
274+ dev_err(prev_dev, "validate_params: error in argument");
275+ goto err_einval;
276+ }
277+
278+ if ((params->features & PREV_AVERAGER) == PREV_AVERAGER) {
279+ if ((params->average != NO_AVE)
280+ && (params->average != AVE_2_PIX)
281+ && (params->average != AVE_4_PIX)
282+ && (params->average != AVE_8_PIX)) {
283+ dev_err(prev_dev, "validate_params: wrong pix "
284+ "average\n");
285+ goto err_einval;
286+ } else if (((params->average == AVE_2_PIX)
287+ && (params->size_params.hsize % 2))
288+ || ((params->average == AVE_4_PIX)
289+ && (params->size_params.hsize % 4))
290+ || ((params->average == AVE_8_PIX)
291+ && (params->size_params.hsize % 8))) {
292+ dev_err(prev_dev, "validate_params: "
293+ "wrong pix average for input size\n");
294+ goto err_einval;
295+ }
296+ }
297+
298+ if ((params->size_params.pixsize != PREV_INWIDTH_8BIT)
299+ && (params->size_params.pixsize
300+ != PREV_INWIDTH_10BIT)) {
301+ dev_err(prev_dev, "validate_params: wrong pixsize\n");
302+ goto err_einval;
303+ }
304+
305+ if (params->size_params.hsize > MAX_IMAGE_WIDTH
306+ || params->size_params.hsize < 0) {
307+ dev_err(prev_dev, "validate_params: wrong hsize\n");
308+ goto err_einval;
309+ }
310+
311+ if ((params->pix_fmt != YCPOS_YCrYCb)
312+ && (YCPOS_YCbYCr != params->pix_fmt)
313+ && (YCPOS_CbYCrY != params->pix_fmt)
314+ && (YCPOS_CrYCbY != params->pix_fmt)) {
315+ dev_err(prev_dev, "validate_params: wrong pix_fmt");
316+ goto err_einval;
317+ }
318+
319+ if ((params->features & PREV_DARK_FRAME_SUBTRACT)
320+ && (params->features
321+ & PREV_DARK_FRAME_CAPTURE)) {
322+ dev_err(prev_dev, "validate_params: DARK FRAME CAPTURE and "
323+ "SUBSTRACT cannot be enabled "
324+ "at same time\n");
325+ goto err_einval;
326+ }
327+
328+ if (params->features & PREV_DARK_FRAME_SUBTRACT)
329+ if (!params->drkf_params.addr
330+ || (params->drkf_params.offset % 32)) {
331+ dev_err(prev_dev, "validate_params: dark frame "
332+ "address\n");
333+ goto err_einval;
334+ }
335+
336+ if (params->features & PREV_LENS_SHADING)
337+ if ((params->lens_shading_shift > 7)
338+ || !params->drkf_params.addr
339+ || (params->drkf_params.offset % 32)) {
340+ dev_err(prev_dev, "validate_params: lens shading "
341+ "shift\n");
342+ goto err_einval;
343+ }
344+
345+ if ((params->size_params.in_pitch <= 0)
346+ || (params->size_params.in_pitch % 32)) {
347+ params->size_params.in_pitch =
348+ (params->size_params.hsize * 2) & 0xFFE0;
349+ dev_err(prev_dev, "\nError in in_pitch; new value = %d",
350+ params->size_params.in_pitch);
351+ }
352+
353+ return 0;
354+err_einval:
355+ return -EINVAL;
356+}
357+
358+/**
359+ * preview_isr - Callback from ISP driver for ISP Preview Interrupt
360+ * @status: ISP IRQ0STATUS register value
361+ * @arg1: Structure containing ISP preview wrapper global information
362+ * @arg2: Currently not used
363+ **/
364+static void preview_isr(unsigned long status, isp_vbq_callback_ptr arg1,
365+ void *arg2)
366+{
367+ struct prev_device *device = (struct prev_device *)arg1;
368+
369+ if ((status & PREV_DONE) != PREV_DONE)
370+ return;
371+
372+ if (device)
373+ complete(&device->wfc);
374+}
375+
376+/**
377+ * prev_do_preview - Performs the Preview process
378+ * @device: Structure containing ISP preview wrapper global information
379+ * @arg: Currently not used
380+ *
381+ * Returns 0 if successful, or -EINVAL if the sent parameters are invalid.
382+ **/
383+static int prev_do_preview(struct prev_device *device, int *arg)
384+{
385+ int bpp, size;
386+ int ret = 0;
387+ u32 out_hsize, out_vsize, out_line_offset;
388+
389+ dev_dbg(prev_dev, "prev_do_preview E\n");
390+
391+ if (!device) {
392+ dev_err(prev_dev, "preview: invalid parameters\n");
393+ return -EINVAL;
394+ }
395+
396+ if (device->params->size_params.pixsize == PREV_INWIDTH_8BIT)
397+ bpp = 1;
398+ else
399+ bpp = 2;
400+
401+ size = device->params->size_params.hsize *
402+ device->params->size_params.vsize * bpp;
403+
404+ ret = isppreview_set_inaddr(device->isp_addr_read);
405+ if (ret)
406+ goto out;
407+
408+ ret = isppreview_set_outaddr(device->isp_addr_read);
409+ if (ret)
410+ goto out;
411+
412+ isppreview_try_size(device->params->size_params.hsize,
413+ device->params->size_params.vsize,
414+ &out_hsize, &out_vsize);
415+
416+ ret = isppreview_config_inlineoffset(device->params->size_params.hsize
417+ * bpp);
418+ if (ret)
419+ goto out;
420+
421+ out_line_offset = (out_hsize * bpp) & PREV_32BYTES_ALIGN_MASK;
422+
423+ ret = isppreview_config_outlineoffset(out_line_offset);
424+ if (ret)
425+ goto out;
426+
427+ ret = isppreview_config_size(device->params->size_params.hsize,
428+ device->params->size_params.vsize,
429+ out_hsize, out_vsize);
430+ if (ret)
431+ goto out;
432+
433+ isppreview_config_datapath(PRV_RAW_MEM, PREVIEW_MEM);
434+
435+ ret = isp_set_callback(CBK_PREV_DONE, preview_isr, (void *)device,
436+ (void *)NULL);
437+ if (ret) {
438+ dev_err(prev_dev, "ERROR while setting Previewer callback!\n");
439+ goto out;
440+ }
441+ isppreview_enable(1);
442+
443+ wait_for_completion_interruptible(&device->wfc);
444+
445+ if (device->isp_addr_read) {
446+ ispmmu_vunmap(device->isp_addr_read);
447+ device->isp_addr_read = 0;
448+ }
449+
450+ ret = isp_unset_callback(CBK_PREV_DONE);
451+
452+ dev_dbg(prev_dev, "prev_do_preview L\n");
453+out:
454+ return ret;
455+}
456+
457+/**
458+ * previewer_vbq_release - Videobuffer queue release
459+ * @q: Structure containing the videobuffer queue.
460+ * @vb: Structure containing the videobuffer used for previewer processing.
461+ **/
462+static void previewer_vbq_release(struct videobuf_queue *q,
463+ struct videobuf_buffer *vb)
464+{
465+ struct prev_fh *fh = q->priv_data;
466+ struct prev_device *device = fh->device;
467+
468+ ispmmu_vunmap(device->isp_addr_read);
469+ device->isp_addr_read = 0;
470+ spin_lock(&device->vbq_lock);
471+ vb->state = VIDEOBUF_NEEDS_INIT;
472+ spin_unlock(&device->vbq_lock);
473+ dev_dbg(prev_dev, "previewer_vbq_release\n");
474+}
475+
476+/**
477+ * previewer_vbq_setup - Sets up the videobuffer size and validates count.
478+ * @q: Structure containing the videobuffer queue.
479+ * @cnt: Number of buffers requested
480+ * @size: Size in bytes of the buffer used for previewing
481+ *
482+ * Always returns 0.
483+ **/
484+static int previewer_vbq_setup(struct videobuf_queue *q,
485+ unsigned int *cnt,
486+ unsigned int *size)
487+{
488+ struct prev_fh *fh = q->priv_data;
489+ struct prev_device *device = fh->device;
490+ u32 bpp = 1;
491+
492+ spin_lock(&device->vbq_lock);
493+ if (*cnt <= 0)
494+ *cnt = VIDEO_MAX_FRAME;
495+
496+ if (*cnt > VIDEO_MAX_FRAME)
497+ *cnt = VIDEO_MAX_FRAME;
498+
499+ if (!device->params->size_params.hsize ||
500+ !device->params->size_params.vsize) {
501+ dev_err(prev_dev, "Can't setup buffer size\n");
502+ spin_unlock(&device->vbq_lock);
503+ return -EINVAL;
504+ }
505+
506+ if (device->params->size_params.pixsize == PREV_INWIDTH_10BIT)
507+ bpp = 2;
508+ *size = prev_bufsize = bpp * device->params->size_params.hsize
509+ * device->params->size_params.vsize;
510+ spin_unlock(&device->vbq_lock);
511+ dev_dbg(prev_dev, "previewer_vbq_setup\n");
512+ return 0;
513+}
514+
515+/**
516+ * previewer_vbq_prepare - Videobuffer is prepared and mmapped.
517+ * @q: Structure containing the videobuffer queue.
518+ * @vb: Structure containing the videobuffer used for previewer processing.
519+ * @field: Type of field to set in videobuffer device.
520+ *
521+ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
522+ * -EIO if the ISP MMU mapping fails
523+ **/
524+static int previewer_vbq_prepare(struct videobuf_queue *q,
525+ struct videobuf_buffer *vb,
526+ enum v4l2_field field)
527+{
528+ struct prev_fh *fh = q->priv_data;
529+ struct prev_device *device = fh->device;
530+ int err = -EINVAL;
531+ unsigned int isp_addr;
532+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
533+
534+ dev_dbg(prev_dev, "previewer_vbq_prepare E\n");
535+ spin_lock(&device->vbq_lock);
536+ if (vb->baddr) {
537+ vb->size = prev_bufsize;
538+ vb->bsize = prev_bufsize;
539+ } else {
540+ spin_unlock(&device->vbq_lock);
541+ dev_err(prev_dev, "No user buffer allocated\n");
542+ goto out;
543+ }
544+
545+ vb->width = device->params->size_params.hsize;
546+ vb->height = device->params->size_params.vsize;
547+ vb->field = field;
548+ spin_unlock(&device->vbq_lock);
549+
550+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
551+ err = videobuf_iolock(q, vb, NULL);
552+ if (!err) {
553+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
554+ if (!isp_addr)
555+ err = -EIO;
556+ else
557+ device->isp_addr_read = isp_addr;
558+ }
559+ }
560+
561+ if (!err) {
562+ vb->state = VIDEOBUF_PREPARED;
563+ flush_cache_user_range(NULL, vb->baddr,
564+ (vb->baddr + vb->bsize));
565+ } else
566+ previewer_vbq_release(q, vb);
567+
568+ dev_dbg(prev_dev, "previewer_vbq_prepare L\n");
569+out:
570+ return err;
571+}
572+
573+static void previewer_vbq_queue(struct videobuf_queue *q,
574+ struct videobuf_buffer *vb)
575+{
576+ return;
577+}
578+
579+/**
580+ * previewer_open - Initializes and opens the Preview Wrapper
581+ * @inode: Inode structure associated with the Preview Wrapper
582+ * @filp: File structure associated with the Preview Wrapper
583+ *
584+ * Returns 0 if successful, -EACCES if its unable to initialize default config,
585+ * -EBUSY if its already opened or the ISP module is not available, or -ENOMEM
586+ * if its unable to allocate the device in kernel space memory.
587+ **/
588+static int previewer_open(struct inode *inode, struct file *filp)
589+{
590+ int ret = 0;
591+ struct prev_device *device = prevdevice;
592+ struct prev_params *config = isppreview_get_config();
593+ struct prev_fh *fh;
594+
595+ if (config == NULL) {
596+ dev_err(prev_dev, "Unable to initialize default config "
597+ "from isppreviewer\n\n");
598+ return -EACCES;
599+ }
600+
601+ if (device->opened || (filp->f_flags & O_NONBLOCK)) {
602+ dev_err(prev_dev, "previewer_open: device is already "
603+ "opened\n");
604+ return -EBUSY;
605+ }
606+
607+ fh = kzalloc(sizeof(struct prev_fh), GFP_KERNEL);
608+ if (NULL == fh)
609+ return -ENOMEM;
610+
611+ isp_get();
612+ ret = isppreview_request();
613+ if (ret) {
614+ isp_put();
615+ dev_err(prev_dev, "Can't acquire isppreview\n");
616+ return ret;
617+ }
618+
619+ device->params = config;
620+ device->opened = 1;
621+
622+ filp->private_data = fh;
623+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
624+ fh->device = device;
625+
626+ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
627+ &device->vbq_lock, fh->type,
628+ V4L2_FIELD_NONE,
629+ sizeof(struct videobuf_buffer), fh);
630+
631+ init_completion(&device->wfc);
632+ device->wfc.done = 0;
633+ mutex_init(&device->prevwrap_mutex);
634+
635+ return 0;
636+}
637+
638+/**
639+ * previewer_release - Releases Preview Wrapper and frees up allocated memory
640+ * @inode: Inode structure associated with the Preview Wrapper
641+ * @filp: File structure associated with the Preview Wrapper
642+ *
643+ * Always returns 0.
644+ **/
645+static int previewer_release(struct inode *inode, struct file *filp)
646+{
647+ struct prev_fh *fh = filp->private_data;
648+ struct prev_device *device = fh->device;
649+ struct videobuf_queue *q = &fh->vbq;
650+
651+ device->opened = 0;
652+ device->params = NULL;
653+ isppreview_free();
654+ videobuf_mmap_free(q);
655+ isp_put();
656+ prev_bufsize = 0;
657+ filp->private_data = NULL;
658+ kfree(fh);
659+
660+ dev_dbg(prev_dev, "previewer_release\n");
661+ return 0;
662+}
663+
664+/**
665+ * previewer_mmap - Memory maps the Preview Wrapper module.
666+ * @file: File structure associated with the Preview Wrapper
667+ * @vma: Virtual memory area structure.
668+ *
669+ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
670+ * function.
671+ **/
672+static int previewer_mmap(struct file *file, struct vm_area_struct *vma)
673+{
674+ struct prev_fh *fh = file->private_data;
675+ dev_dbg(prev_dev, "previewer_mmap\n");
676+
677+ return videobuf_mmap_mapper(&fh->vbq, vma);
678+}
679+
680+/**
681+ * previewer_ioctl - I/O control function for Preview Wrapper
682+ * @inode: Inode structure associated with the Preview Wrapper.
683+ * @file: File structure associated with the Preview Wrapper.
684+ * @cmd: Type of command to execute.
685+ * @arg: Argument to send to requested command.
686+ *
687+ * Returns 0 if successful, -1 if bad command passed or access is denied,
688+ * -EFAULT if copy_from_user() or copy_to_user() fails, -EINVAL if parameter
689+ * validation fails or parameter structure is not present
690+ **/
691+static int previewer_ioctl(struct inode *inode, struct file *file,
692+ unsigned int cmd, unsigned long arg)
693+{
694+ int ret = 0;
695+ struct prev_params params;
696+ struct prev_fh *fh = file->private_data;
697+ struct prev_device *device = fh->device;
698+
699+ dev_dbg(prev_dev, "Entering previewer_ioctl()\n");
700+
701+ if ((_IOC_TYPE(cmd) != PREV_IOC_BASE)
702+ || (_IOC_NR(cmd) > PREV_IOC_MAXNR)) {
703+ dev_err(prev_dev, "Bad command Value \n");
704+ goto err_minusone;
705+ }
706+
707+ if (_IOC_DIR(cmd) & _IOC_READ)
708+ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
709+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
710+ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
711+ if (ret) {
712+ dev_err(prev_dev, "access denied\n");
713+ goto err_minusone;
714+ }
715+
716+ switch (cmd) {
717+ case PREV_REQBUF:
718+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
719+ goto err_eintr;
720+ ret = videobuf_reqbufs(&fh->vbq, (void *)arg);
721+ mutex_unlock(&device->prevwrap_mutex);
722+ break;
723+
724+ case PREV_QUERYBUF:
725+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
726+ goto err_eintr;
727+ ret = videobuf_querybuf(&fh->vbq, (void *)arg);
728+ mutex_unlock(&device->prevwrap_mutex);
729+ break;
730+
731+ case PREV_QUEUEBUF:
732+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
733+ goto err_eintr;
734+ ret = videobuf_qbuf(&fh->vbq, (void *)arg);
735+ mutex_unlock(&device->prevwrap_mutex);
736+ break;
737+
738+ case PREV_SET_PARAM:
739+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
740+ goto err_eintr;
741+ if (copy_from_user(&params, (struct prev_params *)arg,
742+ sizeof(struct prev_params))) {
743+ mutex_unlock(&device->prevwrap_mutex);
744+ return -EFAULT;
745+ }
746+ ret = prev_validate_params(&params);
747+ if (ret < 0) {
748+ dev_err(prev_dev, "Error validating parameters!\n");
749+ mutex_unlock(&device->prevwrap_mutex);
750+ goto out;
751+ }
752+ if (device->params)
753+ memcpy(device->params, &params,
754+ sizeof(struct prev_params));
755+ else {
756+ mutex_unlock(&device->prevwrap_mutex);
757+ return -EINVAL;
758+ }
759+
760+ ret = prev_hw_setup(device->params);
761+ mutex_unlock(&device->prevwrap_mutex);
762+ break;
763+
764+ case PREV_GET_PARAM:
765+ if (copy_to_user((struct prev_params *)arg, device->params,
766+ sizeof(struct prev_params)))
767+ ret = -EFAULT;
768+ break;
769+
770+ case PREV_GET_STATUS:
771+ ret = prev_get_status((struct prev_status *)arg);
772+ break;
773+
774+ case PREV_PREVIEW:
775+ if (mutex_lock_interruptible(&device->prevwrap_mutex))
776+ goto err_eintr;
777+ ret = prev_do_preview(device, (int *)arg);
778+ mutex_unlock(&device->prevwrap_mutex);
779+ break;
780+
781+ case PREV_GET_CROPSIZE:
782+ {
783+ struct prev_cropsize outputsize;
784+ prev_calculate_crop(device, &outputsize);
785+ if (copy_to_user((struct prev_cropsize *)arg, &outputsize,
786+ sizeof(struct prev_cropsize)))
787+ ret = -EFAULT;
788+ }
789+ break;
790+
791+ default:
792+ dev_err(prev_dev, "previewer_ioctl: Invalid Command Value\n");
793+ ret = -EINVAL;
794+ }
795+out:
796+ return ret;
797+err_minusone:
798+ return -1;
799+err_eintr:
800+ return -EINTR;
801+}
802+
803+/**
804+ * previewer_platform_release - Acts when Reference count is zero
805+ * @device: Structure containing ISP preview wrapper global information
806+ *
807+ * This is called when the reference count goes to zero
808+ **/
809+static void previewer_platform_release(struct device *device)
810+{
811+ dev_dbg(prev_dev, "previewer_platform_release()\n");
812+}
813+
814+static struct file_operations prev_fops = {
815+ .owner = THIS_MODULE,
816+ .open = previewer_open,
817+ .release = previewer_release,
818+ .mmap = previewer_mmap,
819+ .ioctl = previewer_ioctl,
820+};
821+
822+static struct platform_device omap_previewer_device = {
823+ .name = OMAP_PREV_NAME,
824+ .id = -1,
825+ .dev = {
826+ .release = previewer_platform_release,
827+ }
828+};
829+
830+/**
831+ * previewer_probe - Checks for device presence
832+ * @pdev: Structure containing details of the current device.
833+ *
834+ * Always returns 0
835+ **/
836+static int __init previewer_probe(struct platform_device *pdev)
837+{
838+ return 0;
839+}
840+
841+/**
842+ * previewer_remove - Handles the removal of the driver
843+ * @pdev: Structure containing details of the current device.
844+ *
845+ * Always returns 0.
846+ **/
847+static int previewer_remove(struct platform_device *pdev)
848+{
849+ dev_dbg(prev_dev, "previewer_remove()\n");
850+
851+ platform_device_unregister(&omap_previewer_device);
852+ platform_driver_unregister(&omap_previewer_driver);
853+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
854+ return 0;
855+}
856+
857+static struct platform_driver omap_previewer_driver = {
858+ .probe = previewer_probe,
859+ .remove = previewer_remove,
860+ .driver = {
861+ .owner = THIS_MODULE,
862+ .name = OMAP_PREV_NAME,
863+ },
864+};
865+
866+/**
867+ * omap_previewer_init - Initialization of Preview Wrapper
868+ *
869+ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
870+ * could not register the wrapper as a character device, or other errors if the
871+ * device or driver can't register.
872+ **/
873+static int __init omap_previewer_init(void)
874+{
875+ int ret;
876+ struct prev_device *device;
877+
878+ device = kzalloc(sizeof(struct prev_device), GFP_KERNEL);
879+ if (!device) {
880+ dev_err(prev_dev, OMAP_PREV_NAME ": could not allocate"
881+ " memory\n");
882+ return -ENOMEM;
883+ }
884+ prev_major = register_chrdev(0, OMAP_PREV_NAME, &prev_fops);
885+
886+ if (prev_major < 0) {
887+ dev_err(prev_dev, OMAP_PREV_NAME ": initialization "
888+ "failed. could not register character "
889+ "device\n");
890+ return -ENODEV;
891+ }
892+
893+ ret = platform_driver_register(&omap_previewer_driver);
894+ if (ret) {
895+ dev_err(prev_dev, OMAP_PREV_NAME
896+ ": failed to register platform driver!\n");
897+ goto fail2;
898+ }
899+ ret = platform_device_register(&omap_previewer_device);
900+ if (ret) {
901+ dev_err(prev_dev, OMAP_PREV_NAME
902+ ": failed to register platform device!\n");
903+ goto fail3;
904+ }
905+
906+ prev_class = class_create(THIS_MODULE, OMAP_PREV_NAME);
907+ if (!prev_class)
908+ goto fail4;
909+
910+ prev_dev = device_create(prev_class, prev_dev,
911+ (MKDEV(prev_major, 0)), NULL,
912+ OMAP_PREV_NAME);
913+ dev_dbg(prev_dev, OMAP_PREV_NAME ": Registered Previewer Wrapper\n");
914+ device->opened = 0;
915+
916+ device->vbq_ops.buf_setup = previewer_vbq_setup;
917+ device->vbq_ops.buf_prepare = previewer_vbq_prepare;
918+ device->vbq_ops.buf_release = previewer_vbq_release;
919+ device->vbq_ops.buf_queue = previewer_vbq_queue;
920+ spin_lock_init(&device->vbq_lock);
921+
922+ prevdevice = device;
923+ return 0;
924+
925+fail4:
926+ platform_device_unregister(&omap_previewer_device);
927+fail3:
928+ platform_driver_unregister(&omap_previewer_driver);
929+fail2:
930+ unregister_chrdev(prev_major, OMAP_PREV_NAME);
931+
932+ return ret;
933+}
934+
935+/**
936+ * omap_previewer_exit - Close of Preview Wrapper
937+ **/
938+static void __exit omap_previewer_exit(void)
939+{
940+ previewer_remove(&omap_previewer_device);
941+ kfree(prevdevice);
942+ prev_major = -1;
943+}
944+
945+module_init(omap_previewer_init);
946+module_exit(omap_previewer_exit);
947+
948+MODULE_AUTHOR("Texas Instruments");
949+MODULE_DESCRIPTION("OMAP ISP Previewer");
950+MODULE_LICENSE("GPL");
951diff --git a/drivers/media/video/isp/omap_previewer.h b/drivers/media/video/isp/omap_previewer.h
952new file mode 100644
953index 0000000..0bb31cd
954--- /dev/null
955+++ b/drivers/media/video/isp/omap_previewer.h
956@@ -0,0 +1,162 @@
957+/*
958+ * drivers/media/video/isp/omap_previewer.h
959+ *
960+ * Header file for Preview module wrapper in TI's OMAP3430 ISP
961+ *
962+ * Copyright (C) 2008 Texas Instruments, Inc.
963+ *
964+ * Contributors:
965+ * Leonides Martinez <leonides.martinez@ti.com>
966+ * Sergio Aguirre <saaguirre@ti.com>
967+ *
968+ * This package is free software; you can redistribute it and/or modify
969+ * it under the terms of the GNU General Public License version 2 as
970+ * published by the Free Software Foundation.
971+ *
972+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
973+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
974+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
975+ */
976+
977+#include "isppreview.h"
978+
979+#ifndef OMAP_ISP_PREVIEW_WRAP_H
980+#define OMAP_ISP_PREVIEW_WRAP_H
981+
982+#define PREV_IOC_BASE 'P'
983+#define PREV_REQBUF _IOWR(PREV_IOC_BASE, 1,\
984+ struct v4l2_requestbuffers)
985+#define PREV_QUERYBUF _IOWR(PREV_IOC_BASE, 2,\
986+ struct v4l2_buffer)
987+#define PREV_SET_PARAM _IOW(PREV_IOC_BASE, 3,\
988+ struct prev_params)
989+#define PREV_GET_PARAM _IOWR(PREV_IOC_BASE, 4,\
990+ struct prev_params)
991+#define PREV_PREVIEW _IOR(PREV_IOC_BASE, 5, int)
992+#define PREV_GET_STATUS _IOR(PREV_IOC_BASE, 6, char)
993+#define PREV_GET_CROPSIZE _IOR(PREV_IOC_BASE, 7,\
994+ struct prev_cropsize)
995+#define PREV_QUEUEBUF _IOWR(PREV_IOC_BASE, 8,\
996+ struct v4l2_buffer)
997+#define PREV_IOC_MAXNR 8
998+
999+#define LUMA_TABLE_SIZE 128
1000+#define GAMMA_TABLE_SIZE 1024
1001+#define CFA_COEFF_TABLE_SIZE 576
1002+#define NOISE_FILTER_TABLE_SIZE 256
1003+
1004+#define MAX_IMAGE_WIDTH 3300
1005+
1006+#define PREV_INWIDTH_8BIT 0 /* pixel width of 8 bits */
1007+#define PREV_INWIDTH_10BIT 1 /* pixel width of 10 bits */
1008+
1009+#define PREV_32BYTES_ALIGN_MASK 0xFFFFFFE0
1010+#define PREV_16PIX_ALIGN_MASK 0xFFFFFFF0
1011+
1012+/**
1013+ * struct prev_rgbblending - Structure for RGB2RGB blending parameters
1014+ * @blending: Color correlation 3x3 matrix.
1015+ * @offset: Color correlation offsets.
1016+ */
1017+struct prev_rgbblending {
1018+ short blending[RGB_MAX][RGB_MAX]; /* color correlation 3x3
1019+ * matrix.
1020+ */
1021+ short offset[RGB_MAX]; /* color correlation offsets */
1022+};
1023+
1024+/**
1025+ * struct prev_cfa_coeffs - Structure for CFA coefficients
1026+ * @hthreshold: Horizontal threshold.
1027+ * @vthreshold: Vertical threshold.
1028+ * @coeffs: CFA coefficients
1029+ */
1030+struct prev_cfa_coeffs {
1031+ char hthreshold, vthreshold;
1032+ int coeffs[CFA_COEFF_TABLE_SIZE];
1033+};
1034+
1035+/**
1036+ * struct prev_gamma_coeffs - Structure for Gamma Coefficients
1037+ * @red: Table of gamma correction values for red color.
1038+ * @green: Table of gamma correction values for green color.
1039+ * @blue: Table of gamma correction values for blue color.
1040+ */
1041+struct prev_gamma_coeffs {
1042+ unsigned char red[GAMMA_TABLE_SIZE];
1043+ unsigned char green[GAMMA_TABLE_SIZE];
1044+ unsigned char blue[GAMMA_TABLE_SIZE];
1045+};
1046+
1047+/**
1048+ * struct prev_noiseflt_coeffs - Structure for Noise Filter Coefficients.
1049+ * @noise: Noise filter table.
1050+ * @strength: Used to find out weighted average.
1051+ */
1052+struct prev_noiseflt_coeffs {
1053+ unsigned char noise[NOISE_FILTER_TABLE_SIZE];
1054+ unsigned char strength;
1055+};
1056+
1057+/**
1058+ * struct prev_chroma_spr - Structure for Chroma Suppression.
1059+ * @hpfy: High passed version of Y or normal Y.
1060+ * @threshold: Threshold for chroma suppress.
1061+ * @gain: Chroma suppression gain
1062+ */
1063+struct prev_chroma_spr {
1064+ unsigned char hpfy;
1065+ char threshold;
1066+ unsigned char gain;
1067+};
1068+
1069+/**
1070+ * struct prev_status - Structure to know status of the hardware
1071+ * @hw_busy: Flag to indicate if Hardware is Busy.
1072+ */
1073+struct prev_status {
1074+ char hw_busy;
1075+};
1076+
1077+/**
1078+ * struct prev_cropsize - Structure to know crop size.
1079+ * @hcrop: Horizontal size of crop window.
1080+ * @vcrop: Vertical size of crop window.
1081+ */
1082+struct prev_cropsize {
1083+ int hcrop;
1084+ int vcrop;
1085+};
1086+
1087+/**
1088+ * struct prev_device - Global device information structure.
1089+ * @params: Pointer to structure containing preview parameters.
1090+ * @opened: State of the device.
1091+ * @wfc: Wait for completion. Used for locking operations.
1092+ * @prevwrap_mutex: Mutex for preview wrapper use.
1093+ * @vbq_lock: Spinlock for videobuf queues.
1094+ * @vbq_ops: Videobuf queue operations
1095+ * @isp_addr_read: Input/Output address
1096+ */
1097+struct prev_device {
1098+ struct prev_params *params;
1099+ unsigned char opened;
1100+ struct completion wfc;
1101+ struct mutex prevwrap_mutex; /* For generic internal use */
1102+ spinlock_t vbq_lock; /* For videobuffer queue handling */
1103+ struct videobuf_queue_ops vbq_ops;
1104+ dma_addr_t isp_addr_read;
1105+};
1106+
1107+/**
1108+ * struct prev_fh - Per-filehandle data structure
1109+ * @type: Used buffer type.
1110+ * @vbq: Videobuffer queue.
1111+ * @device: Pointer to device information structure.
1112+ */
1113+struct prev_fh {
1114+ enum v4l2_buf_type type;
1115+ struct videobuf_queue vbq;
1116+ struct prev_device *device;
1117+};
1118+#endif
1119diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
1120new file mode 100644
1121index 0000000..54bc425
1122--- /dev/null
1123+++ b/drivers/media/video/isp/omap_resizer.c
1124@@ -0,0 +1,1634 @@
1125+/*
1126+ * drivers/media/video/isp/omap_resizer.c
1127+ *
1128+ * Wrapper for Resizer module in TI's OMAP3430 ISP
1129+ *
1130+ * Copyright (C) 2008 Texas Instruments, Inc.
1131+ *
1132+ * Contributors:
1133+ * Sergio Aguirre <saaguirre@ti.com>
1134+ * Troy Laramy <t-laramy@ti.com>
1135+ *
1136+ * This package is free software; you can redistribute it and/or modify
1137+ * it under the terms of the GNU General Public License version 2 as
1138+ * published by the Free Software Foundation.
1139+ *
1140+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1141+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1142+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1143+ */
1144+
1145+#include <linux/mutex.h>
1146+#include <linux/cdev.h>
1147+#include <linux/delay.h>
1148+#include <linux/device.h>
1149+#include <linux/fs.h>
1150+#include <linux/mm.h>
1151+#include <linux/module.h>
1152+#include <linux/platform_device.h>
1153+#include <linux/io.h>
1154+#include <linux/uaccess.h>
1155+#include <media/v4l2-dev.h>
1156+#include <asm/cacheflush.h>
1157+
1158+#include "isp.h"
1159+#include "ispmmu.h"
1160+#include "ispreg.h"
1161+#include "ispresizer.h"
1162+#include <linux/omap_resizer.h>
1163+
1164+#define OMAP_REZR_NAME "omap-resizer"
1165+
1166+/* Defines and Constants*/
1167+#define MAX_CHANNELS 16
1168+#define MAX_IMAGE_WIDTH 2047
1169+#define MAX_IMAGE_WIDTH_HIGH 2047
1170+#define ALIGNMENT 16
1171+#define CHANNEL_BUSY 1
1172+#define CHANNEL_FREE 0
1173+#define PIXEL_EVEN 2
1174+#define RATIO_MULTIPLIER 256
1175+/* Bit position Macro */
1176+/* macro for bit set and clear */
1177+#define BITSET(variable, bit) ((variable) | (1 << bit))
1178+#define BITRESET(variable, bit) ((variable) & ~(0x00000001 << (bit)))
1179+#define SET_BIT_INPUTRAM 28
1180+#define SET_BIT_CBLIN 29
1181+#define SET_BIT_INPTYP 27
1182+#define SET_BIT_YCPOS 26
1183+#define INPUT_RAM 1
1184+#define UP_RSZ_RATIO 64
1185+#define DOWN_RSZ_RATIO 512
1186+#define UP_RSZ_RATIO1 513
1187+#define DOWN_RSZ_RATIO1 1024
1188+#define RSZ_IN_SIZE_VERT_SHIFT 16
1189+#define MAX_HORZ_PIXEL_8BIT 31
1190+#define MAX_HORZ_PIXEL_16BIT 15
1191+#define NUM_PHASES 8
1192+#define NUM_TAPS 4
1193+#define NUM_D2PH 4 /* for downsampling * 2+x ~ 4x,
1194+ * number of phases
1195+ */
1196+#define NUM_D2TAPS 7 /* for downsampling * 2+x ~ 4x,
1197+ * number of taps
1198+ */
1199+#define ALIGN32 32
1200+#define MAX_COEF_COUNTER 16
1201+#define COEFF_ADDRESS_OFFSET 0x04
1202+
1203+/* Global structure which contains information about number of channels
1204+ and protection variables */
1205+struct device_params {
1206+
1207+ unsigned char opened; /* state of the device */
1208+ struct completion compl_isr; /* Completion for interrupt */
1209+ struct mutex reszwrap_mutex; /* Semaphore for array */
1210+
1211+ struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
1212+};
1213+
1214+/* Register mapped structure which contains the every register
1215+ information */
1216+struct resizer_config {
1217+ u32 rsz_pcr; /* pcr register mapping
1218+ * variable.
1219+ */
1220+ u32 rsz_in_start; /* in_start register mapping
1221+ * variable.
1222+ */
1223+ u32 rsz_in_size; /* in_size register mapping
1224+ * variable.
1225+ */
1226+ u32 rsz_out_size; /* out_size register mapping
1227+ * variable.
1228+ */
1229+ u32 rsz_cnt; /* rsz_cnt register mapping
1230+ * variable.
1231+ */
1232+ u32 rsz_sdr_inadd; /* sdr_inadd register mapping
1233+ * variable.
1234+ */
1235+ u32 rsz_sdr_inoff; /* sdr_inoff register mapping
1236+ * variable.
1237+ */
1238+ u32 rsz_sdr_outadd; /* sdr_outadd register mapping
1239+ * variable.
1240+ */
1241+ u32 rsz_sdr_outoff; /* sdr_outbuff register
1242+ * mapping variable.
1243+ */
1244+ u32 rsz_coeff_horz[16]; /* horizontal coefficients
1245+ * mapping array.
1246+ */
1247+ u32 rsz_coeff_vert[16]; /* vertical coefficients
1248+ * mapping array.
1249+ */
1250+ u32 rsz_yehn; /* yehn(luma)register mapping
1251+ * variable.
1252+ */
1253+};
1254+
1255+struct rsz_mult {
1256+ int in_hsize; /* input frame horizontal
1257+ * size.
1258+ */
1259+ int in_vsize; /* input frame vertical size.
1260+ */
1261+ int out_hsize; /* output frame horizontal
1262+ * size.
1263+ */
1264+ int out_vsize; /* output frame vertical
1265+ * size.
1266+ */
1267+ int in_pitch; /* offset between two rows of
1268+ * input frame.
1269+ */
1270+ int out_pitch; /* offset between two rows of
1271+ * output frame.
1272+ */
1273+ int end_hsize;
1274+ int end_vsize;
1275+ int num_htap; /* 0 = 7tap; 1 = 4tap */
1276+ int num_vtap; /* 0 = 7tap; 1 = 4tap */
1277+ int active;
1278+ int inptyp;
1279+ int vrsz;
1280+ int hrsz;
1281+ int hstph; /* for specifying horizontal
1282+ * starting phase.
1283+ */
1284+ int vstph;
1285+ int pix_fmt; /* # defined, UYVY or YUYV. */
1286+ int cbilin; /* # defined, filter with luma
1287+ * or bi-linear.
1288+ */
1289+ u16 tap4filt_coeffs[32]; /* horizontal filter
1290+ * coefficients.
1291+ */
1292+ u16 tap7filt_coeffs[32]; /* vertical filter
1293+ * coefficients.
1294+ */
1295+};
1296+/* Channel specific structure contains information regarding
1297+ the every channel */
1298+struct channel_config {
1299+ struct resizer_config register_config; /* Instance of register set
1300+ * mapping structure
1301+ */
1302+ int status; /* Specifies whether the
1303+ * channel is busy or not
1304+ */
1305+ struct mutex chanprotection_mutex;
1306+ enum config_done config_state;
1307+ u8 input_buf_index;
1308+ u8 output_buf_index;
1309+
1310+};
1311+
1312+/* per-filehandle data structure */
1313+struct rsz_fh {
1314+ struct rsz_params *params;
1315+ struct channel_config *config;
1316+ struct rsz_mult *multipass; /* Multipass to support
1317+ * resizing ration outside
1318+ * of 0.25x to 4x
1319+ */
1320+ spinlock_t vbq_lock; /* spinlock for videobuf
1321+ * queues.
1322+ */
1323+ enum v4l2_buf_type type;
1324+ struct videobuf_queue vbq;
1325+ struct device_params *device;
1326+
1327+ dma_addr_t isp_addr_read; /* Input/Output address */
1328+ dma_addr_t isp_addr_write; /* Input/Output address */
1329+ u32 rsz_bufsize; /* channel specific buffersize
1330+ */
1331+};
1332+
1333+static struct device_params *device_config;
1334+static struct device *rsz_device;
1335+static int rsz_major = -1;
1336+/* functions declaration */
1337+static void rsz_hardware_setup(struct channel_config *rsz_conf_chan);
1338+static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *,
1339+ struct channel_config *);
1340+static int rsz_get_params(struct rsz_params *, struct channel_config *);
1341+static void rsz_copy_data(struct rsz_mult *multipass,
1342+ struct rsz_params *params);
1343+static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1,
1344+ void *arg2);
1345+static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
1346+ struct rsz_cropsize *cropsize);
1347+static int rsz_set_multipass(struct rsz_mult *multipass,
1348+ struct channel_config *rsz_conf_chan);
1349+static int rsz_set_ratio(struct rsz_mult *multipass,
1350+ struct channel_config *rsz_conf_chan);
1351+static void rsz_config_ratio(struct rsz_mult *multipass,
1352+ struct channel_config *rsz_conf_chan);
1353+
1354+/**
1355+ * rsz_hardware_setup - Sets hardware configuration registers
1356+ * @rsz_conf_chan: Structure containing channel configuration
1357+ *
1358+ * Set hardware configuration registers
1359+ **/
1360+static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
1361+{
1362+ int coeffcounter;
1363+ int coeffoffset = 0;
1364+
1365+ omap_writel(rsz_conf_chan->register_config.rsz_cnt,
1366+ OMAP3ISP_RESZ_REG(ISPRSZ_CNT));
1367+
1368+ omap_writel(rsz_conf_chan->register_config.rsz_in_start,
1369+ OMAP3ISP_RESZ_REG(ISPRSZ_IN_START));
1370+ omap_writel(rsz_conf_chan->register_config.rsz_in_size,
1371+ OMAP3ISP_RESZ_REG(ISPRSZ_IN_SIZE));
1372+
1373+ omap_writel(rsz_conf_chan->register_config.rsz_out_size,
1374+ OMAP3ISP_RESZ_REG(ISPRSZ_OUT_SIZE));
1375+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inadd,
1376+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INADD));
1377+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_inoff,
1378+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_INOFF));
1379+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outadd,
1380+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTADD));
1381+ omap_writel(rsz_conf_chan->register_config.rsz_sdr_outoff,
1382+ OMAP3ISP_RESZ_REG(ISPRSZ_SDR_OUTOFF));
1383+ omap_writel(rsz_conf_chan->register_config.rsz_yehn, OMAP3ISP_RESZ_REG(ISPRSZ_YENH));
1384+
1385+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
1386+ coeffcounter++) {
1387+ omap_writel(rsz_conf_chan->register_config.
1388+ rsz_coeff_horz[coeffcounter],
1389+ OMAP3ISP_RESZ_REG(ISPRSZ_HFILT10
1390+ + coeffoffset));
1391+
1392+ omap_writel(rsz_conf_chan->register_config.
1393+ rsz_coeff_vert[coeffcounter],
1394+ OMAP3ISP_RESZ_REG(ISPRSZ_VFILT10
1395+ + coeffoffset));
1396+ coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
1397+ }
1398+}
1399+
1400+/**
1401+ * rsz_start - Enables Resizer Wrapper
1402+ * @arg: Currently not used.
1403+ * @device: Structure containing ISP resizer wrapper global information
1404+ *
1405+ * Submits a resizing task specified by the rsz_resize structure. The call can
1406+ * either be blocked until the task is completed or returned immediately based
1407+ * on the value of the blocking argument in the rsz_resize structure. If it is
1408+ * blocking, the status of the task can be checked by calling ioctl
1409+ * RSZ_G_STATUS. Only one task can be outstanding for each logical channel.
1410+ *
1411+ * Returns 0 if successful, or -EINVAL if could not set callback for RSZR IRQ
1412+ * event or the state of the channel is not configured.
1413+ **/
1414+int rsz_start(int *arg, struct rsz_fh *fh)
1415+{
1416+ struct channel_config *rsz_conf_chan = fh->config;
1417+ struct rsz_mult *multipass = fh->multipass;
1418+ struct videobuf_queue *q = &fh->vbq;
1419+ int ret;
1420+
1421+ if (rsz_conf_chan->config_state) {
1422+ dev_err(rsz_device, "State not configured \n");
1423+ goto err_einval;
1424+ }
1425+
1426+ rsz_conf_chan->status = CHANNEL_BUSY;
1427+
1428+ rsz_hardware_setup(rsz_conf_chan);
1429+
1430+ if (isp_set_callback(CBK_RESZ_DONE, rsz_isr, (void *) NULL,
1431+ (void *)NULL)) {
1432+ dev_err(rsz_device, "No callback for RSZR\n");
1433+ goto err_einval;
1434+ }
1435+mult:
1436+ device_config->compl_isr.done = 0;
1437+
1438+ ispresizer_enable(1);
1439+
1440+ ret = wait_for_completion_interruptible(&device_config->compl_isr);
1441+ if (ret != 0) {
1442+ dev_dbg(rsz_device, "Unexpected exit from "
1443+ "wait_for_completion_interruptible\n");
1444+ wait_for_completion(&device_config->compl_isr);
1445+ }
1446+
1447+ if (multipass->active) {
1448+ rsz_set_multipass(multipass, rsz_conf_chan);
1449+ goto mult;
1450+ }
1451+
1452+ if (fh->isp_addr_read) {
1453+ ispmmu_vunmap(fh->isp_addr_read);
1454+ fh->isp_addr_read = 0;
1455+ }
1456+ if (fh->isp_addr_write) {
1457+ ispmmu_vunmap(fh->isp_addr_write);
1458+ fh->isp_addr_write = 0;
1459+ }
1460+
1461+ rsz_conf_chan->status = CHANNEL_FREE;
1462+ q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
1463+ q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
1464+ rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
1465+ rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
1466+
1467+ /* Unmap and free the DMA memory allocated for buffers */
1468+ videobuf_dma_unmap(q, videobuf_to_dma(
1469+ q->bufs[rsz_conf_chan->input_buf_index]));
1470+ videobuf_dma_unmap(q, videobuf_to_dma(
1471+ q->bufs[rsz_conf_chan->output_buf_index]));
1472+ videobuf_dma_free(videobuf_to_dma(
1473+ q->bufs[rsz_conf_chan->input_buf_index]));
1474+ videobuf_dma_free(videobuf_to_dma(
1475+ q->bufs[rsz_conf_chan->output_buf_index]));
1476+
1477+ isp_unset_callback(CBK_RESZ_DONE);
1478+
1479+ return 0;
1480+err_einval:
1481+ return -EINVAL;
1482+}
1483+
1484+/**
1485+ * rsz_set_multipass - Set resizer multipass
1486+ * @rsz_conf_chan: Structure containing channel configuration
1487+ *
1488+ * Returns always 0
1489+ **/
1490+static int rsz_set_multipass(struct rsz_mult *multipass,
1491+ struct channel_config *rsz_conf_chan)
1492+{
1493+ multipass->in_hsize = multipass->out_hsize;
1494+ multipass->in_vsize = multipass->out_vsize;
1495+ multipass->out_hsize = multipass->end_hsize;
1496+ multipass->out_vsize = multipass->end_vsize;
1497+
1498+ multipass->out_pitch = (multipass->inptyp ? multipass->out_hsize
1499+ : (multipass->out_hsize * 2));
1500+ multipass->in_pitch = (multipass->inptyp ? multipass->in_hsize
1501+ : (multipass->in_hsize * 2));
1502+
1503+ rsz_set_ratio(multipass, rsz_conf_chan);
1504+ rsz_config_ratio(multipass, rsz_conf_chan);
1505+ rsz_hardware_setup(rsz_conf_chan);
1506+ return 0;
1507+}
1508+
1509+/**
1510+ * rsz_copy_data - Copy data
1511+ * @params: Structure containing the Resizer Wrapper parameters
1512+ *
1513+ * Copy data
1514+ **/
1515+static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
1516+{
1517+ int i;
1518+ multipass->in_hsize = params->in_hsize;
1519+ multipass->in_vsize = params->in_vsize;
1520+ multipass->out_hsize = params->out_hsize;
1521+ multipass->out_vsize = params->out_vsize;
1522+ multipass->end_hsize = params->out_hsize;
1523+ multipass->end_vsize = params->out_vsize;
1524+ multipass->in_pitch = params->in_pitch;
1525+ multipass->out_pitch = params->out_pitch;
1526+ multipass->hstph = params->hstph;
1527+ multipass->vstph = params->vstph;
1528+ multipass->inptyp = params->inptyp;
1529+ multipass->pix_fmt = params->pix_fmt;
1530+ multipass->cbilin = params->cbilin;
1531+
1532+ for (i = 0; i < 32; i++) {
1533+ multipass->tap4filt_coeffs[i] = params->tap4filt_coeffs[i];
1534+ multipass->tap7filt_coeffs[i] = params->tap7filt_coeffs[i];
1535+ }
1536+}
1537+
1538+/**
1539+ * rsz_set_params - Set parameters for resizer wrapper
1540+ * @params: Structure containing the Resizer Wrapper parameters
1541+ * @rsz_conf_chan: Structure containing channel configuration
1542+ *
1543+ * Used to set the parameters of the Resizer hardware, including input and
1544+ * output image size, horizontal and vertical poly-phase filter coefficients,
1545+ * luma enchancement filter coefficients, etc.
1546+ **/
1547+static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
1548+ struct channel_config *rsz_conf_chan)
1549+{
1550+ int mul = 1;
1551+ if ((params->yenh_params.type < 0) || (params->yenh_params.type > 2)) {
1552+ dev_err(rsz_device, "rsz_set_params: Wrong yenh type\n");
1553+ return -EINVAL;
1554+ }
1555+ if ((params->in_vsize <= 0) || (params->in_hsize <= 0) ||
1556+ (params->out_vsize <= 0) || (params->out_hsize <= 0) ||
1557+ (params->in_pitch <= 0) || (params->out_pitch <= 0)) {
1558+ dev_err(rsz_device, "rsz_set_params: Invalid size params\n");
1559+ return -EINVAL;
1560+ }
1561+ if ((params->inptyp != RSZ_INTYPE_YCBCR422_16BIT) &&
1562+ (params->inptyp != RSZ_INTYPE_PLANAR_8BIT)) {
1563+ dev_err(rsz_device, "rsz_set_params: Invalid input type\n");
1564+ return -EINVAL;
1565+ }
1566+ if ((params->pix_fmt != RSZ_PIX_FMT_UYVY) &&
1567+ (params->pix_fmt != RSZ_PIX_FMT_YUYV)) {
1568+ dev_err(rsz_device, "rsz_set_params: Invalid pixel format\n");
1569+ return -EINVAL;
1570+ }
1571+ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
1572+ mul = 2;
1573+ else
1574+ mul = 1;
1575+ if (params->in_pitch < (params->in_hsize * mul)) {
1576+ dev_err(rsz_device, "rsz_set_params: Pitch is incorrect\n");
1577+ return -EINVAL;
1578+ }
1579+ if (params->out_pitch < (params->out_hsize * mul)) {
1580+ dev_err(rsz_device, "rsz_set_params: Out pitch cannot be less"
1581+ " than out hsize\n");
1582+ return -EINVAL;
1583+ }
1584+ /* Output H size should be even */
1585+ if ((params->out_hsize % PIXEL_EVEN) != 0) {
1586+ dev_err(rsz_device, "rsz_set_params: Output H size should"
1587+ " be even\n");
1588+ return -EINVAL;
1589+ }
1590+ if (params->horz_starting_pixel < 0) {
1591+ dev_err(rsz_device, "rsz_set_params: Horz start pixel cannot"
1592+ " be less than zero\n");
1593+ return -EINVAL;
1594+ }
1595+
1596+ rsz_copy_data(multipass, params);
1597+ if (0 != rsz_set_ratio(multipass, rsz_conf_chan))
1598+ goto err_einval;
1599+
1600+ if (params->yenh_params.type) {
1601+ if ((multipass->num_htap && multipass->out_hsize >
1602+ 1280) ||
1603+ (!multipass->num_htap && multipass->out_hsize >
1604+ 640))
1605+ goto err_einval;
1606+ }
1607+
1608+ if (INPUT_RAM)
1609+ params->vert_starting_pixel = 0;
1610+
1611+ rsz_conf_chan->register_config.rsz_in_start =
1612+ (params->vert_starting_pixel
1613+ << ISPRSZ_IN_SIZE_VERT_SHIFT)
1614+ & ISPRSZ_IN_SIZE_VERT_MASK;
1615+
1616+ if (params->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
1617+ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_8BIT)
1618+ goto err_einval;
1619+ }
1620+ if (params->inptyp == RSZ_INTYPE_YCBCR422_16BIT) {
1621+ if (params->horz_starting_pixel > MAX_HORZ_PIXEL_16BIT)
1622+ goto err_einval;
1623+ }
1624+
1625+ rsz_conf_chan->register_config.rsz_in_start |=
1626+ params->horz_starting_pixel
1627+ & ISPRSZ_IN_START_HORZ_ST_MASK;
1628+
1629+ rsz_conf_chan->register_config.rsz_yehn =
1630+ (params->yenh_params.type
1631+ << ISPRSZ_YENH_ALGO_SHIFT)
1632+ & ISPRSZ_YENH_ALGO_MASK;
1633+
1634+ if (params->yenh_params.type) {
1635+ rsz_conf_chan->register_config.rsz_yehn |=
1636+ params->yenh_params.core
1637+ & ISPRSZ_YENH_CORE_MASK;
1638+
1639+ rsz_conf_chan->register_config.rsz_yehn |=
1640+ (params->yenh_params.gain
1641+ << ISPRSZ_YENH_GAIN_SHIFT)
1642+ & ISPRSZ_YENH_GAIN_MASK;
1643+
1644+ rsz_conf_chan->register_config.rsz_yehn |=
1645+ (params->yenh_params.slop
1646+ << ISPRSZ_YENH_SLOP_SHIFT)
1647+ & ISPRSZ_YENH_SLOP_MASK;
1648+ }
1649+
1650+ rsz_config_ratio(multipass, rsz_conf_chan);
1651+
1652+ rsz_conf_chan->config_state = STATE_CONFIGURED;
1653+
1654+ return 0;
1655+err_einval:
1656+ return -EINVAL;
1657+}
1658+
1659+/**
1660+ * rsz_set_ratio - Set ratio
1661+ * @rsz_conf_chan: Structure containing channel configuration
1662+ *
1663+ * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
1664+ * being requested, or other ratio configuration value is out of bounds
1665+ **/
1666+static int rsz_set_ratio(struct rsz_mult *multipass,
1667+ struct channel_config *rsz_conf_chan)
1668+{
1669+ int alignment = 0;
1670+
1671+ rsz_conf_chan->register_config.rsz_cnt = 0;
1672+
1673+ if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
1674+ (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
1675+ dev_err(rsz_device, "Invalid output size!");
1676+ goto err_einval;
1677+ }
1678+ if (multipass->cbilin) {
1679+ rsz_conf_chan->register_config.rsz_cnt =
1680+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1681+ SET_BIT_CBLIN);
1682+ }
1683+ if (INPUT_RAM) {
1684+ rsz_conf_chan->register_config.rsz_cnt =
1685+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1686+ SET_BIT_INPUTRAM);
1687+ }
1688+ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT) {
1689+ rsz_conf_chan->register_config.rsz_cnt =
1690+ BITSET(rsz_conf_chan->register_config.rsz_cnt,
1691+ SET_BIT_INPTYP);
1692+ } else {
1693+ rsz_conf_chan->register_config.rsz_cnt =
1694+ BITRESET(rsz_conf_chan->register_config.
1695+ rsz_cnt, SET_BIT_INPTYP);
1696+
1697+ if (multipass->pix_fmt == RSZ_PIX_FMT_UYVY) {
1698+ rsz_conf_chan->register_config.rsz_cnt =
1699+ BITRESET(rsz_conf_chan->register_config.
1700+ rsz_cnt, SET_BIT_YCPOS);
1701+ } else if (multipass->pix_fmt == RSZ_PIX_FMT_YUYV) {
1702+ rsz_conf_chan->register_config.rsz_cnt =
1703+ BITSET(rsz_conf_chan->register_config.
1704+ rsz_cnt, SET_BIT_YCPOS);
1705+ }
1706+
1707+ }
1708+ multipass->vrsz =
1709+ (multipass->in_vsize * RATIO_MULTIPLIER) / multipass->out_vsize;
1710+ multipass->hrsz =
1711+ (multipass->in_hsize * RATIO_MULTIPLIER) / multipass->out_hsize;
1712+ if (UP_RSZ_RATIO > multipass->vrsz || UP_RSZ_RATIO > multipass->hrsz) {
1713+ dev_err(rsz_device, "Upscaling ratio not supported!");
1714+ goto err_einval;
1715+ }
1716+ multipass->vrsz = (multipass->in_vsize - NUM_D2TAPS) * RATIO_MULTIPLIER
1717+ / (multipass->out_vsize - 1);
1718+ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
1719+ * RATIO_MULTIPLIER) /
1720+ (multipass->out_hsize - 1);
1721+
1722+ if (multipass->hrsz <= 512) {
1723+ multipass->hrsz = (multipass->in_hsize - NUM_TAPS)
1724+ * RATIO_MULTIPLIER
1725+ / (multipass->out_hsize - 1);
1726+ if (multipass->hrsz < 64)
1727+ multipass->hrsz = 64;
1728+ if (multipass->hrsz > 512)
1729+ multipass->hrsz = 512;
1730+ if (multipass->hstph > NUM_PHASES)
1731+ goto err_einval;
1732+ multipass->num_htap = 1;
1733+ } else if (multipass->hrsz >= 513 && multipass->hrsz <= 1024) {
1734+ if (multipass->hstph > NUM_D2PH)
1735+ goto err_einval;
1736+ multipass->num_htap = 0;
1737+ }
1738+
1739+ if (multipass->vrsz <= 512) {
1740+ multipass->vrsz = (multipass->in_vsize - NUM_TAPS)
1741+ * RATIO_MULTIPLIER
1742+ / (multipass->out_vsize - 1);
1743+ if (multipass->vrsz < 64)
1744+ multipass->vrsz = 64;
1745+ if (multipass->vrsz > 512)
1746+ multipass->vrsz = 512;
1747+ if (multipass->vstph > NUM_PHASES)
1748+ goto err_einval;
1749+ multipass->num_vtap = 1;
1750+ } else if (multipass->vrsz >= 513 && multipass->vrsz <= 1024) {
1751+ if (multipass->vstph > NUM_D2PH)
1752+ goto err_einval;
1753+ multipass->num_vtap = 0;
1754+ }
1755+
1756+ if ((multipass->in_pitch) % ALIGN32) {
1757+ dev_err(rsz_device, "Invalid input pitch: %d \n",
1758+ multipass->in_pitch);
1759+ goto err_einval;
1760+ }
1761+ if ((multipass->out_pitch) % ALIGN32) {
1762+ dev_err(rsz_device, "Invalid output pitch %d \n",
1763+ multipass->out_pitch);
1764+ goto err_einval;
1765+ }
1766+
1767+ if (multipass->vrsz < 256 &&
1768+ (multipass->in_vsize < multipass->out_vsize)) {
1769+ if (multipass->inptyp == RSZ_INTYPE_PLANAR_8BIT)
1770+ alignment = ALIGNMENT;
1771+ else if (multipass->inptyp == RSZ_INTYPE_YCBCR422_16BIT)
1772+ alignment = (ALIGNMENT / 2);
1773+ else
1774+ dev_err(rsz_device, "Invalid input type\n");
1775+
1776+ if (!(((multipass->out_hsize % PIXEL_EVEN) == 0)
1777+ && (multipass->out_hsize % alignment) == 0)) {
1778+ dev_err(rsz_device, "wrong hsize\n");
1779+ goto err_einval;
1780+ }
1781+ }
1782+ if (multipass->hrsz >= 64 && multipass->hrsz <= 1024) {
1783+ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
1784+ dev_err(rsz_device, "wrong width\n");
1785+ goto err_einval;
1786+ }
1787+ multipass->active = 0;
1788+
1789+ } else if (multipass->hrsz > 1024) {
1790+ if (multipass->out_hsize > MAX_IMAGE_WIDTH) {
1791+ dev_err(rsz_device, "wrong width\n");
1792+ goto err_einval;
1793+ }
1794+ if (multipass->hstph > NUM_D2PH)
1795+ goto err_einval;
1796+ multipass->num_htap = 0;
1797+ multipass->out_hsize = multipass->in_hsize * 256 / 1024;
1798+ if (multipass->out_hsize % ALIGN32) {
1799+ multipass->out_hsize +=
1800+ abs((multipass->out_hsize % ALIGN32) - ALIGN32);
1801+ }
1802+ multipass->out_pitch = ((multipass->inptyp) ?
1803+ multipass->out_hsize :
1804+ (multipass->out_hsize * 2));
1805+ multipass->hrsz = ((multipass->in_hsize - NUM_D2TAPS)
1806+ * RATIO_MULTIPLIER)
1807+ / (multipass->out_hsize - 1);
1808+ multipass->active = 1;
1809+
1810+ }
1811+
1812+ if (multipass->vrsz > 1024) {
1813+ if (multipass->out_vsize > MAX_IMAGE_WIDTH_HIGH) {
1814+ dev_err(rsz_device, "wrong width\n");
1815+ goto err_einval;
1816+ }
1817+
1818+ multipass->out_vsize = multipass->in_vsize * 256 / 1024;
1819+ multipass->vrsz = ((multipass->in_vsize - NUM_D2TAPS)
1820+ * RATIO_MULTIPLIER)
1821+ / (multipass->out_vsize - 1);
1822+ multipass->active = 1;
1823+ multipass->num_vtap = 0;
1824+
1825+ }
1826+ rsz_conf_chan->register_config.rsz_out_size =
1827+ multipass->out_hsize
1828+ & ISPRSZ_OUT_SIZE_HORZ_MASK;
1829+
1830+ rsz_conf_chan->register_config.rsz_out_size |=
1831+ (multipass->out_vsize
1832+ << ISPRSZ_OUT_SIZE_VERT_SHIFT)
1833+ & ISPRSZ_OUT_SIZE_VERT_MASK;
1834+
1835+ rsz_conf_chan->register_config.rsz_sdr_inoff =
1836+ multipass->in_pitch
1837+ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
1838+
1839+ rsz_conf_chan->register_config.rsz_sdr_outoff =
1840+ multipass->out_pitch
1841+ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
1842+
1843+ if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
1844+ if (multipass->hstph > NUM_PHASES)
1845+ goto err_einval;
1846+ } else if (multipass->hrsz >= 64 && multipass->hrsz <= 512) {
1847+ if (multipass->hstph > NUM_D2PH)
1848+ goto err_einval;
1849+ }
1850+
1851+ rsz_conf_chan->register_config.rsz_cnt |=
1852+ (multipass->hstph
1853+ << ISPRSZ_CNT_HSTPH_SHIFT)
1854+ & ISPRSZ_CNT_HSTPH_MASK;
1855+
1856+ if (multipass->vrsz >= 64 && multipass->hrsz <= 512) {
1857+ if (multipass->vstph > NUM_PHASES)
1858+ goto err_einval;
1859+ } else if (multipass->vrsz >= 64 && multipass->vrsz <= 512) {
1860+ if (multipass->vstph > NUM_D2PH)
1861+ goto err_einval;
1862+ }
1863+
1864+ rsz_conf_chan->register_config.rsz_cnt |=
1865+ (multipass->vstph
1866+ << ISPRSZ_CNT_VSTPH_SHIFT)
1867+ & ISPRSZ_CNT_VSTPH_MASK;
1868+
1869+ rsz_conf_chan->register_config.rsz_cnt |=
1870+ (multipass->hrsz - 1)
1871+ & ISPRSZ_CNT_HRSZ_MASK;
1872+
1873+ rsz_conf_chan->register_config.rsz_cnt |=
1874+ ((multipass->vrsz - 1)
1875+ << ISPRSZ_CNT_VRSZ_SHIFT)
1876+ & ISPRSZ_CNT_VRSZ_MASK;
1877+
1878+ return 0;
1879+err_einval:
1880+ return -EINVAL;
1881+}
1882+
1883+/**
1884+ * rsz_config_ratio - Configure ratio
1885+ * @rsz_conf_chan: Structure containing channel configuration
1886+ *
1887+ * Configure ratio
1888+ **/
1889+static void rsz_config_ratio(struct rsz_mult *multipass,
1890+ struct channel_config *rsz_conf_chan)
1891+{
1892+ int hsize;
1893+ int vsize;
1894+ int coeffcounter;
1895+
1896+ if (multipass->hrsz <= 512) {
1897+ hsize = ((32 * multipass->hstph + (multipass->out_hsize - 1)
1898+ * multipass->hrsz + 16) >> 8) + 7;
1899+ } else {
1900+ hsize = ((64 * multipass->hstph + (multipass->out_hsize - 1)
1901+ * multipass->hrsz + 32) >> 8) + 7;
1902+ }
1903+ if (multipass->vrsz <= 512) {
1904+ vsize = ((32 * multipass->vstph + (multipass->out_vsize - 1)
1905+ * multipass->vrsz + 16) >> 8) + 4;
1906+ } else {
1907+ vsize = ((64 * multipass->vstph + (multipass->out_vsize - 1)
1908+ * multipass->vrsz + 32) >> 8) + 7;
1909+ }
1910+ rsz_conf_chan->register_config.rsz_in_size = hsize;
1911+
1912+ rsz_conf_chan->register_config.rsz_in_size |=
1913+ ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
1914+ & ISPRSZ_IN_SIZE_VERT_MASK);
1915+
1916+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
1917+ coeffcounter++) {
1918+ if (multipass->num_htap) {
1919+ rsz_conf_chan->register_config.
1920+ rsz_coeff_horz[coeffcounter] =
1921+ (multipass->tap4filt_coeffs[2
1922+ * coeffcounter]
1923+ & ISPRSZ_HFILT10_COEF0_MASK);
1924+ rsz_conf_chan->register_config.
1925+ rsz_coeff_horz[coeffcounter] |=
1926+ ((multipass->tap4filt_coeffs[2
1927+ * coeffcounter + 1]
1928+ << ISPRSZ_HFILT10_COEF1_SHIFT)
1929+ & ISPRSZ_HFILT10_COEF1_MASK);
1930+ } else {
1931+ rsz_conf_chan->register_config.
1932+ rsz_coeff_horz[coeffcounter] =
1933+ (multipass->tap7filt_coeffs[2
1934+ * coeffcounter]
1935+ & ISPRSZ_HFILT10_COEF0_MASK);
1936+
1937+ rsz_conf_chan->register_config.
1938+ rsz_coeff_horz[coeffcounter] |=
1939+ ((multipass->tap7filt_coeffs[2
1940+ * coeffcounter + 1]
1941+ << ISPRSZ_HFILT10_COEF1_SHIFT)
1942+ & ISPRSZ_HFILT10_COEF1_MASK);
1943+ }
1944+
1945+ if (multipass->num_vtap) {
1946+ rsz_conf_chan->register_config.
1947+ rsz_coeff_vert[coeffcounter] =
1948+ (multipass->tap4filt_coeffs[2
1949+ * coeffcounter]
1950+ & ISPRSZ_VFILT10_COEF0_MASK);
1951+
1952+ rsz_conf_chan->register_config.
1953+ rsz_coeff_vert[coeffcounter] |=
1954+ ((multipass->tap4filt_coeffs[2
1955+ * coeffcounter + 1]
1956+ << ISPRSZ_VFILT10_COEF1_SHIFT) &
1957+ ISPRSZ_VFILT10_COEF1_MASK);
1958+ } else {
1959+ rsz_conf_chan->register_config.
1960+ rsz_coeff_vert[coeffcounter] =
1961+ (multipass->tap7filt_coeffs[2
1962+ * coeffcounter]
1963+ & ISPRSZ_VFILT10_COEF0_MASK);
1964+ rsz_conf_chan->register_config.
1965+ rsz_coeff_vert[coeffcounter] |=
1966+ ((multipass->tap7filt_coeffs[2
1967+ * coeffcounter + 1]
1968+ << ISPRSZ_VFILT10_COEF1_SHIFT)
1969+ & ISPRSZ_VFILT10_COEF1_MASK);
1970+ }
1971+ }
1972+}
1973+
1974+/**
1975+ * rsz_get_params - Gets the parameter values
1976+ * @params: Structure containing the Resizer Wrapper parameters
1977+ * @rsz_conf_chan: Structure containing channel configuration
1978+ *
1979+ * Used to get the Resizer hardware settings associated with the
1980+ * current logical channel represented by fd.
1981+ **/
1982+static int rsz_get_params(struct rsz_params *params,
1983+ struct channel_config *rsz_conf_chan)
1984+{
1985+ int coeffcounter;
1986+
1987+ if (rsz_conf_chan->config_state) {
1988+ dev_err(rsz_device, "state not configured\n");
1989+ return -EINVAL;
1990+ }
1991+
1992+ params->in_hsize = rsz_conf_chan->register_config.rsz_in_size
1993+ & ISPRSZ_IN_SIZE_HORZ_MASK;
1994+ params->in_vsize = (rsz_conf_chan->register_config.rsz_in_size
1995+ & ISPRSZ_IN_SIZE_VERT_MASK)
1996+ >> ISPRSZ_IN_SIZE_VERT_SHIFT;
1997+
1998+ params->in_pitch = rsz_conf_chan->register_config.rsz_sdr_inoff
1999+ & ISPRSZ_SDR_INOFF_OFFSET_MASK;
2000+
2001+ params->out_hsize = rsz_conf_chan->register_config.rsz_out_size
2002+ & ISPRSZ_OUT_SIZE_HORZ_MASK;
2003+
2004+ params->out_vsize = (rsz_conf_chan->register_config.rsz_out_size
2005+ & ISPRSZ_OUT_SIZE_VERT_MASK)
2006+ >> ISPRSZ_OUT_SIZE_VERT_SHIFT;
2007+
2008+ params->out_pitch = rsz_conf_chan->register_config.rsz_sdr_outoff
2009+ & ISPRSZ_SDR_OUTOFF_OFFSET_MASK;
2010+
2011+ params->cbilin = (rsz_conf_chan->register_config.rsz_cnt
2012+ & SET_BIT_CBLIN) >> SET_BIT_CBLIN;
2013+
2014+ params->inptyp = (rsz_conf_chan->register_config.rsz_cnt
2015+ & ISPRSZ_CNT_INPTYP_MASK)
2016+ >> SET_BIT_INPTYP;
2017+ params->horz_starting_pixel = ((rsz_conf_chan->register_config.
2018+ rsz_in_start
2019+ & ISPRSZ_IN_START_HORZ_ST_MASK));
2020+ params->vert_starting_pixel = ((rsz_conf_chan->register_config.
2021+ rsz_in_start
2022+ & ISPRSZ_IN_START_VERT_ST_MASK)
2023+ >> ISPRSZ_IN_START_VERT_ST_SHIFT);
2024+
2025+ params->hstph = ((rsz_conf_chan->register_config.rsz_cnt
2026+ & ISPRSZ_CNT_HSTPH_MASK
2027+ >> ISPRSZ_CNT_HSTPH_SHIFT));
2028+ params->vstph = ((rsz_conf_chan->register_config.rsz_cnt
2029+ & ISPRSZ_CNT_VSTPH_MASK
2030+ >> ISPRSZ_CNT_VSTPH_SHIFT));
2031+
2032+ for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
2033+ coeffcounter++) {
2034+ params->tap4filt_coeffs[2 * coeffcounter] =
2035+ rsz_conf_chan->register_config.
2036+ rsz_coeff_horz[coeffcounter]
2037+ & ISPRSZ_HFILT10_COEF0_MASK;
2038+
2039+ params->tap4filt_coeffs[2 * coeffcounter + 1] =
2040+ (rsz_conf_chan->register_config.
2041+ rsz_coeff_horz[coeffcounter]
2042+ & ISPRSZ_HFILT10_COEF1_MASK)
2043+ >> ISPRSZ_HFILT10_COEF1_SHIFT;
2044+
2045+ params->tap7filt_coeffs[2 * coeffcounter] =
2046+ rsz_conf_chan->register_config.
2047+ rsz_coeff_vert[coeffcounter]
2048+ & ISPRSZ_VFILT10_COEF0_MASK;
2049+
2050+ params->tap7filt_coeffs[2 * coeffcounter + 1] =
2051+ (rsz_conf_chan->register_config.
2052+ rsz_coeff_vert[coeffcounter]
2053+ & ISPRSZ_VFILT10_COEF1_MASK)
2054+ >> ISPRSZ_VFILT10_COEF1_SHIFT;
2055+
2056+ }
2057+
2058+ params->yenh_params.type = (rsz_conf_chan->register_config.rsz_yehn
2059+ & ISPRSZ_YENH_ALGO_MASK)
2060+ >> ISPRSZ_YENH_ALGO_SHIFT;
2061+
2062+ params->yenh_params.core = rsz_conf_chan->register_config.rsz_yehn
2063+ & ISPRSZ_YENH_CORE_MASK;
2064+
2065+ params->yenh_params.gain = (rsz_conf_chan->register_config.rsz_yehn
2066+ & ISPRSZ_YENH_GAIN_MASK)
2067+ >> ISPRSZ_YENH_GAIN_SHIFT;
2068+
2069+ params->yenh_params.slop = (rsz_conf_chan->register_config.rsz_yehn
2070+ & ISPRSZ_YENH_SLOP_MASK)
2071+ >> ISPRSZ_YENH_SLOP_SHIFT;
2072+
2073+ params->pix_fmt = ((rsz_conf_chan->register_config.rsz_cnt
2074+ & ISPRSZ_CNT_PIXFMT_MASK)
2075+ >> SET_BIT_YCPOS);
2076+
2077+ if (params->pix_fmt)
2078+ params->pix_fmt = RSZ_PIX_FMT_UYVY;
2079+ else
2080+ params->pix_fmt = RSZ_PIX_FMT_YUYV;
2081+
2082+ return 0;
2083+}
2084+
2085+/**
2086+ * rsz_calculate_crop - Calculate Crop values
2087+ * @rsz_conf_chan: Structure containing channel configuration
2088+ * @cropsize: Structure containing crop parameters
2089+ *
2090+ * Calculate Crop values
2091+ **/
2092+static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
2093+ struct rsz_cropsize *cropsize)
2094+{
2095+ int luma_enable;
2096+
2097+ cropsize->hcrop = 0;
2098+ cropsize->vcrop = 0;
2099+
2100+ luma_enable = (rsz_conf_chan->register_config.rsz_yehn
2101+ & ISPRSZ_YENH_ALGO_MASK)
2102+ >> ISPRSZ_YENH_ALGO_SHIFT;
2103+
2104+ if (luma_enable)
2105+ cropsize->hcrop += 2;
2106+}
2107+
2108+/**
2109+ * rsz_vbq_release - Videobuffer queue release
2110+ * @q: Structure containing the videobuffer queue file handle, and device
2111+ * structure which contains the actual configuration.
2112+ * @vb: Structure containing the videobuffer used for resizer processing.
2113+ **/
2114+static void rsz_vbq_release(struct videobuf_queue *q,
2115+ struct videobuf_buffer *vb)
2116+{
2117+ int i;
2118+ struct rsz_fh *fh = q->priv_data;
2119+
2120+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
2121+ struct videobuf_dmabuf *dma = NULL;
2122+ if (!q->bufs[i])
2123+ continue;
2124+ if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
2125+ continue;
2126+ dma = videobuf_to_dma(q->bufs[i]);
2127+ videobuf_dma_unmap(q, dma);
2128+ videobuf_dma_free(dma);
2129+ }
2130+
2131+ ispmmu_vunmap(fh->isp_addr_read);
2132+ ispmmu_vunmap(fh->isp_addr_write);
2133+ fh->isp_addr_read = 0;
2134+ fh->isp_addr_write = 0;
2135+ spin_lock(&fh->vbq_lock);
2136+ vb->state = VIDEOBUF_NEEDS_INIT;
2137+ spin_unlock(&fh->vbq_lock);
2138+
2139+}
2140+
2141+/**
2142+ * rsz_vbq_setup - Sets up the videobuffer size and validates count.
2143+ * @q: Structure containing the videobuffer queue file handle, and device
2144+ * structure which contains the actual configuration.
2145+ * @cnt: Number of buffers requested
2146+ * @size: Size in bytes of the buffer used for previewing
2147+ *
2148+ * Always returns 0.
2149+ **/
2150+static int rsz_vbq_setup(struct videobuf_queue *q, unsigned int *cnt,
2151+ unsigned int *size)
2152+{
2153+ struct rsz_fh *fh = q->priv_data;
2154+ struct rsz_mult *multipass = fh->multipass;
2155+ u32 insize, outsize;
2156+
2157+ spin_lock(&fh->vbq_lock);
2158+ if (*cnt <= 0)
2159+ *cnt = VIDEO_MAX_FRAME;
2160+
2161+ if (*cnt > VIDEO_MAX_FRAME)
2162+ *cnt = VIDEO_MAX_FRAME;
2163+
2164+ outsize = multipass->out_pitch * multipass->out_vsize;
2165+ insize = multipass->in_pitch * multipass->in_vsize;
2166+ if (*cnt == 1 && (outsize > insize)) {
2167+ dev_err(rsz_device, "2 buffers are required for Upscaling "
2168+ "mode\n");
2169+ goto err_einval;
2170+ }
2171+ if (!fh->params->in_hsize || !fh->params->in_vsize) {
2172+ dev_err(rsz_device, "Can't setup buffer size\n");
2173+ goto err_einval;
2174+ } else {
2175+ if (outsize > insize)
2176+ *size = outsize;
2177+ else
2178+ *size = insize;
2179+
2180+ fh->rsz_bufsize = *size;
2181+ }
2182+ spin_unlock(&fh->vbq_lock);
2183+
2184+ return 0;
2185+err_einval:
2186+ spin_unlock(&fh->vbq_lock);
2187+ return -EINVAL;
2188+}
2189+
2190+/**
2191+ * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
2192+ * @q: Structure containing the videobuffer queue file handle, and device
2193+ * structure which contains the actual configuration.
2194+ * @vb: Structure containing the videobuffer used for resizer processing.
2195+ * @field: Type of field to set in videobuffer device.
2196+ *
2197+ * Returns 0 if successful, or -EINVAL if buffer couldn't get allocated, or
2198+ * -EIO if the ISP MMU mapping fails
2199+ **/
2200+static int rsz_vbq_prepare(struct videobuf_queue *q,
2201+ struct videobuf_buffer *vb,
2202+ enum v4l2_field field)
2203+{
2204+ struct rsz_fh *fh = q->priv_data;
2205+ struct channel_config *rsz_conf_chan = fh->config;
2206+ struct rsz_mult *multipass = fh->multipass;
2207+ int err = 0;
2208+ unsigned int isp_addr, insize, outsize;
2209+ struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
2210+
2211+ spin_lock(&fh->vbq_lock);
2212+ if (vb->baddr) {
2213+ vb->size = fh->rsz_bufsize;
2214+ vb->bsize = fh->rsz_bufsize;
2215+ } else {
2216+ spin_unlock(&fh->vbq_lock);
2217+ dev_err(rsz_device, "No user buffer allocated\n");
2218+ goto out;
2219+ }
2220+ if (vb->i) {
2221+ vb->width = fh->params->out_hsize;
2222+ vb->height = fh->params->out_vsize;
2223+ } else {
2224+ vb->width = fh->params->in_hsize;
2225+ vb->height = fh->params->in_vsize;
2226+ }
2227+
2228+ vb->field = field;
2229+ spin_unlock(&fh->vbq_lock);
2230+
2231+ if (vb->state == VIDEOBUF_NEEDS_INIT) {
2232+ err = videobuf_iolock(q, vb, NULL);
2233+ if (!err) {
2234+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
2235+ if (!isp_addr)
2236+ err = -EIO;
2237+ else {
2238+ if (vb->i) {
2239+ rsz_conf_chan->register_config.
2240+ rsz_sdr_outadd
2241+ = isp_addr;
2242+ fh->isp_addr_write = isp_addr;
2243+ rsz_conf_chan->output_buf_index = vb->i;
2244+ } else {
2245+ rsz_conf_chan->register_config.
2246+ rsz_sdr_inadd
2247+ = isp_addr;
2248+ rsz_conf_chan->input_buf_index = vb->i;
2249+ outsize = multipass->out_pitch *
2250+ multipass->out_vsize;
2251+ insize = multipass->in_pitch *
2252+ multipass->in_vsize;
2253+ if (outsize < insize) {
2254+ rsz_conf_chan->register_config.
2255+ rsz_sdr_outadd
2256+ = isp_addr;
2257+ rsz_conf_chan->
2258+ output_buf_index =
2259+ vb->i;
2260+ }
2261+
2262+ fh->isp_addr_read = isp_addr;
2263+ }
2264+ }
2265+ }
2266+
2267+ }
2268+
2269+ if (!err) {
2270+ spin_lock(&fh->vbq_lock);
2271+ vb->state = VIDEOBUF_PREPARED;
2272+ spin_unlock(&fh->vbq_lock);
2273+ flush_cache_user_range(NULL, vb->baddr, (vb->baddr
2274+ + vb->bsize));
2275+ } else
2276+ rsz_vbq_release(q, vb);
2277+
2278+out:
2279+ return err;
2280+}
2281+
2282+static void rsz_vbq_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
2283+{
2284+ return;
2285+}
2286+
2287+/**
2288+ * rsz_open - Initializes and opens the Resizer Wrapper
2289+ * @inode: Inode structure associated with the Resizer Wrapper
2290+ * @filp: File structure associated with the Resizer Wrapper
2291+ *
2292+ * Returns 0 if successful, -EBUSY if its already opened or the ISP module is
2293+ * not available, or -ENOMEM if its unable to allocate the device in kernel
2294+ * space memory.
2295+ **/
2296+static int rsz_open(struct inode *inode, struct file *filp)
2297+{
2298+ int ret = 0;
2299+ struct channel_config *rsz_conf_chan;
2300+ struct rsz_fh *fh;
2301+ struct device_params *device = device_config;
2302+ struct rsz_params *params;
2303+ struct rsz_mult *multipass;
2304+
2305+ if ((filp->f_flags & O_NONBLOCK) == O_NONBLOCK) {
2306+ printk(KERN_DEBUG "omap-resizer: Device is opened in "
2307+ "non blocking mode\n");
2308+ } else {
2309+ printk(KERN_DEBUG "omap-resizer: Device is opened in blocking "
2310+ "mode\n");
2311+ }
2312+ fh = kzalloc(sizeof(struct rsz_fh), GFP_KERNEL);
2313+ if (NULL == fh)
2314+ return -ENOMEM;
2315+
2316+ isp_get();
2317+
2318+ rsz_conf_chan = kzalloc(sizeof(struct channel_config), GFP_KERNEL);
2319+ if (rsz_conf_chan == NULL) {
2320+ dev_err(rsz_device, "\n cannot allocate memory to config");
2321+ ret = -ENOMEM;
2322+ goto err_enomem0;
2323+ }
2324+ params = kzalloc(sizeof(struct rsz_params), GFP_KERNEL);
2325+ if (params == NULL) {
2326+ dev_err(rsz_device, "\n cannot allocate memory to params");
2327+ ret = -ENOMEM;
2328+ goto err_enomem1;
2329+ }
2330+ multipass = kzalloc(sizeof(struct rsz_mult), GFP_KERNEL);
2331+ if (multipass == NULL) {
2332+ dev_err(rsz_device, "\n cannot allocate memory to multipass");
2333+ ret = -ENOMEM;
2334+ goto err_enomem2;
2335+ }
2336+
2337+ fh->multipass = multipass;
2338+ fh->params = params;
2339+ fh->config = rsz_conf_chan;
2340+
2341+ if (mutex_lock_interruptible(&device->reszwrap_mutex)) {
2342+ ret = -EINTR;
2343+ goto err_enomem2;
2344+ }
2345+ device->opened++;
2346+ mutex_unlock(&device->reszwrap_mutex);
2347+
2348+ rsz_conf_chan->config_state = STATE_NOT_CONFIGURED;
2349+ rsz_conf_chan->status = CHANNEL_FREE;
2350+
2351+ filp->private_data = fh;
2352+ fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2353+ fh->device = device;
2354+
2355+ videobuf_queue_sg_init(&fh->vbq, &device->vbq_ops, NULL,
2356+ &fh->vbq_lock, fh->type,
2357+ V4L2_FIELD_NONE,
2358+ sizeof(struct videobuf_buffer), fh);
2359+
2360+ spin_lock_init(&fh->vbq_lock);
2361+ mutex_init(&rsz_conf_chan->chanprotection_mutex);
2362+
2363+ return 0;
2364+err_enomem2:
2365+ kfree(params);
2366+err_enomem1:
2367+ kfree(rsz_conf_chan);
2368+err_enomem0:
2369+ kfree(fh);
2370+ return ret;
2371+}
2372+
2373+/**
2374+ * rsz_release - Releases Resizer Wrapper and frees up allocated memory
2375+ * @inode: Inode structure associated with the Resizer Wrapper
2376+ * @filp: File structure associated with the Resizer Wrapper
2377+ *
2378+ * Returns 0 if successful, or -EBUSY if channel is being used.
2379+ **/
2380+static int rsz_release(struct inode *inode, struct file *filp)
2381+{
2382+ u32 timeout = 0;
2383+ struct rsz_fh *fh = filp->private_data;
2384+ struct channel_config *rsz_conf_chan = fh->config;
2385+ struct rsz_params *params = fh->params;
2386+ struct rsz_mult *multipass = fh->multipass;
2387+ struct videobuf_queue *q = &fh->vbq;
2388+
2389+ while ((rsz_conf_chan->status != CHANNEL_FREE) && (timeout < 20)) {
2390+ timeout++;
2391+ schedule();
2392+ }
2393+ if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
2394+ return -EINTR;
2395+ device_config->opened--;
2396+ mutex_unlock(&device_config->reszwrap_mutex);
2397+ /* This will Free memory allocated to the buffers,
2398+ * and flushes the queue
2399+ */
2400+ videobuf_queue_cancel(q);
2401+ fh->params = NULL;
2402+ fh->config = NULL;
2403+
2404+ fh->rsz_bufsize = 0;
2405+ filp->private_data = NULL;
2406+
2407+ kfree(rsz_conf_chan);
2408+ kfree(params);
2409+ kfree(multipass);
2410+ kfree(fh);
2411+
2412+ isp_put();
2413+
2414+ return 0;
2415+}
2416+
2417+/**
2418+ * rsz_mmap - Memory maps the Resizer Wrapper module.
2419+ * @file: File structure associated with the Resizer Wrapper
2420+ * @vma: Virtual memory area structure.
2421+ *
2422+ * Returns 0 if successful, or returned value by the videobuf_mmap_mapper()
2423+ * function.
2424+ **/
2425+static int rsz_mmap(struct file *file, struct vm_area_struct *vma)
2426+{
2427+ struct rsz_fh *fh = file->private_data;
2428+
2429+ return videobuf_mmap_mapper(&fh->vbq, vma);
2430+}
2431+
2432+/**
2433+ * rsz_ioctl - I/O control function for Resizer Wrapper
2434+ * @inode: Inode structure associated with the Resizer Wrapper.
2435+ * @file: File structure associated with the Resizer Wrapper.
2436+ * @cmd: Type of command to execute.
2437+ * @arg: Argument to send to requested command.
2438+ *
2439+ * Returns 0 if successful, -EBUSY if channel is being used, -1 if bad command
2440+ * passed or access is denied, -EFAULT if copy_from_user() or copy_to_user()
2441+ * fails, -EINVAL if parameter validation fails or parameter structure is not
2442+ * present.
2443+ **/
2444+static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
2445+ unsigned long arg)
2446+{
2447+ int ret = 0;
2448+ struct rsz_fh *fh = file->private_data;
2449+ struct device_params *device = fh->device;
2450+ struct channel_config *rsz_conf_chan = fh->config;
2451+
2452+ if ((_IOC_TYPE(cmd) != RSZ_IOC_BASE)
2453+ || (_IOC_NR(cmd) > RSZ_IOC_MAXNR)) {
2454+ dev_err(rsz_device, "Bad command value \n");
2455+ return -1;
2456+ }
2457+
2458+ if (_IOC_DIR(cmd) & _IOC_READ)
2459+ ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
2460+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
2461+ ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
2462+
2463+ if (ret) {
2464+ dev_err(rsz_device, "Access denied\n");
2465+ return -1;
2466+ }
2467+
2468+ switch (cmd) {
2469+ case RSZ_REQBUF:
2470+ {
2471+ struct v4l2_requestbuffers req_buf;
2472+ if (copy_from_user(&req_buf, (struct v4l2_requestbuffers *)arg,
2473+ sizeof(struct v4l2_requestbuffers))) {
2474+ return -EFAULT;
2475+ }
2476+ if (mutex_lock_interruptible(&rsz_conf_chan->
2477+ chanprotection_mutex))
2478+ return -EINTR;
2479+ ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
2480+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2481+ break;
2482+ }
2483+ case RSZ_QUERYBUF:
2484+ {
2485+ struct v4l2_buffer buf;
2486+ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
2487+ sizeof(struct v4l2_buffer))) {
2488+ return -EFAULT;
2489+ }
2490+ if (mutex_lock_interruptible(&rsz_conf_chan->
2491+ chanprotection_mutex))
2492+ return -EINTR;
2493+ ret = videobuf_querybuf(&fh->vbq, (void *)&buf);
2494+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2495+ if (copy_to_user((struct v4l2_buffer *)arg, &buf,
2496+ sizeof(struct v4l2_buffer)))
2497+ return -EFAULT;
2498+ break;
2499+ }
2500+ case RSZ_QUEUEBUF:
2501+ {
2502+ struct v4l2_buffer buf;
2503+ if (copy_from_user(&buf, (struct v4l2_buffer *)arg,
2504+ sizeof(struct v4l2_buffer))) {
2505+ return -EFAULT;
2506+ }
2507+ if (mutex_lock_interruptible(&rsz_conf_chan->
2508+ chanprotection_mutex))
2509+ return -EINTR;
2510+ ret = videobuf_qbuf(&fh->vbq, (void *)&buf);
2511+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2512+ break;
2513+ }
2514+ case RSZ_S_PARAM:
2515+ {
2516+ struct rsz_params *params = fh->params;
2517+ if (copy_from_user(params, (struct rsz_params *)arg,
2518+ sizeof(struct rsz_params))) {
2519+ return -EFAULT;
2520+ }
2521+ if (mutex_lock_interruptible(&rsz_conf_chan->
2522+ chanprotection_mutex))
2523+ return -EINTR;
2524+ ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
2525+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
2526+ break;
2527+ }
2528+ case RSZ_G_PARAM:
2529+ ret = rsz_get_params((struct rsz_params *)arg, rsz_conf_chan);
2530+ break;
2531+
2532+ case RSZ_G_STATUS:
2533+ {
2534+ struct rsz_status *status;
2535+ status = (struct rsz_status *)arg;
2536+ status->chan_busy = rsz_conf_chan->status;
2537+ status->hw_busy = ispresizer_busy();
2538+ status->src = INPUT_RAM;
2539+ break;
2540+ }
2541+ case RSZ_RESIZE:
2542+ if (file->f_flags & O_NONBLOCK) {
2543+ if (ispresizer_busy())
2544+ return -EBUSY;
2545+ else {
2546+ if (!mutex_trylock(&device->reszwrap_mutex))
2547+ return -EBUSY;
2548+ }
2549+ } else {
2550+ if (mutex_lock_interruptible(&device->reszwrap_mutex))
2551+ return -EINTR;
2552+ }
2553+ ret = rsz_start((int *)arg, fh);
2554+ mutex_unlock(&device->reszwrap_mutex);
2555+ break;
2556+ case RSZ_GET_CROPSIZE:
2557+ rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
2558+ break;
2559+
2560+ default:
2561+ dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
2562+ return -EINVAL;
2563+ }
2564+
2565+ return (long)ret;
2566+}
2567+
2568+static struct file_operations rsz_fops = {
2569+ .owner = THIS_MODULE,
2570+ .open = rsz_open,
2571+ .release = rsz_release,
2572+ .mmap = rsz_mmap,
2573+ .unlocked_ioctl = rsz_unlocked_ioctl,
2574+};
2575+
2576+/**
2577+ * rsz_isr - Interrupt Service Routine for Resizer wrapper
2578+ * @status: ISP IRQ0STATUS register value
2579+ * @arg1: Currently not used
2580+ * @arg2: Currently not used
2581+ *
2582+ * Interrupt Service Routine for Resizer wrapper
2583+ **/
2584+static void rsz_isr(unsigned long status, isp_vbq_callback_ptr arg1, void *arg2)
2585+{
2586+
2587+ if ((status & RESZ_DONE) != RESZ_DONE)
2588+ return;
2589+
2590+ complete(&(device_config->compl_isr));
2591+
2592+}
2593+
2594+/**
2595+ * resizer_platform_release - Acts when Reference count is zero
2596+ * @device: Structure containing ISP resizer wrapper global information
2597+ *
2598+ * This is called when the reference count goes to zero.
2599+ **/
2600+static void resizer_platform_release(struct device *device)
2601+{
2602+}
2603+
2604+/**
2605+ * resizer_probe - Checks for device presence
2606+ * @device: Structure containing details of the current device.
2607+ *
2608+ * Always returns 0.
2609+ **/
2610+static int __init resizer_probe(struct platform_device *device)
2611+{
2612+ return 0;
2613+}
2614+
2615+/**
2616+ * resizer_remove - Handles the removal of the driver
2617+ * @omap_resizer_device: Structure containing details of the current device.
2618+ *
2619+ * Always returns 0.
2620+ **/
2621+static int resizer_remove(struct platform_device *omap_resizer_device)
2622+{
2623+ return 0;
2624+}
2625+
2626+static struct class *rsz_class;
2627+static struct cdev c_dev;
2628+static dev_t dev;
2629+static struct platform_device omap_resizer_device = {
2630+ .name = OMAP_REZR_NAME,
2631+ .id = 2,
2632+ .dev = {
2633+ .release = resizer_platform_release,}
2634+};
2635+
2636+static struct platform_driver omap_resizer_driver = {
2637+ .probe = resizer_probe,
2638+ .remove = resizer_remove,
2639+ .driver = {
2640+ .bus = &platform_bus_type,
2641+ .name = OMAP_REZR_NAME,
2642+ },
2643+};
2644+
2645+/**
2646+ * omap_rsz_init - Initialization of Resizer Wrapper
2647+ *
2648+ * Returns 0 if successful, -ENOMEM if could not allocate memory, -ENODEV if
2649+ * could not register the wrapper as a character device, or other errors if the
2650+ * device or driver can't register.
2651+ **/
2652+static int __init omap_rsz_init(void)
2653+{
2654+ int ret = 0;
2655+ struct device_params *device;
2656+ device = kzalloc(sizeof(struct device_params), GFP_KERNEL);
2657+ if (!device) {
2658+ dev_err(rsz_device, OMAP_REZR_NAME ": could not allocate "
2659+ "memory\n");
2660+ return -ENOMEM;
2661+ }
2662+
2663+ ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
2664+ if (ret < 0) {
2665+ dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
2666+ "Could not allocate region "
2667+ "for character device\n");
2668+ kfree(device);
2669+ return -ENODEV;
2670+ }
2671+
2672+ /* Register the driver in the kernel */
2673+ /* Initialize of character device */
2674+ cdev_init(&c_dev, &rsz_fops);
2675+ c_dev.owner = THIS_MODULE;
2676+ c_dev.ops = &rsz_fops;
2677+
2678+ /* Addding character device */
2679+ ret = cdev_add(&c_dev, dev, 1);
2680+ if (ret) {
2681+ dev_err(rsz_device, OMAP_REZR_NAME ": Error adding "
2682+ "device - %d\n", ret);
2683+ goto fail2;
2684+ }
2685+ rsz_major = MAJOR(dev);
2686+
2687+ /* register driver as a platform driver */
2688+ ret = platform_driver_register(&omap_resizer_driver);
2689+ if (ret) {
2690+ dev_err(rsz_device, OMAP_REZR_NAME
2691+ ": Failed to register platform driver!\n");
2692+ goto fail3;
2693+ }
2694+
2695+ /* Register the drive as a platform device */
2696+ ret = platform_device_register(&omap_resizer_device);
2697+ if (ret) {
2698+ dev_err(rsz_device, OMAP_REZR_NAME
2699+ ": Failed to register platform device!\n");
2700+ goto fail4;
2701+ }
2702+
2703+ rsz_class = class_create(THIS_MODULE, OMAP_REZR_NAME);
2704+ if (!rsz_class) {
2705+ dev_err(rsz_device, OMAP_REZR_NAME
2706+ ": Failed to create class!\n");
2707+ goto fail5;
2708+ }
2709+
2710+ /* make entry in the devfs */
2711+ rsz_device = device_create(rsz_class, rsz_device,
2712+ MKDEV(rsz_major, 0), NULL,
2713+ OMAP_REZR_NAME);
2714+ dev_dbg(rsz_device, OMAP_REZR_NAME ": Registered Resizer Wrapper\n");
2715+ device->opened = 0;
2716+
2717+ device->vbq_ops.buf_setup = rsz_vbq_setup;
2718+ device->vbq_ops.buf_prepare = rsz_vbq_prepare;
2719+ device->vbq_ops.buf_release = rsz_vbq_release;
2720+ device->vbq_ops.buf_queue = rsz_vbq_queue;
2721+ init_completion(&device->compl_isr);
2722+ mutex_init(&device->reszwrap_mutex);
2723+
2724+ device_config = device;
2725+ return 0;
2726+
2727+fail5:
2728+ platform_device_unregister(&omap_resizer_device);
2729+fail4:
2730+ platform_driver_unregister(&omap_resizer_driver);
2731+fail3:
2732+ cdev_del(&c_dev);
2733+fail2:
2734+ unregister_chrdev_region(dev, 1);
2735+ kfree(device);
2736+ return ret;
2737+}
2738+
2739+/**
2740+ * omap_rsz_exit - Close of Resizer Wrapper
2741+ **/
2742+void __exit omap_rsz_exit(void)
2743+{
2744+ device_destroy(rsz_class, dev);
2745+ class_destroy(rsz_class);
2746+ platform_device_unregister(&omap_resizer_device);
2747+ platform_driver_unregister(&omap_resizer_driver);
2748+ cdev_del(&c_dev);
2749+ unregister_chrdev_region(dev, 1);
2750+ kfree(device_config);
2751+}
2752+
2753+module_init(omap_rsz_init)
2754+module_exit(omap_rsz_exit)
2755+
2756+MODULE_AUTHOR("Texas Instruments");
2757+MODULE_DESCRIPTION("OMAP ISP Resizer");
2758+MODULE_LICENSE("GPL");
2759diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
2760new file mode 100644
2761index 0000000..5ac0c88
2762--- /dev/null
2763+++ b/include/linux/omap_resizer.h
2764@@ -0,0 +1,136 @@
2765+/*
2766+ * drivers/media/video/isp/omap_resizer.h
2767+ *
2768+ * Include file for Resizer module wrapper in TI's OMAP3430 ISP
2769+ *
2770+ * Copyright (C) 2008 Texas Instruments, Inc.
2771+ *
2772+ * This package is free software; you can redistribute it and/or modify
2773+ * it under the terms of the GNU General Public License version 2 as
2774+ * published by the Free Software Foundation.
2775+ *
2776+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2777+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2778+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2779+ */
2780+
2781+#ifndef OMAP_RESIZER_H
2782+#define OMAP_RESIZER_H
2783+
2784+#include <linux/types.h>
2785+
2786+/* ioctls definition */
2787+#define RSZ_IOC_BASE 'R'
2788+#define RSZ_IOC_MAXNR 8
2789+
2790+/*Ioctl options which are to be passed while calling the ioctl*/
2791+#define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
2792+ struct v4l2_requestbuffers)
2793+#define RSZ_QUERYBUF _IOWR(RSZ_IOC_BASE, 2, struct v4l2_buffer)
2794+#define RSZ_S_PARAM _IOWR(RSZ_IOC_BASE, 3, struct rsz_params)
2795+#define RSZ_G_PARAM _IOWR(RSZ_IOC_BASE, 4, struct rsz_params)
2796+#define RSZ_RESIZE _IOWR(RSZ_IOC_BASE, 5, __s32)
2797+#define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
2798+#define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
2799+#define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
2800+
2801+#define RSZ_INTYPE_YCBCR422_16BIT 0
2802+#define RSZ_INTYPE_PLANAR_8BIT 1
2803+#define RSZ_PIX_FMT_UYVY 1 /* cb:y:cr:y */
2804+#define RSZ_PIX_FMT_YUYV 0 /* y:cb:y:cr */
2805+
2806+enum config_done {
2807+ STATE_CONFIGURED, /* Resizer driver configured
2808+ * by application.
2809+ */
2810+ STATE_NOT_CONFIGURED /* Resizer driver not
2811+ * configured by application.
2812+ */
2813+};
2814+
2815+/* Structure Definitions */
2816+
2817+/* used to luma enhancement options */
2818+
2819+struct rsz_yenh {
2820+ __s32 type; /* represents luma enable or
2821+ * disable.
2822+ */
2823+ __u8 gain; /* represents gain. */
2824+ __u8 slop; /* represents slop. */
2825+ __u8 core; /* Represents core value. */
2826+};
2827+
2828+/* Conatins all the parameters for resizing. This structure
2829+ * is used to configure resiser parameters
2830+ */
2831+struct rsz_params {
2832+ __s32 in_hsize; /* input frame horizontal
2833+ * size.
2834+ */
2835+ __s32 in_vsize; /* input frame vertical size */
2836+ __s32 in_pitch; /* offset between two rows of
2837+ * input frame.
2838+ */
2839+ __s32 inptyp; /* for determining 16 bit or
2840+ * 8 bit data.
2841+ */
2842+ __s32 vert_starting_pixel; /* for specifying vertical
2843+ * starting pixel in input.
2844+ */
2845+ __s32 horz_starting_pixel; /* for specyfing horizontal
2846+ * starting pixel in input.
2847+ */
2848+ __s32 cbilin; /* # defined, filter with luma
2849+ * or bi-linear interpolation.
2850+ */
2851+ __s32 pix_fmt; /* # defined, UYVY or YUYV */
2852+ __s32 out_hsize; /* output frame horizontal
2853+ * size.
2854+ */
2855+ __s32 out_vsize; /* output frame vertical
2856+ * size.
2857+ */
2858+ __s32 out_pitch; /* offset between two rows of
2859+ * output frame.
2860+ */
2861+ __s32 hstph; /* for specifying horizontal
2862+ * starting phase.
2863+ */
2864+ __s32 vstph; /* for specifying vertical
2865+ * starting phase.
2866+ */
2867+ __u16 tap4filt_coeffs[32]; /* horizontal filter
2868+ * coefficients.
2869+ */
2870+ __u16 tap7filt_coeffs[32]; /* vertical filter
2871+ * coefficients.
2872+ */
2873+ struct rsz_yenh yenh_params;
2874+};
2875+
2876+/* Contains the status of hardware and channel */
2877+struct rsz_status {
2878+ __s32 chan_busy; /* 1: channel is busy,
2879+ * 0: channel is not busy
2880+ */
2881+ __s32 hw_busy; /* 1: hardware is busy,
2882+ * 0: hardware is not busy
2883+ */
2884+ __s32 src; /* # defined, can be either
2885+ * SD-RAM or CCDC/PREVIEWER
2886+ */
2887+};
2888+
2889+/* Passed by application for getting crop size */
2890+struct rsz_cropsize {
2891+ __u32 hcrop; /* Number of pixels per line
2892+ * cropped in output image.
2893+ */
2894+
2895+ __u32 vcrop; /* Number of lines cropped
2896+ * in output image.
2897+ */
2898+};
2899+
2900+#endif
2901--
29021.6.0.3
2903
2904--- /tmp/Kconfig 2009-04-06 10:56:27.000000000 +0200
2905+++ git/drivers/media/video/Kconfig 2009-04-06 10:57:25.000000000 +0200
2906@@ -711,6 +711,9 @@
2907 CMOS camera controller. This is the controller found on first-
2908 generation OLPC systems.
2909
2910+
2911+source "drivers/media/video/isp/Kconfig"
2912+
2913 config VIDEO_OMAP3
2914 tristate "OMAP 3 Camera support"
2915 select VIDEOBUF_GEN
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch
new file mode 100644
index 0000000000..631b05f417
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/standalone/0002-Resizer-bug-fixes-on-top-of-1.0.2-release.patch
@@ -0,0 +1,730 @@
1From 20d79137ecaa6c7dad007d9ea1d7be5550db4839 Mon Sep 17 00:00:00 2001
2From: Vaibhav Hiremath <hvaibhav@ti.com>
3Date: Fri, 13 Feb 2009 15:40:25 +0530
4Subject: [PATCH 2/2] Resizer bug fixes on top of 1.0.2 release
5
6This commit contains resizer bug fixes on top of
7 PSP1.0.2 release -
8 - 4096 aligned address constraint
9 - workaround for extra page allocation for page aligned
10 size buffers
11
12Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
13---
14 drivers/media/video/isp/omap_resizer.c | 417 ++++++++++++++++++++++++--------
15 include/linux/omap_resizer.h | 3 +-
16 2 files changed, 321 insertions(+), 99 deletions(-)
17
18diff --git a/drivers/media/video/isp/omap_resizer.c b/drivers/media/video/isp/omap_resizer.c
19index 54bc425..8059c70 100644
20--- a/drivers/media/video/isp/omap_resizer.c
21+++ b/drivers/media/video/isp/omap_resizer.c
22@@ -28,6 +28,7 @@
23 #include <linux/platform_device.h>
24 #include <linux/io.h>
25 #include <linux/uaccess.h>
26+#include <linux/pci.h>
27 #include <media/v4l2-dev.h>
28 #include <asm/cacheflush.h>
29
30@@ -76,6 +77,10 @@
31 #define MAX_COEF_COUNTER 16
32 #define COEFF_ADDRESS_OFFSET 0x04
33
34+#define RSZ_DEF_REQ_EXP 0xE /* Default read operation expand
35+ * for the Resizer driver; value
36+ * taken from Davinci.
37+ */
38 /* Global structure which contains information about number of channels
39 and protection variables */
40 struct device_params {
41@@ -85,6 +90,7 @@ struct device_params {
42 struct mutex reszwrap_mutex; /* Semaphore for array */
43
44 struct videobuf_queue_ops vbq_ops; /* videobuf queue operations */
45+ unsigned long extra_page_addr;
46 };
47
48 /* Register mapped structure which contains the every register
49@@ -126,6 +132,9 @@ struct resizer_config {
50 u32 rsz_yehn; /* yehn(luma)register mapping
51 * variable.
52 */
53+ u32 sdr_req_exp; /* Configuration for Non
54+ * real time read expand
55+ */
56 };
57
58 struct rsz_mult {
59@@ -179,6 +188,7 @@ struct channel_config {
60 * channel is busy or not
61 */
62 struct mutex chanprotection_mutex;
63+ int buf_address[VIDEO_MAX_FRAME];
64 enum config_done config_state;
65 u8 input_buf_index;
66 u8 output_buf_index;
67@@ -200,8 +210,6 @@ struct rsz_fh {
68 struct videobuf_queue vbq;
69 struct device_params *device;
70
71- dma_addr_t isp_addr_read; /* Input/Output address */
72- dma_addr_t isp_addr_write; /* Input/Output address */
73 u32 rsz_bufsize; /* channel specific buffersize
74 */
75 };
76@@ -227,6 +235,10 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
77 static void rsz_config_ratio(struct rsz_mult *multipass,
78 struct channel_config *rsz_conf_chan);
79
80+static void inline rsz_set_exp(unsigned int exp)
81+{
82+ omap_writel(((exp & 0x3FF) << 10), OMAP3ISP_SBL_REG(0xF8));
83+}
84 /**
85 * rsz_hardware_setup - Sets hardware configuration registers
86 * @rsz_conf_chan: Structure containing channel configuration
87@@ -271,12 +283,15 @@ static void rsz_hardware_setup(struct channel_config *rsz_conf_chan)
88 + coeffoffset));
89 coeffoffset = coeffoffset + COEFF_ADDRESS_OFFSET;
90 }
91+ /* Configure the read expand register */
92+ rsz_set_exp(rsz_conf_chan->register_config.sdr_req_exp);
93 }
94
95 /**
96 * rsz_start - Enables Resizer Wrapper
97 * @arg: Currently not used.
98- * @device: Structure containing ISP resizer wrapper global information
99+ * @fh: File structure containing ISP resizer information specific to
100+ * channel opened.
101 *
102 * Submits a resizing task specified by the rsz_resize structure. The call can
103 * either be blocked until the task is completed or returned immediately based
104@@ -292,12 +307,18 @@ int rsz_start(int *arg, struct rsz_fh *fh)
105 struct channel_config *rsz_conf_chan = fh->config;
106 struct rsz_mult *multipass = fh->multipass;
107 struct videobuf_queue *q = &fh->vbq;
108+ struct videobuf_buffer *buf;
109 int ret;
110
111 if (rsz_conf_chan->config_state) {
112 dev_err(rsz_device, "State not configured \n");
113 goto err_einval;
114 }
115+ if (!rsz_conf_chan->register_config.rsz_sdr_inadd ||
116+ !rsz_conf_chan->register_config.rsz_sdr_outadd) {
117+ dev_err(rsz_device, "address is null\n");
118+ goto err_einval;
119+ }
120
121 rsz_conf_chan->status = CHANNEL_BUSY;
122
123@@ -325,33 +346,22 @@ mult:
124 goto mult;
125 }
126
127- if (fh->isp_addr_read) {
128- ispmmu_vunmap(fh->isp_addr_read);
129- fh->isp_addr_read = 0;
130- }
131- if (fh->isp_addr_write) {
132- ispmmu_vunmap(fh->isp_addr_write);
133- fh->isp_addr_write = 0;
134- }
135-
136 rsz_conf_chan->status = CHANNEL_FREE;
137- q->bufs[rsz_conf_chan->input_buf_index]->state = VIDEOBUF_NEEDS_INIT;
138- q->bufs[rsz_conf_chan->output_buf_index]->state = VIDEOBUF_NEEDS_INIT;
139 rsz_conf_chan->register_config.rsz_sdr_outadd = 0;
140 rsz_conf_chan->register_config.rsz_sdr_inadd = 0;
141
142- /* Unmap and free the DMA memory allocated for buffers */
143- videobuf_dma_unmap(q, videobuf_to_dma(
144- q->bufs[rsz_conf_chan->input_buf_index]));
145- videobuf_dma_unmap(q, videobuf_to_dma(
146- q->bufs[rsz_conf_chan->output_buf_index]));
147- videobuf_dma_free(videobuf_to_dma(
148- q->bufs[rsz_conf_chan->input_buf_index]));
149- videobuf_dma_free(videobuf_to_dma(
150- q->bufs[rsz_conf_chan->output_buf_index]));
151-
152 isp_unset_callback(CBK_RESZ_DONE);
153
154+ /* Empty the Videobuf queue which was filled during the qbuf */
155+ buf = q->bufs[rsz_conf_chan->input_buf_index];
156+ buf->state = VIDEOBUF_IDLE;
157+ list_del(&buf->stream);
158+ if (rsz_conf_chan->input_buf_index != rsz_conf_chan->output_buf_index) {
159+ buf = q->bufs[rsz_conf_chan->output_buf_index];
160+ buf->state = VIDEOBUF_IDLE;
161+ list_del(&buf->stream);
162+ }
163+
164 return 0;
165 err_einval:
166 return -EINVAL;
167@@ -359,6 +369,8 @@ err_einval:
168
169 /**
170 * rsz_set_multipass - Set resizer multipass
171+ * @multipass: Structure containing channel configuration
172+ for multipass support
173 * @rsz_conf_chan: Structure containing channel configuration
174 *
175 * Returns always 0
176@@ -384,6 +396,8 @@ static int rsz_set_multipass(struct rsz_mult *multipass,
177
178 /**
179 * rsz_copy_data - Copy data
180+ * @multipass: Structure containing channel configuration
181+ for multipass support
182 * @params: Structure containing the Resizer Wrapper parameters
183 *
184 * Copy data
185@@ -413,6 +427,8 @@ static void rsz_copy_data(struct rsz_mult *multipass, struct rsz_params *params)
186
187 /**
188 * rsz_set_params - Set parameters for resizer wrapper
189+ * @multipass: Structure containing channel configuration
190+ for multipass support
191 * @params: Structure containing the Resizer Wrapper parameters
192 * @rsz_conf_chan: Structure containing channel configuration
193 *
194@@ -524,6 +540,8 @@ static int rsz_set_params(struct rsz_mult *multipass, struct rsz_params *params,
195 }
196
197 rsz_config_ratio(multipass, rsz_conf_chan);
198+ /* Default value for read expand:Taken from Davinci */
199+ rsz_conf_chan->register_config.sdr_req_exp = RSZ_DEF_REQ_EXP;
200
201 rsz_conf_chan->config_state = STATE_CONFIGURED;
202
203@@ -534,6 +552,8 @@ err_einval:
204
205 /**
206 * rsz_set_ratio - Set ratio
207+ * @multipass: Structure containing channel configuration
208+ for multipass support
209 * @rsz_conf_chan: Structure containing channel configuration
210 *
211 * Returns 0 if successful, -EINVAL if invalid output size, upscaling ratio is
212@@ -548,7 +568,8 @@ static int rsz_set_ratio(struct rsz_mult *multipass,
213
214 if ((multipass->out_hsize > MAX_IMAGE_WIDTH) ||
215 (multipass->out_vsize > MAX_IMAGE_WIDTH)) {
216- dev_err(rsz_device, "Invalid output size!");
217+ dev_err(rsz_device, "Invalid output size! - %d", \
218+ multipass->out_hsize);
219 goto err_einval;
220 }
221 if (multipass->cbilin) {
222@@ -758,6 +779,8 @@ err_einval:
223
224 /**
225 * rsz_config_ratio - Configure ratio
226+ * @multipass: Structure containing channel configuration
227+ for multipass support
228 * @rsz_conf_chan: Structure containing channel configuration
229 *
230 * Configure ratio
231@@ -789,6 +812,20 @@ static void rsz_config_ratio(struct rsz_mult *multipass,
232 ((vsize << ISPRSZ_IN_SIZE_VERT_SHIFT)
233 & ISPRSZ_IN_SIZE_VERT_MASK);
234
235+ /* This is another workaround for the ISP-MMU translation fault.
236+ For the parameters whose image size comes exactly to PAGE_SIZE
237+ generates ISP-MMU translation fault. The root-cause is the equation
238+ input width = (32*sph + (ow - 1)*hrsz + 16) >> 8 + 7
239+ = (64*sph + (ow - 1)*hrsz + 32) >> 8 + 7
240+ input height = (32*spv + (oh - 1)*vrsz + 16) >> 8 + 4
241+ = (64*spv + (oh - 1)*vrsz + 32) >> 8 + 7
242+
243+ we are adjusting the input width to suit for Resizer module,
244+ application should use this configuration henceforth.
245+ */
246+ multipass->in_hsize = hsize;
247+ multipass->in_vsize = vsize;
248+
249 for (coeffcounter = 0; coeffcounter < MAX_COEF_COUNTER;
250 coeffcounter++) {
251 if (multipass->num_htap) {
252@@ -990,24 +1027,15 @@ static void rsz_calculate_crop(struct channel_config *rsz_conf_chan,
253 static void rsz_vbq_release(struct videobuf_queue *q,
254 struct videobuf_buffer *vb)
255 {
256- int i;
257 struct rsz_fh *fh = q->priv_data;
258+ struct videobuf_dmabuf *dma = NULL;
259
260- for (i = 0; i < VIDEO_MAX_FRAME; i++) {
261- struct videobuf_dmabuf *dma = NULL;
262- if (!q->bufs[i])
263- continue;
264- if (q->bufs[i]->memory != V4L2_MEMORY_MMAP)
265- continue;
266- dma = videobuf_to_dma(q->bufs[i]);
267- videobuf_dma_unmap(q, dma);
268- videobuf_dma_free(dma);
269- }
270+ dma = videobuf_to_dma(q->bufs[vb->i]);
271+ videobuf_dma_unmap(q, dma);
272+ videobuf_dma_free(dma);
273+ ispmmu_vunmap(fh->config->buf_address[vb->i]);
274+ fh->config->buf_address[vb->i] = 0;
275
276- ispmmu_vunmap(fh->isp_addr_read);
277- ispmmu_vunmap(fh->isp_addr_write);
278- fh->isp_addr_read = 0;
279- fh->isp_addr_write = 0;
280 spin_lock(&fh->vbq_lock);
281 vb->state = VIDEOBUF_NEEDS_INIT;
282 spin_unlock(&fh->vbq_lock);
283@@ -1062,7 +1090,105 @@ err_einval:
284 spin_unlock(&fh->vbq_lock);
285 return -EINVAL;
286 }
287+/*
288+ * This function is work around for the videobuf_iolock API,
289+ * for User memory allocated with ioremap (VM_IO flag) the API
290+ * get_user_pages fails.
291+ *
292+ * To fulfill this requirement, we have completely ignored VM layer of
293+ * Linux, and configuring the ISP MMU with physical address.
294+ */
295+static int omap_videobuf_dma_init_user(struct videobuf_buffer *vb,
296+ unsigned long physp, unsigned long asize)
297+{
298+ struct videobuf_dmabuf *dma;
299+ struct scatterlist *sglist;
300+ unsigned long data, first, last;
301+ int len, i = 0;
302+
303+ dma = videobuf_to_dma(vb);
304+ data = vb->baddr;
305+
306+ first = (data & PAGE_MASK) >> PAGE_SHIFT;
307+ last = ((data+asize-1) & PAGE_MASK) >> PAGE_SHIFT;
308+ dma->offset = data & ~PAGE_MASK;
309+ dma->nr_pages = last-first+1;
310+
311+ dma->direction = PCI_DMA_FROMDEVICE;
312+ /*
313+ * Allocate array of sglen + 1, to add entry of extra page
314+ * for input buffer. Driver always uses 0th buffer as input buffer.
315+ */
316+ len = dma->nr_pages + (vb->i ? 0 : 1);
317+ sglist = kcalloc(len, sizeof(*sglist), GFP_KERNEL);
318+ if (NULL == sglist)
319+ return -ENOMEM;
320+
321+ sglist[0].offset = 0;
322+ sglist[0].length = PAGE_SIZE - dma->offset;
323+ sglist[0].dma_address = (dma_addr_t)physp;
324+ physp += sglist[0].length;
325+ /*
326+ * Iterate in a loop for the number of pages
327+ */
328+ for (i = 1; i < (len - (vb->i ? 0 : 1)); i++) {
329+ sglist[i].offset = 0;
330+ sglist[i].length = PAGE_SIZE;
331+ sglist[i].dma_address = (dma_addr_t)physp;
332+ physp += PAGE_SIZE;
333+ }
334+ if (0 == vb->i) {
335+ sglist[i].offset = 0;
336+ sglist[i].length = PAGE_SIZE;
337+ sglist[i].dma_address =
338+ (dma_addr_t)device_config->extra_page_addr;
339+ }
340+ dma->sglist = sglist;
341+ dma->sglen = len;
342+ return 0;
343+
344+ }
345+/*
346+ * This function is workaround for the issue, where ISP-MMU generated
347+ * translation fault for specific params whose size is aligned to PAGE_SIZE.
348+
349+ * As a workaround we are padding one extra page for input buffer. This page
350+ * we are allocating during init time and will not be released through-out
351+ * life time of resizer driver. Please note that Resizer module only reads
352+ * from this extra page.
353+ */
354+int omap_create_sg(struct videobuf_queue *q, struct videobuf_dmabuf *dma)
355+{
356+ struct scatterlist *sglist;
357+ int sglen;
358
359+ sglen = dma->sglen;
360+ sglist = kcalloc(sglen + 1, sizeof(*sglist), GFP_KERNEL);
361+ if (NULL == sglist)
362+ return -ENOMEM;
363+ /*
364+ * Copy the sglist locally
365+ */
366+ memcpy(sglist, dma->sglist, sglen * sizeof(*sglist));
367+ /*
368+ * Release the old sglist, since we already copied it locally
369+ */
370+ videobuf_dma_unmap(q, dma);
371+ /*
372+ * Add extra entry to sglist to work with specific params, whose
373+ * buffer address alined to PAGE_SIZE.
374+ */
375+ sglist[sglen].offset = 0;
376+ sglist[sglen].length = PAGE_SIZE;
377+ sglist[sglen].dma_address = (dma_addr_t)device_config->extra_page_addr;
378+ sglen++;
379+ /*
380+ * Save the sglist for mapping to ISP-MMU space
381+ */
382+ dma->sglist = sglist;
383+ dma->sglen = sglen;
384+ return 0;
385+}
386 /**
387 * rsz_vbq_prepare - Videobuffer is prepared and mmapped.
388 * @q: Structure containing the videobuffer queue file handle, and device
389@@ -1079,19 +1205,24 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
390 {
391 struct rsz_fh *fh = q->priv_data;
392 struct channel_config *rsz_conf_chan = fh->config;
393- struct rsz_mult *multipass = fh->multipass;
394 int err = 0;
395 unsigned int isp_addr, insize, outsize;
396- struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
397-
398+ struct rsz_mult *multipass = fh->multipass;
399 spin_lock(&fh->vbq_lock);
400 if (vb->baddr) {
401+ /* Check for 32 byte alignement */
402+ if (vb->baddr != (vb->baddr & ~0x1F)) {
403+ spin_unlock(&fh->vbq_lock);
404+ dev_err(rsz_device, "Buffer address should be aligned \
405+ to 32 byte\n");
406+ return -EINVAL;
407+ }
408 vb->size = fh->rsz_bufsize;
409 vb->bsize = fh->rsz_bufsize;
410 } else {
411 spin_unlock(&fh->vbq_lock);
412 dev_err(rsz_device, "No user buffer allocated\n");
413- goto out;
414+ return -EINVAL;
415 }
416 if (vb->i) {
417 vb->width = fh->params->out_hsize;
418@@ -1103,55 +1234,128 @@ static int rsz_vbq_prepare(struct videobuf_queue *q,
419
420 vb->field = field;
421 spin_unlock(&fh->vbq_lock);
422+ /*
423+ * Calculate input and output sizes, will be used while mapping
424+ * user pages
425+ */
426+ outsize = multipass->out_pitch * multipass->out_vsize;
427+ insize = multipass->in_pitch * multipass->in_vsize;
428
429 if (vb->state == VIDEOBUF_NEEDS_INIT) {
430- err = videobuf_iolock(q, vb, NULL);
431- if (!err) {
432- isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
433- if (!isp_addr)
434- err = -EIO;
435- else {
436- if (vb->i) {
437- rsz_conf_chan->register_config.
438- rsz_sdr_outadd
439- = isp_addr;
440- fh->isp_addr_write = isp_addr;
441- rsz_conf_chan->output_buf_index = vb->i;
442- } else {
443+ struct videobuf_dmabuf *dma;
444+ struct vm_area_struct *vma;
445+ spin_lock(&fh->vbq_lock);
446+ dma = videobuf_to_dma(vb);
447+ vma = find_vma(current->mm, vb->baddr);
448+ if ((vma) && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) {
449+ /* This will catch ioremaped buffers to the kernel.
450+ * It gives two possible scenarios -
451+ * - Driver allocates buffer using either
452+ * dma_alloc_coherent or get_free_pages,
453+ * and maps to user space using
454+ * io_remap_pfn_range/remap_pfn_range
455+ * - Drivers maps memory outside from Linux using
456+ * io_remap
457+ */
458+ unsigned long physp = 0, asize;
459+ asize = vb->i ? outsize : insize;
460+ if ((vb->baddr + asize) > vma->vm_end) {
461+ spin_unlock(&fh->vbq_lock);
462+ dev_err(rsz_device, "User Buffer Allocation:" \
463+ "err=%lu[%lu]\n",\
464+ (vma->vm_end - vb->baddr), asize);
465+ return -ENOMEM;
466+ }
467+ physp = (vma->vm_pgoff << PAGE_SHIFT) +
468+ (vb->baddr - vma->vm_start);
469+ err = omap_videobuf_dma_init_user(vb, physp, asize);
470+ spin_unlock(&fh->vbq_lock);
471+ if (0 != err)
472+ return err;
473+ } else {
474+ err = videobuf_iolock(q, vb, NULL);
475+ /*
476+ * In case of user pointer mode, the get_user_pages
477+ * will fail if user has allocated less memory than
478+ * vb->size. But it is not error from resizer driver
479+ * point of view. so handled seperately
480+ */
481+ if ((err < 0) && (dma->nr_pages > 0))
482+ err = videobuf_dma_map(q, dma);
483+ if (err)
484+ goto buf_release;
485+ /*
486+ * Add one extra page for input buffer
487+ */
488+ if (0 == vb->i)
489+ err = omap_create_sg(q, dma);
490+ if (err)
491+ goto buf_release;
492+ spin_unlock(&fh->vbq_lock);
493+ }
494+ isp_addr = ispmmu_vmap(dma->sglist, dma->sglen);
495+ if (!isp_addr)
496+ err = -EIO;
497+ else {
498+ if (vb->i) {
499+ rsz_conf_chan->buf_address[vb->i] = isp_addr;
500+ rsz_conf_chan->register_config.
501+ rsz_sdr_outadd
502+ = isp_addr;
503+ rsz_conf_chan->output_buf_index = vb->i;
504+ } else {
505+ rsz_conf_chan->buf_address[vb->i] = isp_addr;
506+ rsz_conf_chan->register_config.
507+ rsz_sdr_inadd
508+ = isp_addr;
509+ rsz_conf_chan->input_buf_index = vb->i;
510+ if (outsize < insize && rsz_conf_chan->
511+ register_config.
512+ rsz_sdr_outadd == 0) {
513 rsz_conf_chan->register_config.
514- rsz_sdr_inadd
515- = isp_addr;
516- rsz_conf_chan->input_buf_index = vb->i;
517- outsize = multipass->out_pitch *
518- multipass->out_vsize;
519- insize = multipass->in_pitch *
520- multipass->in_vsize;
521- if (outsize < insize) {
522- rsz_conf_chan->register_config.
523- rsz_sdr_outadd
524- = isp_addr;
525- rsz_conf_chan->
526- output_buf_index =
527- vb->i;
528- }
529-
530- fh->isp_addr_read = isp_addr;
531+ rsz_sdr_outadd
532+ = isp_addr;
533+ rsz_conf_chan->
534+ output_buf_index =
535+ vb->i;
536 }
537 }
538 }
539
540- }
541+ } else {
542+ if(vb->i) {
543+ rsz_conf_chan->register_config.
544+ rsz_sdr_outadd =
545+ rsz_conf_chan->buf_address[vb->i];
546+ rsz_conf_chan->output_buf_index = vb->i;
547+ } else {
548+ rsz_conf_chan->register_config.
549+ rsz_sdr_inadd =
550+ rsz_conf_chan->buf_address[vb->i];
551+ rsz_conf_chan->input_buf_index = vb->i;
552+ if(outsize < insize && rsz_conf_chan->
553+ register_config.
554+ rsz_sdr_outadd == 0) {
555+ rsz_conf_chan->register_config.
556+ rsz_sdr_outadd
557+ = rsz_conf_chan->buf_address[vb->i];
558+ rsz_conf_chan->output_buf_index = vb->i;
559+ }
560+
561+ }
562
563+ }
564 if (!err) {
565 spin_lock(&fh->vbq_lock);
566 vb->state = VIDEOBUF_PREPARED;
567 spin_unlock(&fh->vbq_lock);
568- flush_cache_user_range(NULL, vb->baddr, (vb->baddr
569- + vb->bsize));
570 } else
571 rsz_vbq_release(q, vb);
572
573-out:
574+ return err;
575+buf_release:
576+ spin_unlock(&fh->vbq_lock);
577+ rsz_vbq_release(q, vb);
578 return err;
579 }
580
581@@ -1255,7 +1459,8 @@ err_enomem0:
582 **/
583 static int rsz_release(struct inode *inode, struct file *filp)
584 {
585- u32 timeout = 0;
586+ int i;
587+ unsigned int timeout = 0;
588 struct rsz_fh *fh = filp->private_data;
589 struct channel_config *rsz_conf_chan = fh->config;
590 struct rsz_params *params = fh->params;
591@@ -1266,17 +1471,17 @@ static int rsz_release(struct inode *inode, struct file *filp)
592 timeout++;
593 schedule();
594 }
595- if (mutex_lock_interruptible(&device_config->reszwrap_mutex))
596- return -EINTR;
597- device_config->opened--;
598- mutex_unlock(&device_config->reszwrap_mutex);
599- /* This will Free memory allocated to the buffers,
600- * and flushes the queue
601- */
602- videobuf_queue_cancel(q);
603- fh->params = NULL;
604- fh->config = NULL;
605+ /* Free memory allocated to the buffers */
606+ for (i = 0 ; i < VIDEO_MAX_FRAME ; i++) {
607+ struct videobuf_dmabuf *dma = NULL;
608+ if (!q->bufs[i])
609+ continue;
610+ dma = videobuf_to_dma(q->bufs[i]);
611+ videobuf_dma_unmap(q, dma);
612+ videobuf_dma_free(dma);
613+ }
614
615+ videobuf_mmap_free(q);
616 fh->rsz_bufsize = 0;
617 filp->private_data = NULL;
618
619@@ -1286,7 +1491,8 @@ static int rsz_release(struct inode *inode, struct file *filp)
620 kfree(fh);
621
622 isp_put();
623-
624+ fh->params = NULL;
625+ fh->config = NULL;
626 return 0;
627 }
628
629@@ -1353,6 +1559,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
630 chanprotection_mutex))
631 return -EINTR;
632 ret = videobuf_reqbufs(&fh->vbq, (void *)&req_buf);
633+ if (ret >= 0) {
634+ if (copy_to_user((struct v4l2_requestbuffers *)arg,
635+ &req_buf, sizeof(struct
636+ v4l2_requestbuffers)))
637+ return -EFAULT;
638+ }
639 mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
640 break;
641 }
642@@ -1394,11 +1606,7 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
643 sizeof(struct rsz_params))) {
644 return -EFAULT;
645 }
646- if (mutex_lock_interruptible(&rsz_conf_chan->
647- chanprotection_mutex))
648- return -EINTR;
649- ret = rsz_set_params(fh->multipass, params, rsz_conf_chan);
650- mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
651+ ret = rsz_set_params(fh->multipass, fh->params, rsz_conf_chan);
652 break;
653 }
654 case RSZ_G_PARAM:
655@@ -1433,6 +1641,12 @@ static long rsz_unlocked_ioctl(struct file *file, unsigned int cmd,
656 rsz_calculate_crop(rsz_conf_chan, (struct rsz_cropsize *)arg);
657 break;
658
659+ case RSZ_S_EXP:
660+ if (mutex_lock_interruptible(&rsz_conf_chan->chanprotection_mutex))
661+ return -EINTR;
662+ rsz_conf_chan->register_config.sdr_req_exp = *((unsigned int *)arg);
663+ mutex_unlock(&rsz_conf_chan->chanprotection_mutex);
664+ break;
665 default:
666 dev_err(rsz_device, "resizer_ioctl: Invalid Command Value");
667 return -EINVAL;
668@@ -1535,14 +1749,18 @@ static int __init omap_rsz_init(void)
669 "memory\n");
670 return -ENOMEM;
671 }
672-
673+ device->extra_page_addr = __get_free_pages(GFP_KERNEL | GFP_DMA, 0);
674+ if (!device->extra_page_addr) {
675+ dev_err(rsz_device, OMAP_REZR_NAME ":Allocation failed. ");
676+ kfree(device);
677+ return -ENOMEM;
678+ }
679 ret = alloc_chrdev_region(&dev, 0, 1, OMAP_REZR_NAME);
680 if (ret < 0) {
681 dev_err(rsz_device, OMAP_REZR_NAME ": intialization failed. "
682 "Could not allocate region "
683 "for character device\n");
684- kfree(device);
685- return -ENODEV;
686+ goto fail1;
687 }
688
689 /* Register the driver in the kernel */
690@@ -1608,6 +1826,8 @@ fail3:
691 cdev_del(&c_dev);
692 fail2:
693 unregister_chrdev_region(dev, 1);
694+fail1:
695+ free_pages((unsigned long)device->extra_page_addr, 0);
696 kfree(device);
697 return ret;
698 }
699@@ -1623,6 +1843,7 @@ void __exit omap_rsz_exit(void)
700 platform_driver_unregister(&omap_resizer_driver);
701 cdev_del(&c_dev);
702 unregister_chrdev_region(dev, 1);
703+ free_pages((unsigned long)device_config->extra_page_addr, 0);
704 kfree(device_config);
705 }
706
707diff --git a/include/linux/omap_resizer.h b/include/linux/omap_resizer.h
708index 5ac0c88..47b8dd8 100644
709--- a/include/linux/omap_resizer.h
710+++ b/include/linux/omap_resizer.h
711@@ -21,7 +21,7 @@
712
713 /* ioctls definition */
714 #define RSZ_IOC_BASE 'R'
715-#define RSZ_IOC_MAXNR 8
716+#define RSZ_IOC_MAXNR 9
717
718 /*Ioctl options which are to be passed while calling the ioctl*/
719 #define RSZ_REQBUF _IOWR(RSZ_IOC_BASE, 1,\
720@@ -33,6 +33,7 @@
721 #define RSZ_G_STATUS _IOWR(RSZ_IOC_BASE, 6, struct rsz_status)
722 #define RSZ_QUEUEBUF _IOWR(RSZ_IOC_BASE, 7, struct v4l2_buffer)
723 #define RSZ_GET_CROPSIZE _IOWR(RSZ_IOC_BASE, 8, struct rsz_cropsize)
724+#define RSZ_S_EXP _IOWR(RSZ_IOC_BASE, 9, __s32)
725
726 #define RSZ_INTYPE_YCBCR422_16BIT 0
727 #define RSZ_INTYPE_PLANAR_8BIT 1
728--
7291.6.0.3
730
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch
new file mode 100644
index 0000000000..d9e4243b4a
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0001-V4L2-Add-COLORFX-user-control.patch
@@ -0,0 +1,44 @@
1From ad422f476ce04636f911557bbfd066c516e9b472 Mon Sep 17 00:00:00 2001
2From: Aguirre Rodriguez, Sergio Alberto <saaguirre@ti.com>
3Date: Tue, 20 Jan 2009 16:29:26 -0600
4Subject: [PATCH] V4L2: Add COLORFX user control
5
6From 07396d67b39bf7bcc81440d3e72d253ad6c54f11 Mon Sep 17 00:00:00 2001
7From: Sergio Aguirre <saaguirre@ti.com>
8Date: Tue, 20 Jan 2009 15:34:43 -0600
9Subject: [PATCH v2] V4L2: Add COLORFX user control
10
11This is a common feature on many cameras. the options are:
12Default colors,
13B & W,
14Sepia
15
16Signed-off-by: Sergio Aguirre <saaguirre@ti.com>
17---
18 include/linux/videodev2.h | 9 ++++++++-
19 1 files changed, 8 insertions(+), 1 deletions(-)
20
21diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
22index 5571dbe..8e4e25e 100644
23--- a/include/linux/videodev2.h
24+++ b/include/linux/videodev2.h
25@@ -879,8 +879,15 @@ enum v4l2_power_line_frequency {
26 #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28)
27 #define V4L2_CID_CHROMA_AGC (V4L2_CID_BASE+29)
28 #define V4L2_CID_COLOR_KILLER (V4L2_CID_BASE+30)
29+#define V4L2_CID_COLORFX (V4L2_CID_BASE+31)
30+enum v4l2_colorfx {
31+ V4L2_COLORFX_NONE = 0,
32+ V4L2_COLORFX_BW = 1,
33+ V4L2_COLORFX_SEPIA = 2,
34+};
35+
36 /* last CID + 1 */
37-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+31)
38+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+32)
39
40 /* MPEG-class control IDs defined by V4L2 */
41 #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
42--
431.5.6.5
44
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch
new file mode 100644
index 0000000000..45e27a2fda
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0002-V4L-Int-if-v4l2_int_device_try_attach_all-requires.patch
@@ -0,0 +1,50 @@
1From 5b007183d51543624bc9f582966f245a64157b57 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@nokia.com>
3Date: Fri, 31 Oct 2008 11:51:30 +0200
4Subject: [PATCH] V4L: Int if: v4l2_int_device_try_attach_all requires mutex
5
6Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
7---
8 drivers/media/video/v4l2-int-device.c | 12 ++++++++++--
9 1 files changed, 10 insertions(+), 2 deletions(-)
10
11diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
12index a935bae..eb8dc84 100644
13--- a/drivers/media/video/v4l2-int-device.c
14+++ b/drivers/media/video/v4l2-int-device.c
15@@ -32,7 +32,7 @@
16 static DEFINE_MUTEX(mutex);
17 static LIST_HEAD(int_list);
18
19-void v4l2_int_device_try_attach_all(void)
20+static void __v4l2_int_device_try_attach_all(void)
21 {
22 struct v4l2_int_device *m, *s;
23
24@@ -66,6 +66,14 @@ void v4l2_int_device_try_attach_all(void)
25 }
26 }
27 }
28+
29+void v4l2_int_device_try_attach_all(void)
30+{
31+ mutex_lock(&mutex);
32+ __v4l2_int_device_try_attach_all();
33+ mutex_unlock(&mutex);
34+}
35+
36 EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all);
37
38 static int ioctl_sort_cmp(const void *a, const void *b)
39@@ -89,7 +97,7 @@ int v4l2_int_device_register(struct v4l2_int_device *d)
40 &ioctl_sort_cmp, NULL);
41 mutex_lock(&mutex);
42 list_add(&d->head, &int_list);
43- v4l2_int_device_try_attach_all();
44+ __v4l2_int_device_try_attach_all();
45 mutex_unlock(&mutex);
46
47 return 0;
48--
491.5.6.5
50
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch
new file mode 100644
index 0000000000..829810fab0
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0003-V4L-Int-if-Dummy-slave.patch
@@ -0,0 +1,61 @@
1From cc1d76e0f50321e80f7f50e9e214de2c9a45628a Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@nokia.com>
3Date: Wed, 22 Oct 2008 18:41:20 +0300
4Subject: [PATCH] V4L: Int if: Dummy slave
5
6This patch implements a dummy slave that has no functionality. Helps
7managing slaves in the OMAP 3 camera driver; no need to check for NULL
8pointers.
9
10Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
11---
12 drivers/media/video/v4l2-int-device.c | 19 +++++++++++++++++++
13 include/media/v4l2-int-device.h | 2 ++
14 2 files changed, 21 insertions(+), 0 deletions(-)
15
16diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c
17index eb8dc84..483ee2e 100644
18--- a/drivers/media/video/v4l2-int-device.c
19+++ b/drivers/media/video/v4l2-int-device.c
20@@ -67,6 +67,25 @@ static void __v4l2_int_device_try_attach_all(void)
21 }
22 }
23
24+static struct v4l2_int_slave dummy_slave = {
25+ /* Dummy pointer to avoid underflow in find_ioctl. */
26+ .ioctls = (void *)sizeof(struct v4l2_int_ioctl_desc),
27+ .num_ioctls = 0,
28+};
29+
30+static struct v4l2_int_device dummy = {
31+ .type = v4l2_int_type_slave,
32+ .u = {
33+ .slave = &dummy_slave,
34+ },
35+};
36+
37+struct v4l2_int_device *v4l2_int_device_dummy()
38+{
39+ return &dummy;
40+}
41+EXPORT_SYMBOL_GPL(v4l2_int_device_dummy);
42+
43 void v4l2_int_device_try_attach_all(void)
44 {
45 mutex_lock(&mutex);
46diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
47index fbf5855..5d254c4 100644
48--- a/include/media/v4l2-int-device.h
49+++ b/include/media/v4l2-int-device.h
50@@ -84,6 +84,8 @@ struct v4l2_int_device {
51 void *priv;
52 };
53
54+struct v4l2_int_device *v4l2_int_device_dummy(void);
55+
56 void v4l2_int_device_try_attach_all(void);
57
58 int v4l2_int_device_register(struct v4l2_int_device *d);
59--
601.5.6.5
61
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch
new file mode 100644
index 0000000000..b81b20419e
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0004-V4L-int-device-add-support-for-VIDIOC_QUERYMENU.patch
@@ -0,0 +1,33 @@
1From e041e57cafca24cf92430cdf3cc091060a271e19 Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@nokia.com>
3Date: Fri, 31 Oct 2008 10:20:31 +0200
4Subject: [PATCH] V4L: int device: add support for VIDIOC_QUERYMENU
5
6Signed-off-by: Tuukka Toivonen <tuukka.o.toivonen@nokia.com>
7---
8 include/media/v4l2-int-device.h | 2 ++
9 1 files changed, 2 insertions(+), 0 deletions(-)
10
11diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
12index 5d254c4..81f4863 100644
13--- a/include/media/v4l2-int-device.h
14+++ b/include/media/v4l2-int-device.h
15@@ -178,6 +178,7 @@ enum v4l2_int_ioctl_num {
16 vidioc_int_s_fmt_cap_num,
17 vidioc_int_try_fmt_cap_num,
18 vidioc_int_queryctrl_num,
19+ vidioc_int_querymenu_num,
20 vidioc_int_g_ctrl_num,
21 vidioc_int_s_ctrl_num,
22 vidioc_int_cropcap_num,
23@@ -282,6 +283,7 @@ V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
24 V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
25 V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *);
26 V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *);
27+V4L2_INT_WRAPPER_1(querymenu, struct v4l2_querymenu, *);
28 V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *);
29 V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *);
30 V4L2_INT_WRAPPER_1(cropcap, struct v4l2_cropcap, *);
31--
321.5.6.5
33
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch
new file mode 100644
index 0000000000..a9e06290fa
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/v4l/0005-V4L-Int-if-Add-vidioc_int_querycap.patch
@@ -0,0 +1,35 @@
1From dc05ee10583dca44e0f8d4109bd1397ee3c5ffae Mon Sep 17 00:00:00 2001
2From: Sakari Ailus <sakari.ailus@nokia.com>
3Date: Thu, 2 Oct 2008 11:55:07 +0300
4Subject: [PATCH] V4L: Int if: Add vidioc_int_querycap
5
6Signed-off-by: Sakari Ailus <sakari.ailus@nokia.com>
7---
8 include/media/v4l2-int-device.h | 4 +++-
9 1 files changed, 3 insertions(+), 1 deletions(-)
10
11diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h
12index 81f4863..2830ae1 100644
13--- a/include/media/v4l2-int-device.h
14+++ b/include/media/v4l2-int-device.h
15@@ -173,7 +173,8 @@ enum v4l2_int_ioctl_num {
16 * "Proper" V4L ioctls, as in struct video_device.
17 *
18 */
19- vidioc_int_enum_fmt_cap_num = 1,
20+ vidioc_int_querycap_num = 1,
21+ vidioc_int_enum_fmt_cap_num,
22 vidioc_int_g_fmt_cap_num,
23 vidioc_int_s_fmt_cap_num,
24 vidioc_int_try_fmt_cap_num,
25@@ -278,6 +279,7 @@ enum v4l2_int_ioctl_num {
26 return desc; \
27 }
28
29+V4L2_INT_WRAPPER_1(querycap, struct v4l2_capability, *);
30 V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *);
31 V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
32 V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
33--
341.5.6.5
35