diff options
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.patch | 1875 |
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 @@ | |||
1 | From 9ea796fe5383a6961125a6a18185a901fe8627d7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
3 | Date: Tue, 10 Mar 2009 10:49:02 +0200 | ||
4 | Subject: [PATCH] omap3isp: Add ISP frontend (CCDC) | ||
5 | |||
6 | Signed-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 | |||
14 | diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c | ||
15 | new file mode 100644 | ||
16 | index 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 | +} | ||
1658 | diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h | ||
1659 | new file mode 100644 | ||
1660 | index 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 | -- | ||
1874 | 1.5.6.5 | ||
1875 | |||