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:
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