summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/isp
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
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