summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
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/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch
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/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch1875
1 files changed, 1875 insertions, 0 deletions
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