Full support for Ginger Console
[linux-ginger.git] / drivers / media / video / isp / isppreview.c
blob44099bee6afa587b3cce84d04a5ea9e502d4f642
1 /*
2 * isppreview.c
4 * Driver Library for Preview module in TI's OMAP3 Camera ISP
6 * Copyright (C) 2009 Texas Instruments, Inc.
8 * Contributors:
9 * Senthilvadivu Guruswamy <svadivu@ti.com>
10 * Pallavi Kulkarni <p-kulkarni@ti.com>
11 * Sergio Aguirre <saaguirre@ti.com>
13 * This package is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
17 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 #include <linux/mutex.h>
23 #include <linux/module.h>
24 #include <linux/uaccess.h>
25 #include <linux/device.h>
27 #include "isp.h"
28 #include "ispreg.h"
29 #include "isppreview.h"
31 /* Structure for saving/restoring preview module registers */
32 static struct isp_reg ispprev_reg_list[] = {
33 {OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO, 0x0000},
34 {OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO, 0x0000},
35 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR, 0x0000},
36 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET, 0x0000},
37 {OMAP3_ISP_IOMEM_PREV, ISPPRV_DSDR_ADDR, 0x0000},
38 {OMAP3_ISP_IOMEM_PREV, ISPPRV_DRKF_OFFSET, 0x0000},
39 {OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR, 0x0000},
40 {OMAP3_ISP_IOMEM_PREV, ISPPRV_WADD_OFFSET, 0x0000},
41 {OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE, 0x0000},
42 {OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED, 0x0000},
43 {OMAP3_ISP_IOMEM_PREV, ISPPRV_NF, 0x0000},
44 {OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN, 0x0000},
45 {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN, 0x0000},
46 {OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL, 0x0000},
47 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA, 0x0000},
48 {OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF, 0x0000},
49 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1, 0x0000},
50 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2, 0x0000},
51 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3, 0x0000},
52 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4, 0x0000},
53 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5, 0x0000},
54 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1, 0x0000},
55 {OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2, 0x0000},
56 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0, 0x0000},
57 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1, 0x0000},
58 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2, 0x0000},
59 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET, 0x0000},
60 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT, 0x0000},
61 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP, 0x0000},
62 {OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC, 0x0000},
63 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0, 0x0000},
64 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1, 0x0000},
65 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2, 0x0000},
66 {OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3, 0x0000},
67 {OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, 0x0000},
68 {0, ISP_TOK_TERM, 0x0000}
72 /* Default values in Office Flourescent Light for RGBtoRGB Blending */
73 static struct ispprev_rgbtorgb flr_rgb2rgb = {
74 { /* RGB-RGB Matrix */
75 {0x01E2, 0x0F30, 0x0FEE},
76 {0x0F9B, 0x01AC, 0x0FB9},
77 {0x0FE0, 0x0EC0, 0x0260}
78 }, /* RGB Offset */
79 {0x0000, 0x0000, 0x0000}
82 /* Default values in Office Flourescent Light for RGB to YUV Conversion*/
83 static struct ispprev_csc flr_prev_csc[] = {
85 { /* CSC Coef Matrix */
86 {66, 129, 25},
87 {-38, -75, 112},
88 {112, -94 , -18}
89 }, /* CSC Offset */
90 {0x0, 0x0, 0x0}
93 { /* CSC Coef Matrix BW */
94 {66, 129, 25},
95 {0, 0, 0},
96 {0, 0, 0}
97 }, /* CSC Offset */
98 {0x0, 0x0, 0x0}
101 { /* CSC Coef Matrix Sepia */
102 {19, 38, 7},
103 {0, 0, 0},
104 {0, 0, 0}
105 }, /* CSC Offset */
106 {0x0, 0xE7, 0x14}
111 /* Default values in Office Flourescent Light for CFA Gradient*/
112 #define FLR_CFA_GRADTHRS_HORZ 0x28
113 #define FLR_CFA_GRADTHRS_VERT 0x28
115 /* Default values in Office Flourescent Light for Chroma Suppression*/
116 #define FLR_CSUP_GAIN 0x0D
117 #define FLR_CSUP_THRES 0xEB
119 /* Default values in Office Flourescent Light for Noise Filter*/
120 #define FLR_NF_STRGTH 0x03
122 /* Default values in Office Flourescent Light for White Balance*/
123 #define FLR_WBAL_DGAIN 0x100
124 #define FLR_WBAL_COEF0 0x29
125 #define FLR_WBAL_COEF1 0x20
126 #define FLR_WBAL_COEF2 0x20
127 #define FLR_WBAL_COEF3 0x2d
129 #define FLR_WBAL_COEF0_ES1 0x23
130 #define FLR_WBAL_COEF1_ES1 0x20
131 #define FLR_WBAL_COEF2_ES1 0x20
132 #define FLR_WBAL_COEF3_ES1 0x39
134 /* Default values in Office Flourescent Light for Black Adjustment*/
135 #define FLR_BLKADJ_BLUE 0x0
136 #define FLR_BLKADJ_GREEN 0x0
137 #define FLR_BLKADJ_RED 0x0
140 * Coeficient Tables for the submodules in Preview.
141 * Array is initialised with the values from.the tables text file.
145 * CFA Filter Coefficient Table
148 static u32 cfa_coef_table[] = {
149 #include "cfa_coef_table.h"
153 * Gamma Correction Table - Red
155 static u32 redgamma_table[] = {
156 #include "redgamma_table.h"
160 * Gamma Correction Table - Green
162 static u32 greengamma_table[] = {
163 #include "greengamma_table.h"
167 * Gamma Correction Table - Blue
169 static u32 bluegamma_table[] = {
170 #include "bluegamma_table.h"
174 * Noise Filter Threshold table
176 static u32 noise_filter_table[] = {
177 #include "noise_filter_table.h"
181 * Luminance Enhancement Table
183 static u32 luma_enhance_table[] = {
184 #include "luma_enhance_table.h"
187 static int omap34xx_isp_tables_update(struct isp_prev_device *isp_prev,
188 struct isptables_update *isptables_struct);
192 * omap34xx_isp_preview_config - Abstraction layer Preview configuration.
193 * @userspace_add: Pointer from Userspace to structure with flags and data to
194 * update.
196 int omap34xx_isp_preview_config(struct isp_prev_device *isp_prev,
197 void *userspace_add)
199 struct isp_device *isp =
200 container_of(isp_prev, struct isp_device, isp_prev);
201 struct ispprev_hmed prev_hmed_t;
202 struct ispprev_csup csup_t;
203 struct ispprev_wbal prev_wbal_t;
204 struct ispprev_blkadj prev_blkadj_t;
205 struct ispprev_yclimit yclimit_t;
206 struct ispprev_dcor prev_dcor_t;
207 struct ispprv_update_config *config;
208 struct isptables_update isp_table_update;
209 int yen_t[ISPPRV_YENH_TBL_SIZE];
210 unsigned long flags;
212 if (userspace_add == NULL)
213 return -EINVAL;
215 spin_lock_irqsave(&isp_prev->lock, flags);
216 isp_prev->shadow_update = 1;
217 spin_unlock_irqrestore(&isp_prev->lock, flags);
219 config = userspace_add;
221 if (isp->running != ISP_STOPPED)
222 goto out_config_shadow;
224 if (ISP_ABS_PREV_LUMAENH & config->flag) {
225 if (ISP_ABS_PREV_LUMAENH & config->update) {
226 if (copy_from_user(yen_t, config->yen,
227 sizeof(yen_t)))
228 goto err_copy_from_user;
229 isppreview_config_luma_enhancement(isp_prev, yen_t);
231 isp_prev->params.features |= PREV_LUMA_ENHANCE;
232 } else if (ISP_ABS_PREV_LUMAENH & config->update)
233 isp_prev->params.features &= ~PREV_LUMA_ENHANCE;
235 if (ISP_ABS_PREV_INVALAW & config->flag) {
236 isppreview_enable_invalaw(isp_prev, 1);
237 isp_prev->params.features |= PREV_INVERSE_ALAW;
238 } else {
239 isppreview_enable_invalaw(isp_prev, 0);
240 isp_prev->params.features &= ~PREV_INVERSE_ALAW;
243 if (ISP_ABS_PREV_HRZ_MED & config->flag) {
244 if (ISP_ABS_PREV_HRZ_MED & config->update) {
245 if (copy_from_user(&prev_hmed_t,
246 (struct ispprev_hmed *)
247 config->prev_hmed,
248 sizeof(struct ispprev_hmed)))
249 goto err_copy_from_user;
250 isppreview_config_hmed(isp_prev, prev_hmed_t);
252 isppreview_enable_hmed(isp_prev, 1);
253 isp_prev->params.features |= PREV_HORZ_MEDIAN_FILTER;
254 } else if (ISP_ABS_PREV_HRZ_MED & config->update) {
255 isppreview_enable_hmed(isp_prev, 0);
256 isp_prev->params.features &= ~PREV_HORZ_MEDIAN_FILTER;
259 if (ISP_ABS_PREV_CHROMA_SUPP & config->flag) {
260 if (ISP_ABS_PREV_CHROMA_SUPP & config->update) {
261 if (copy_from_user(&csup_t,
262 (struct ispprev_csup *)
263 config->csup,
264 sizeof(struct ispprev_csup)))
265 goto err_copy_from_user;
266 isppreview_config_chroma_suppression(isp_prev, csup_t);
268 isppreview_enable_chroma_suppression(isp_prev, 1);
269 isp_prev->params.features |= PREV_CHROMA_SUPPRESS;
270 } else if (ISP_ABS_PREV_CHROMA_SUPP & config->update) {
271 isppreview_enable_chroma_suppression(isp_prev, 0);
272 isp_prev->params.features &= ~PREV_CHROMA_SUPPRESS;
275 if (ISP_ABS_PREV_WB & config->update) {
276 if (copy_from_user(&prev_wbal_t, (struct ispprev_wbal *)
277 config->prev_wbal,
278 sizeof(struct ispprev_wbal)))
279 goto err_copy_from_user;
280 isppreview_config_whitebalance(isp_prev, prev_wbal_t);
283 if (ISP_ABS_PREV_BLKADJ & config->update) {
284 if (copy_from_user(&prev_blkadj_t, (struct ispprev_blkadjl *)
285 config->prev_blkadj,
286 sizeof(struct ispprev_blkadj)))
287 goto err_copy_from_user;
288 isppreview_config_blkadj(isp_prev, prev_blkadj_t);
291 if (ISP_ABS_PREV_YC_LIMIT & config->update) {
292 if (copy_from_user(&yclimit_t, (struct ispprev_yclimit *)
293 config->yclimit,
294 sizeof(struct ispprev_yclimit)))
295 goto err_copy_from_user;
296 isppreview_config_yc_range(isp_prev, yclimit_t);
299 if (ISP_ABS_PREV_DEFECT_COR & config->flag) {
300 if (ISP_ABS_PREV_DEFECT_COR & config->update) {
301 if (copy_from_user(&prev_dcor_t,
302 (struct ispprev_dcor *)
303 config->prev_dcor,
304 sizeof(struct ispprev_dcor)))
305 goto err_copy_from_user;
306 isppreview_config_dcor(isp_prev, prev_dcor_t);
308 isppreview_enable_dcor(isp_prev, 1);
309 isp_prev->params.features |= PREV_DEFECT_COR;
310 } else if (ISP_ABS_PREV_DEFECT_COR & config->update) {
311 isppreview_enable_dcor(isp_prev, 0);
312 isp_prev->params.features &= ~PREV_DEFECT_COR;
315 if (ISP_ABS_PREV_GAMMABYPASS & config->flag) {
316 isppreview_enable_gammabypass(isp_prev, 1);
317 isp_prev->params.features |= PREV_GAMMA_BYPASS;
318 } else {
319 isppreview_enable_gammabypass(isp_prev, 0);
320 isp_prev->params.features &= ~PREV_GAMMA_BYPASS;
323 out_config_shadow:
324 if (ISP_ABS_PREV_RGB2RGB & config->update) {
325 if (copy_from_user(&isp_prev->params.rgb2rgb,
326 (struct ispprev_rgbtorgb *)
327 config->rgb2rgb,
328 sizeof(struct ispprev_rgbtorgb)))
329 goto err_copy_from_user;
330 isppreview_config_rgb_blending(isp_prev,
331 isp_prev->params.rgb2rgb);
332 /* The function call above prevents compiler from reordering
333 * writes so that the flag below is always set after
334 * isp_prev->params.rgb2rgb is written to. */
335 isp_prev->update_rgb_blending = 1;
338 if (ISP_ABS_PREV_COLOR_CONV & config->update) {
339 if (copy_from_user(&isp_prev->params.rgb2ycbcr,
340 (struct ispprev_csc *)
341 config->prev_csc,
342 sizeof(struct ispprev_csc)))
343 goto err_copy_from_user;
344 isppreview_config_rgb_to_ycbcr(isp_prev,
345 isp_prev->params.rgb2ycbcr);
346 /* Same here... this flag has to be set after rgb2ycbcr
347 * structure is written to. */
348 isp_prev->update_rgb_to_ycbcr = 1;
351 isp_table_update.update = config->update;
352 isp_table_update.flag = config->flag;
353 isp_table_update.prev_nf = config->prev_nf;
354 isp_table_update.red_gamma = config->red_gamma;
355 isp_table_update.green_gamma = config->green_gamma;
356 isp_table_update.blue_gamma = config->blue_gamma;
357 isp_table_update.prev_cfa = config->prev_cfa;
359 if (omap34xx_isp_tables_update(isp_prev, &isp_table_update))
360 goto err_copy_from_user;
362 spin_lock_irqsave(&isp_prev->lock, flags);
363 isp_prev->shadow_update = 0;
364 spin_unlock_irqrestore(&isp_prev->lock, flags);
366 return 0;
368 err_copy_from_user:
369 spin_lock_irqsave(&isp_prev->lock, flags);
370 isp_prev->shadow_update = 0;
371 spin_unlock_irqrestore(&isp_prev->lock, flags);
373 dev_err(isp_prev->dev, "preview: Config: Copy From User Error\n");
374 return -EFAULT;
376 EXPORT_SYMBOL_GPL(omap34xx_isp_preview_config);
379 * omap34xx_isp_tables_update - Abstraction layer Tables update.
380 * @isptables_struct: Pointer from Userspace to structure with flags and table
381 * data to update.
383 static int omap34xx_isp_tables_update(struct isp_prev_device *isp_prev,
384 struct isptables_update *isptables_struct)
387 if (ISP_ABS_TBL_NF & isptables_struct->flag) {
388 isp_prev->nf_enable = 1;
389 isp_prev->params.features |= PREV_NOISE_FILTER;
390 if (ISP_ABS_TBL_NF & isptables_struct->update) {
391 if (copy_from_user(&isp_prev->prev_nf_t,
392 (struct ispprev_nf *)
393 isptables_struct->prev_nf,
394 sizeof(struct ispprev_nf)))
395 goto err_copy_from_user;
397 isp_prev->nf_update = 1;
398 } else
399 isp_prev->nf_update = 0;
400 } else {
401 isp_prev->nf_enable = 0;
402 isp_prev->params.features &= ~PREV_NOISE_FILTER;
403 if (ISP_ABS_TBL_NF & isptables_struct->update)
404 isp_prev->nf_update = 1;
405 else
406 isp_prev->nf_update = 0;
409 if (ISP_ABS_TBL_REDGAMMA & isptables_struct->update) {
410 if (copy_from_user(redgamma_table, isptables_struct->red_gamma,
411 sizeof(redgamma_table))) {
412 goto err_copy_from_user;
414 isp_prev->rg_update = 1;
415 } else
416 isp_prev->rg_update = 0;
418 if (ISP_ABS_TBL_GREENGAMMA & isptables_struct->update) {
419 if (copy_from_user(greengamma_table,
420 isptables_struct->green_gamma,
421 sizeof(greengamma_table)))
422 goto err_copy_from_user;
423 isp_prev->gg_update = 1;
424 } else
425 isp_prev->gg_update = 0;
427 if (ISP_ABS_TBL_BLUEGAMMA & isptables_struct->update) {
428 if (copy_from_user(bluegamma_table,
429 isptables_struct->blue_gamma,
430 sizeof(bluegamma_table))) {
431 goto err_copy_from_user;
433 isp_prev->bg_update = 1;
434 } else
435 isp_prev->bg_update = 0;
437 if (ISP_ABS_PREV_CFA & isptables_struct->update) {
438 struct ispprev_cfa cfa;
439 if (isptables_struct->prev_cfa) {
440 if (copy_from_user(&cfa,
441 isptables_struct->prev_cfa,
442 sizeof(struct ispprev_cfa)))
443 goto err_copy_from_user;
444 if (cfa.cfa_table != NULL) {
445 if (copy_from_user(cfa_coef_table,
446 cfa.cfa_table,
447 sizeof(cfa_coef_table)))
448 goto err_copy_from_user;
450 cfa.cfa_table = cfa_coef_table;
451 isp_prev->params.cfa = cfa;
453 if (ISP_ABS_PREV_CFA & isptables_struct->flag) {
454 isp_prev->cfa_en = 1;
455 isp_prev->params.features |= PREV_CFA;
456 } else {
457 isp_prev->cfa_en = 0;
458 isp_prev->params.features &= ~PREV_CFA;
460 isp_prev->cfa_update = 1;
463 return 0;
465 err_copy_from_user:
466 dev_err(isp_prev->dev, "preview tables: Copy From User Error\n");
467 return -EFAULT;
471 * isppreview_config_shadow_registers - Program shadow registers for preview.
473 * Allows user to program shadow registers associated with preview module.
475 void isppreview_config_shadow_registers(struct isp_prev_device *isp_prev)
477 u8 current_brightness_contrast;
478 int ctr;
479 unsigned long flags;
481 spin_lock_irqsave(&isp_prev->lock, flags);
482 if (isp_prev->shadow_update) {
483 spin_unlock_irqrestore(&isp_prev->lock, flags);
484 return;
487 isppreview_query_brightness(isp_prev, &current_brightness_contrast);
488 if (current_brightness_contrast != isp_prev->brightness) {
489 DPRINTK_ISPPREV(" Changing Brightness level to %d\n",
490 isp_prev->brightness);
491 isppreview_config_brightness(isp_prev, isp_prev->brightness);
494 isppreview_query_contrast(isp_prev, &current_brightness_contrast);
495 if (current_brightness_contrast != isp_prev->contrast) {
496 DPRINTK_ISPPREV(" Changing Contrast level to %d\n",
497 isp_prev->contrast);
498 isppreview_config_contrast(isp_prev, isp_prev->contrast);
500 if (isp_prev->update_color_matrix) {
501 isppreview_config_rgb_to_ycbcr(isp_prev,
502 flr_prev_csc[isp_prev->color]);
503 isp_prev->update_color_matrix = 0;
505 if (isp_prev->update_rgb_blending) {
506 isp_prev->update_rgb_blending = 0;
507 isppreview_config_rgb_blending(isp_prev,
508 isp_prev->params.rgb2rgb);
510 if (isp_prev->update_rgb_to_ycbcr) {
511 isp_prev->update_rgb_to_ycbcr = 0;
512 isppreview_config_rgb_to_ycbcr(isp_prev,
513 isp_prev->params.rgb2ycbcr);
516 if (isp_prev->gg_update) {
517 isp_reg_writel(isp_prev->dev, ISPPRV_TBL_ADDR_GREEN_G_START,
518 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
520 for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
521 isp_reg_writel(isp_prev->dev, greengamma_table[ctr],
522 OMAP3_ISP_IOMEM_PREV,
523 ISPPRV_SET_TBL_DATA);
525 isp_prev->gg_update = 0;
528 if (isp_prev->rg_update) {
529 isp_reg_writel(isp_prev->dev, ISPPRV_TBL_ADDR_RED_G_START,
530 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
532 for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
533 isp_reg_writel(isp_prev->dev, redgamma_table[ctr],
534 OMAP3_ISP_IOMEM_PREV,
535 ISPPRV_SET_TBL_DATA);
537 isp_prev->rg_update = 0;
540 if (isp_prev->bg_update) {
541 isp_reg_writel(isp_prev->dev, ISPPRV_TBL_ADDR_BLUE_G_START,
542 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
544 for (ctr = 0; ctr < ISP_GAMMA_TABLE_SIZE; ctr++) {
545 isp_reg_writel(isp_prev->dev, bluegamma_table[ctr],
546 OMAP3_ISP_IOMEM_PREV,
547 ISPPRV_SET_TBL_DATA);
549 isp_prev->bg_update = 0;
552 if (isp_prev->cfa_update) {
553 isp_prev->cfa_update = 0;
554 isppreview_config_cfa(isp_prev, &isp_prev->params.cfa);
555 isppreview_enable_cfa(isp_prev, isp_prev->cfa_en);
558 if (isp_prev->nf_update && isp_prev->nf_enable) {
559 isp_reg_writel(isp_prev->dev, 0xC00,
560 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
561 isp_reg_writel(isp_prev->dev, isp_prev->prev_nf_t.spread,
562 OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
563 for (ctr = 0; ctr < ISPPRV_NF_TBL_SIZE; ctr++) {
564 isp_reg_writel(isp_prev->dev,
565 isp_prev->prev_nf_t.table[ctr],
566 OMAP3_ISP_IOMEM_PREV,
567 ISPPRV_SET_TBL_DATA);
569 isppreview_enable_noisefilter(isp_prev, 1);
570 isp_prev->nf_update = 0;
573 if (~isp_prev->nf_update && isp_prev->nf_enable)
574 isppreview_enable_noisefilter(isp_prev, 1);
576 if (isp_prev->nf_update && ~isp_prev->nf_enable)
577 isppreview_enable_noisefilter(isp_prev, 0);
579 spin_unlock_irqrestore(&isp_prev->lock, flags);
581 EXPORT_SYMBOL_GPL(isppreview_config_shadow_registers);
584 * isppreview_request - Reserves the preview module.
586 * Returns 0 if successful, or -EBUSY if the module was already reserved.
588 int isppreview_request(struct isp_prev_device *isp_prev)
590 isp_reg_or(isp_prev->dev,
591 OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_PREV_RAM_EN |
592 ISPCTRL_PREV_CLK_EN | ISPCTRL_SBL_WR1_RAM_EN);
593 return 0;
595 EXPORT_SYMBOL_GPL(isppreview_request);
598 * isppreview_free - Frees the preview module.
600 * Returns 0 if successful, or -EINVAL if the module was already freed.
602 int isppreview_free(struct isp_prev_device *isp_prev)
604 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
605 ~(ISPCTRL_PREV_CLK_EN |
606 ISPCTRL_PREV_RAM_EN |
607 ISPCTRL_SBL_WR1_RAM_EN));
609 return 0;
611 EXPORT_SYMBOL_GPL(isppreview_free);
613 /** isppreview_config_datapath - Specifies input and output modules for Preview
614 * @input: Indicates the module that gives the image to preview.
615 * @output: Indicates the module to which the preview outputs to.
617 * Configures the default configuration for the CCDC to work with.
619 * The valid values for the input are PRV_RAW_CCDC (0), PRV_RAW_MEM (1),
620 * PRV_RGBBAYERCFA (2), PRV_COMPCFA (3), PRV_CCDC_DRKF (4), PRV_OTHERS (5).
622 * The valid values for the output are PREVIEW_RSZ (0), PREVIEW_MEM (1).
624 * Returns 0 if successful, or -EINVAL if wrong input or output values are
625 * specified.
627 int isppreview_config_datapath(struct isp_prev_device *isp_prev,
628 struct isp_pipeline *pipe)
630 u32 pcr = 0;
631 u8 enable = 0;
632 struct prev_params *params = &isp_prev->params;
633 struct ispprev_yclimit yclimit;
635 pcr = isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
637 switch (pipe->prv_in) {
638 case PRV_RAW_CCDC:
639 pcr &= ~ISPPRV_PCR_SOURCE;
640 break;
641 case PRV_RAW_MEM:
642 pcr |= ISPPRV_PCR_SOURCE;
643 break;
644 case PRV_CCDC_DRKF:
645 pcr |= ISPPRV_PCR_DRKFCAP;
646 break;
647 case PRV_COMPCFA:
648 break;
649 case PRV_OTHERS:
650 break;
651 case PRV_RGBBAYERCFA:
652 break;
653 default:
654 dev_err(isp_prev->dev, "preview: Wrong Input\n");
655 return -EINVAL;
658 switch (pipe->prv_out) {
659 case PREVIEW_RSZ:
660 pcr |= ISPPRV_PCR_RSZPORT;
661 pcr &= ~ISPPRV_PCR_SDRPORT;
662 break;
663 case PREVIEW_MEM:
664 pcr &= ~ISPPRV_PCR_RSZPORT;
665 pcr |= ISPPRV_PCR_SDRPORT;
666 break;
667 default:
668 dev_err(isp_prev->dev, "preview: Wrong Output\n");
669 return -EINVAL;
672 isp_reg_writel(isp_prev->dev, pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
674 if (params->csup.hypf_en == 1)
675 isppreview_config_chroma_suppression(isp_prev, params->csup);
676 if (params->ytable != NULL)
677 isppreview_config_luma_enhancement(isp_prev, params->ytable);
679 if (params->gtable.redtable != NULL)
680 isppreview_config_gammacorrn(isp_prev, params->gtable);
682 isp_prev->cfa_update = 0;
683 isppreview_config_cfa(isp_prev, &params->cfa);
684 enable = (params->features & PREV_CFA) ? 1 : 0;
685 isppreview_enable_cfa(isp_prev, enable);
687 enable = (params->features & PREV_CHROMA_SUPPRESS) ? 1 : 0;
688 isppreview_enable_chroma_suppression(isp_prev, enable);
690 enable = (params->features & PREV_LUMA_ENHANCE) ? 1 : 0;
691 isppreview_enable_luma_enhancement(isp_prev, enable);
693 enable = (params->features & PREV_NOISE_FILTER) ? 1 : 0;
694 if (enable)
695 isppreview_config_noisefilter(isp_prev, params->nf);
696 isppreview_enable_noisefilter(isp_prev, enable);
698 enable = (params->features & PREV_DEFECT_COR) ? 1 : 0;
699 if (enable)
700 isppreview_config_dcor(isp_prev, params->dcor);
701 isppreview_enable_dcor(isp_prev, enable);
703 enable = (params->features & PREV_GAMMA_BYPASS) ? 1 : 0;
704 isppreview_enable_gammabypass(isp_prev, enable);
706 isppreview_config_whitebalance(isp_prev, params->wbal);
707 isppreview_config_blkadj(isp_prev, params->blk_adj);
708 isppreview_config_rgb_blending(isp_prev, params->rgb2rgb);
709 isppreview_config_rgb_to_ycbcr(isp_prev, params->rgb2ycbcr);
711 isppreview_config_contrast(isp_prev, params->contrast);
712 isppreview_config_brightness(isp_prev, params->brightness);
714 yclimit.minC = ISPPRV_YC_MIN;
715 yclimit.maxC = ISPPRV_YC_MAX;
716 yclimit.minY = ISPPRV_YC_MIN;
717 yclimit.maxY = ISPPRV_YC_MAX;
718 isppreview_config_yc_range(isp_prev, yclimit);
720 return 0;
722 EXPORT_SYMBOL_GPL(isppreview_config_datapath);
725 * isppreview_set_skip - Set the number of rows/columns that should be skipped.
726 * h - Start Pixel Horizontal.
727 * v - Start Line Vertical.
729 void isppreview_set_skip(struct isp_prev_device *isp_prev, u32 h, u32 v)
731 isp_prev->sph = h;
732 isp_prev->slv = v;
734 EXPORT_SYMBOL_GPL(isppreview_set_skip);
737 * isppreview_config_ycpos - Configure byte layout of YUV image.
738 * @mode: Indicates the required byte layout.
740 void isppreview_config_ycpos(struct isp_prev_device *isp_prev,
741 enum preview_ycpos_mode mode)
743 u32 pcr = isp_reg_readl(isp_prev->dev,
744 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
745 pcr &= ~ISPPRV_PCR_YCPOS_CrYCbY;
746 pcr |= (mode << ISPPRV_PCR_YCPOS_SHIFT);
747 isp_reg_writel(isp_prev->dev, pcr, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
749 EXPORT_SYMBOL_GPL(isppreview_config_ycpos);
752 * isppreview_config_averager - Enable / disable / configure averager
753 * @average: Average value to be configured.
755 void isppreview_config_averager(struct isp_prev_device *isp_prev, u8 average)
757 int reg = 0;
759 reg = AVE_ODD_PIXEL_DIST | AVE_EVEN_PIXEL_DIST | average;
760 isp_reg_writel(isp_prev->dev, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
762 EXPORT_SYMBOL_GPL(isppreview_config_averager);
765 * isppreview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
766 * @enable: 1 - Reverse the A-Law done in CCDC.
768 void isppreview_enable_invalaw(struct isp_prev_device *isp_prev, u8 enable)
770 u32 pcr_val = 0;
771 pcr_val = isp_reg_readl(isp_prev->dev,
772 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
774 if (enable) {
775 isp_reg_writel(isp_prev->dev,
776 pcr_val | ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW,
777 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
778 } else {
779 isp_reg_writel(isp_prev->dev, pcr_val &
780 ~(ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW),
781 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
784 EXPORT_SYMBOL_GPL(isppreview_enable_invalaw);
787 * isppreview_enable_drkframe - Enable/Disable of the darkframe subtract.
788 * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
789 * subtracted with the pixels in the current frame.
791 * The proccess is applied for each captured frame.
793 void isppreview_enable_drkframe(struct isp_prev_device *isp_prev, u8 enable)
795 if (enable)
796 isp_reg_or(isp_prev->dev,
797 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_DRKFEN);
798 else {
799 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
800 ~ISPPRV_PCR_DRKFEN);
803 EXPORT_SYMBOL_GPL(isppreview_enable_drkframe);
806 * isppreview_enable_shadcomp - Enables/Disables the shading compensation.
807 * @enable: 1 - Enables the shading compensation.
809 * If dark frame subtract won't be used, then enable this shading
810 * compensation.
812 void isppreview_enable_shadcomp(struct isp_prev_device *isp_prev, u8 enable)
815 if (enable) {
816 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
817 ISPPRV_PCR_SCOMP_EN);
818 isppreview_enable_drkframe(isp_prev, 1);
819 } else {
820 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
821 ~ISPPRV_PCR_SCOMP_EN);
824 EXPORT_SYMBOL_GPL(isppreview_enable_shadcomp);
827 * isppreview_config_drkf_shadcomp - Configures shift value in shading comp.
828 * @scomp_shtval: 3bit value of shift used in shading compensation.
830 void isppreview_config_drkf_shadcomp(struct isp_prev_device *isp_prev,
831 u8 scomp_shtval)
833 u32 pcr_val = isp_reg_readl(isp_prev->dev,
834 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
836 pcr_val &= ISPPRV_PCR_SCOMP_SFT_MASK;
837 isp_reg_writel(isp_prev->dev,
838 pcr_val | (scomp_shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT),
839 OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR);
841 EXPORT_SYMBOL_GPL(isppreview_config_drkf_shadcomp);
844 * isppreview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
845 * @enable: 1 - Enables Horizontal Median Filter.
847 void isppreview_enable_hmed(struct isp_prev_device *isp_prev, u8 enable)
849 if (enable)
850 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
851 ISPPRV_PCR_HMEDEN);
852 else {
853 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
854 ~ISPPRV_PCR_HMEDEN);
856 isp_prev->hmed_en = enable ? 1 : 0;
858 EXPORT_SYMBOL_GPL(isppreview_enable_hmed);
861 * isppreview_config_hmed - Configures the Horizontal Median Filter.
862 * @prev_hmed: Structure containing the odd and even distance between the
863 * pixels in the image along with the filter threshold.
865 void isppreview_config_hmed(struct isp_prev_device *isp_prev,
866 struct ispprev_hmed prev_hmed)
869 u32 odddist = 0;
870 u32 evendist = 0;
872 if (prev_hmed.odddist == 1)
873 odddist = ~ISPPRV_HMED_ODDDIST;
874 else
875 odddist = ISPPRV_HMED_ODDDIST;
877 if (prev_hmed.evendist == 1)
878 evendist = ~ISPPRV_HMED_EVENDIST;
879 else
880 evendist = ISPPRV_HMED_EVENDIST;
882 isp_reg_writel(isp_prev->dev, odddist | evendist | (prev_hmed.thres <<
883 ISPPRV_HMED_THRESHOLD_SHIFT),
884 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
887 EXPORT_SYMBOL_GPL(isppreview_config_hmed);
890 * isppreview_config_noisefilter - Configures the Noise Filter.
891 * @prev_nf: Structure containing the noisefilter table, strength to be used
892 * for the noise filter and the defect correction enable flag.
894 void isppreview_config_noisefilter(struct isp_prev_device *isp_prev,
895 struct ispprev_nf prev_nf)
897 int i = 0;
899 isp_reg_writel(isp_prev->dev, prev_nf.spread, OMAP3_ISP_IOMEM_PREV,
900 ISPPRV_NF);
901 isp_reg_writel(isp_prev->dev, ISPPRV_NF_TABLE_ADDR,
902 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
903 for (i = 0; i < ISPPRV_NF_TBL_SIZE; i++) {
904 isp_reg_writel(isp_prev->dev, prev_nf.table[i],
905 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
908 EXPORT_SYMBOL_GPL(isppreview_config_noisefilter);
911 * isppreview_config_dcor - Configures the defect correction
912 * @prev_nf: Structure containing the defect correction structure
914 void isppreview_config_dcor(struct isp_prev_device *isp_prev,
915 struct ispprev_dcor prev_dcor)
917 if (prev_dcor.couplet_mode_en) {
918 isp_reg_writel(isp_prev->dev, prev_dcor.detect_correct[0],
919 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
920 isp_reg_writel(isp_prev->dev, prev_dcor.detect_correct[1],
921 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
922 isp_reg_writel(isp_prev->dev, prev_dcor.detect_correct[2],
923 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
924 isp_reg_writel(isp_prev->dev, prev_dcor.detect_correct[3],
925 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
926 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
927 ISPPRV_PCR_DCCOUP);
928 } else {
929 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
930 ~ISPPRV_PCR_DCCOUP);
933 EXPORT_SYMBOL_GPL(isppreview_config_dcor);
936 * isppreview_config_cfa - Configures the CFA Interpolation parameters.
937 * @prev_cfa: Structure containing the CFA interpolation table, CFA format
938 * in the image, vertical and horizontal gradient threshold.
940 void isppreview_config_cfa(struct isp_prev_device *isp_prev,
941 struct ispprev_cfa *prev_cfa)
943 int i = 0;
945 isp_prev->cfafmt = prev_cfa->cfafmt;
947 isp_reg_and_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
948 ~ISPPRV_PCR_CFAFMT_MASK,
949 (prev_cfa->cfafmt << ISPPRV_PCR_CFAFMT_SHIFT));
951 isp_reg_writel(isp_prev->dev,
952 (prev_cfa->cfa_gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
953 (prev_cfa->cfa_gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
954 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
956 isp_reg_writel(isp_prev->dev, ISPPRV_CFA_TABLE_ADDR,
957 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
959 for (i = 0; i < ISPPRV_CFA_TBL_SIZE; i++) {
960 isp_reg_writel(isp_prev->dev, prev_cfa->cfa_table[i],
961 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
964 EXPORT_SYMBOL_GPL(isppreview_config_cfa);
967 * isppreview_config_gammacorrn - Configures the Gamma Correction table values
968 * @gtable: Structure containing the table for red, blue, green gamma table.
970 void isppreview_config_gammacorrn(struct isp_prev_device *isp_prev,
971 struct ispprev_gtable gtable)
973 int i = 0;
975 isp_reg_writel(isp_prev->dev, ISPPRV_REDGAMMA_TABLE_ADDR,
976 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
977 for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
978 isp_reg_writel(isp_prev->dev, gtable.redtable[i],
979 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
982 isp_reg_writel(isp_prev->dev, ISPPRV_GREENGAMMA_TABLE_ADDR,
983 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
984 for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
985 isp_reg_writel(isp_prev->dev, gtable.greentable[i],
986 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
989 isp_reg_writel(isp_prev->dev, ISPPRV_BLUEGAMMA_TABLE_ADDR,
990 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
991 for (i = 0; i < ISPPRV_GAMMA_TBL_SIZE; i++) {
992 isp_reg_writel(isp_prev->dev, gtable.bluetable[i],
993 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
996 EXPORT_SYMBOL_GPL(isppreview_config_gammacorrn);
999 * isppreview_set_luma_enhancement - Stores the Luminance Enhancement table.
1000 * @ytable: Structure containing the table for Luminance Enhancement table.
1002 void isppreview_set_luma_enhancement(struct isp_prev_device *isp_prev,
1003 u32 *ytable)
1005 int i;
1007 for (i = 0; i < ISPPRV_YENH_TBL_SIZE; i++)
1008 isp_prev->params.ytable[i] = ytable[i];
1010 EXPORT_SYMBOL_GPL(isppreview_set_luma_enhancement);
1013 * isppreview_config_luma_enhancement - Writes the Luminance Enhancement table.
1014 * @ytable: Structure containing the table for Luminance Enhancement table.
1016 void isppreview_config_luma_enhancement(struct isp_prev_device *isp_prev,
1017 u32 *ytable)
1019 int i = 0;
1021 isp_reg_writel(isp_prev->dev, ISPPRV_YENH_TABLE_ADDR,
1022 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
1023 for (i = 0; i < ISPPRV_YENH_TBL_SIZE; i++) {
1024 isp_reg_writel(isp_prev->dev, ytable[i],
1025 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
1028 EXPORT_SYMBOL_GPL(isppreview_config_luma_enhancement);
1031 * isppreview_config_chroma_suppression - Configures the Chroma Suppression.
1032 * @csup: Structure containing the threshold value for suppression
1033 * and the hypass filter enable flag.
1035 void isppreview_config_chroma_suppression(struct isp_prev_device *isp_prev,
1036 struct ispprev_csup csup)
1038 isp_reg_writel(isp_prev->dev,
1039 csup.gain | (csup.thres << ISPPRV_CSUP_THRES_SHIFT) |
1040 (csup.hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
1041 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
1043 EXPORT_SYMBOL_GPL(isppreview_config_chroma_suppression);
1046 * isppreview_enable_noisefilter - Enables/Disables the Noise Filter.
1047 * @enable: 1 - Enables the Noise Filter.
1049 void isppreview_enable_noisefilter(struct isp_prev_device *isp_prev, u8 enable)
1051 if (enable)
1052 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1053 ISPPRV_PCR_NFEN);
1054 else
1055 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1056 ~ISPPRV_PCR_NFEN);
1057 isp_prev->nf_en = enable ? 1 : 0;
1059 EXPORT_SYMBOL_GPL(isppreview_enable_noisefilter);
1062 * isppreview_enable_dcor - Enables/Disables the defect correction.
1063 * @enable: 1 - Enables the defect correction.
1065 void isppreview_enable_dcor(struct isp_prev_device *isp_prev, u8 enable)
1067 if (enable)
1068 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1069 ISPPRV_PCR_DCOREN);
1070 else {
1071 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1072 ~ISPPRV_PCR_DCOREN);
1074 isp_prev->dcor_en = enable ? 1 : 0;
1076 EXPORT_SYMBOL_GPL(isppreview_enable_dcor);
1079 * isppreview_enable_cfa - Enable/Disable the CFA Interpolation.
1080 * @enable: 1 - Enables the CFA.
1082 void isppreview_enable_cfa(struct isp_prev_device *isp_prev, u8 enable)
1084 if (enable)
1085 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1086 ISPPRV_PCR_CFAEN);
1087 else {
1088 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1089 ~ISPPRV_PCR_CFAEN);
1091 isp_prev->cfa_en = enable ? 1 : 0;
1093 EXPORT_SYMBOL_GPL(isppreview_enable_cfa);
1096 * isppreview_enable_gammabypass - Enables/Disables the GammaByPass
1097 * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
1098 * 0 - Goes through Gamma Correction. input and output is 10bit.
1100 void isppreview_enable_gammabypass(struct isp_prev_device *isp_prev, u8 enable)
1102 if (enable) {
1103 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1104 ISPPRV_PCR_GAMMA_BYPASS);
1105 } else {
1106 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1107 ~ISPPRV_PCR_GAMMA_BYPASS);
1110 EXPORT_SYMBOL_GPL(isppreview_enable_gammabypass);
1113 * isppreview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
1114 * @enable: 1 - Enable the Luminance Enhancement.
1116 void isppreview_enable_luma_enhancement(struct isp_prev_device *isp_prev,
1117 u8 enable)
1119 if (enable) {
1120 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1121 ISPPRV_PCR_YNENHEN);
1122 } else {
1123 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1124 ~ISPPRV_PCR_YNENHEN);
1126 isp_prev->yenh_en = enable ? 1 : 0;
1128 EXPORT_SYMBOL_GPL(isppreview_enable_luma_enhancement);
1131 * isppreview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
1132 * @enable: 1 - Enable the Chrominance Suppression.
1134 void isppreview_enable_chroma_suppression(struct isp_prev_device *isp_prev,
1135 u8 enable)
1137 if (enable)
1138 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1139 ISPPRV_PCR_SUPEN);
1140 else {
1141 isp_reg_and(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1142 ~ISPPRV_PCR_SUPEN);
1144 isp_prev->csup_en = enable ? 1 : 0;
1146 EXPORT_SYMBOL_GPL(isppreview_enable_chroma_suppression);
1149 * isppreview_config_whitebalance - Configures the White Balance parameters.
1150 * @prev_wbal: Structure containing the digital gain and white balance
1151 * coefficient.
1153 * Coefficient matrix always with default values.
1155 void isppreview_config_whitebalance(struct isp_prev_device *isp_prev,
1156 struct ispprev_wbal prev_wbal)
1158 u32 val;
1160 isp_reg_writel(isp_prev->dev, prev_wbal.dgain, OMAP3_ISP_IOMEM_PREV,
1161 ISPPRV_WB_DGAIN);
1163 val = prev_wbal.coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
1164 val |= prev_wbal.coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
1165 val |= prev_wbal.coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
1166 val |= prev_wbal.coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
1167 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1168 ISPPRV_WBGAIN);
1170 isp_reg_writel(isp_prev->dev,
1171 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
1172 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
1173 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
1174 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
1175 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
1176 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
1177 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
1178 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
1179 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
1180 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
1181 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
1182 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
1183 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
1184 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
1185 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
1186 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
1187 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
1189 EXPORT_SYMBOL_GPL(isppreview_config_whitebalance);
1192 * isppreview_config_whitebalance2 - Configures the White Balance parameters.
1193 * @prev_wbal: Structure containing the digital gain and white balance
1194 * coefficient.
1196 * Coefficient matrix can be changed.
1198 void isppreview_config_whitebalance2(struct isp_prev_device *isp_prev,
1199 struct prev_white_balance prev_wbal)
1201 isp_reg_writel(isp_prev->dev, prev_wbal.wb_dgain,
1202 OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
1203 isp_reg_writel(isp_prev->dev, prev_wbal.wb_gain[0] |
1204 prev_wbal.wb_gain[1] << ISPPRV_WBGAIN_COEF1_SHIFT |
1205 prev_wbal.wb_gain[2] << ISPPRV_WBGAIN_COEF2_SHIFT |
1206 prev_wbal.wb_gain[3] << ISPPRV_WBGAIN_COEF3_SHIFT,
1207 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
1209 isp_reg_writel(isp_prev->dev,
1210 prev_wbal.wb_coefmatrix[0][0] << ISPPRV_WBSEL_N0_0_SHIFT |
1211 prev_wbal.wb_coefmatrix[0][1] << ISPPRV_WBSEL_N0_1_SHIFT |
1212 prev_wbal.wb_coefmatrix[0][2] << ISPPRV_WBSEL_N0_2_SHIFT |
1213 prev_wbal.wb_coefmatrix[0][3] << ISPPRV_WBSEL_N0_3_SHIFT |
1214 prev_wbal.wb_coefmatrix[1][0] << ISPPRV_WBSEL_N1_0_SHIFT |
1215 prev_wbal.wb_coefmatrix[1][1] << ISPPRV_WBSEL_N1_1_SHIFT |
1216 prev_wbal.wb_coefmatrix[1][2] << ISPPRV_WBSEL_N1_2_SHIFT |
1217 prev_wbal.wb_coefmatrix[1][3] << ISPPRV_WBSEL_N1_3_SHIFT |
1218 prev_wbal.wb_coefmatrix[2][0] << ISPPRV_WBSEL_N2_0_SHIFT |
1219 prev_wbal.wb_coefmatrix[2][1] << ISPPRV_WBSEL_N2_1_SHIFT |
1220 prev_wbal.wb_coefmatrix[2][2] << ISPPRV_WBSEL_N2_2_SHIFT |
1221 prev_wbal.wb_coefmatrix[2][3] << ISPPRV_WBSEL_N2_3_SHIFT |
1222 prev_wbal.wb_coefmatrix[3][0] << ISPPRV_WBSEL_N3_0_SHIFT |
1223 prev_wbal.wb_coefmatrix[3][1] << ISPPRV_WBSEL_N3_1_SHIFT |
1224 prev_wbal.wb_coefmatrix[3][2] << ISPPRV_WBSEL_N3_2_SHIFT |
1225 prev_wbal.wb_coefmatrix[3][3] << ISPPRV_WBSEL_N3_3_SHIFT,
1226 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
1228 EXPORT_SYMBOL_GPL(isppreview_config_whitebalance2);
1231 * isppreview_config_blkadj - Configures the Black Adjustment parameters.
1232 * @prev_blkadj: Structure containing the black adjustment towards red, green,
1233 * blue.
1235 void isppreview_config_blkadj(struct isp_prev_device *isp_prev,
1236 struct ispprev_blkadj prev_blkadj)
1238 isp_reg_writel(isp_prev->dev, prev_blkadj.blue |
1239 (prev_blkadj.green << ISPPRV_BLKADJOFF_G_SHIFT) |
1240 (prev_blkadj.red << ISPPRV_BLKADJOFF_R_SHIFT),
1241 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
1243 EXPORT_SYMBOL_GPL(isppreview_config_blkadj);
1246 * isppreview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
1247 * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
1248 * offset.
1250 void isppreview_config_rgb_blending(struct isp_prev_device *isp_prev,
1251 struct ispprev_rgbtorgb rgb2rgb)
1253 u32 val = 0;
1255 val = (rgb2rgb.matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
1256 val |= (rgb2rgb.matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
1257 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1258 ISPPRV_RGB_MAT1);
1260 val = (rgb2rgb.matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
1261 val |= (rgb2rgb.matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
1262 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1263 ISPPRV_RGB_MAT2);
1265 val = (rgb2rgb.matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
1266 val |= (rgb2rgb.matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
1267 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1268 ISPPRV_RGB_MAT3);
1270 val = (rgb2rgb.matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
1271 val |= (rgb2rgb.matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
1272 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1273 ISPPRV_RGB_MAT4);
1275 val = (rgb2rgb.matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
1276 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1277 ISPPRV_RGB_MAT5);
1279 val = (rgb2rgb.offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
1280 val |= (rgb2rgb.offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
1281 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1282 ISPPRV_RGB_OFF1);
1284 val = (rgb2rgb.offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
1285 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1286 ISPPRV_RGB_OFF2);
1288 EXPORT_SYMBOL_GPL(isppreview_config_rgb_blending);
1291 * Configures the RGB-YCbYCr conversion matrix
1292 * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
1293 * YCbCr offset.
1295 void isppreview_config_rgb_to_ycbcr(struct isp_prev_device *isp_prev,
1296 struct ispprev_csc prev_csc)
1298 u32 val = 0;
1300 val = (prev_csc.matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
1301 val |= (prev_csc.matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
1302 val |= (prev_csc.matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
1303 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
1305 val = (prev_csc.matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
1306 val |= (prev_csc.matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
1307 val |= (prev_csc.matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
1308 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
1310 val = (prev_csc.matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
1311 val |= (prev_csc.matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
1312 val |= (prev_csc.matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
1313 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
1315 val = (prev_csc.offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
1316 val |= (prev_csc.offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
1317 val |= (prev_csc.offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
1318 isp_reg_writel(isp_prev->dev, val, OMAP3_ISP_IOMEM_PREV,
1319 ISPPRV_CSC_OFFSET);
1321 EXPORT_SYMBOL_GPL(isppreview_config_rgb_to_ycbcr);
1324 * isppreview_query_contrast - Query the contrast.
1325 * @contrast: Pointer to hold the current programmed contrast value.
1327 void isppreview_query_contrast(struct isp_prev_device *isp_prev, u8 *contrast)
1329 u32 brt_cnt_val = 0;
1331 brt_cnt_val = isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1332 ISPPRV_CNT_BRT);
1333 *contrast = (brt_cnt_val >> ISPPRV_CNT_BRT_CNT_SHIFT) & 0xff;
1334 DPRINTK_ISPPREV(" Current brt cnt value in hw is %x\n", brt_cnt_val);
1336 EXPORT_SYMBOL_GPL(isppreview_query_contrast);
1339 * isppreview_update_contrast - Updates the contrast.
1340 * @contrast: Pointer to hold the current programmed contrast value.
1342 * Value should be programmed before enabling the module.
1344 void isppreview_update_contrast(struct isp_prev_device *isp_prev, u8 *contrast)
1346 isp_prev->contrast = *contrast;
1348 EXPORT_SYMBOL_GPL(isppreview_update_contrast);
1351 * isppreview_config_contrast - Configures the Contrast.
1352 * @contrast: 8 bit value in U8Q4 format.
1354 * Value should be programmed before enabling the module.
1356 void isppreview_config_contrast(struct isp_prev_device *isp_prev, u8 contrast)
1358 u32 brt_cnt_val = 0;
1360 brt_cnt_val = isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1361 ISPPRV_CNT_BRT);
1362 brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_CNT_SHIFT);
1363 contrast &= 0xff;
1364 isp_reg_writel(isp_prev->dev,
1365 brt_cnt_val | contrast << ISPPRV_CNT_BRT_CNT_SHIFT,
1366 OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1368 EXPORT_SYMBOL_GPL(isppreview_config_contrast);
1371 * isppreview_get_contrast_range - Gets the range contrast value.
1372 * @min_contrast: Pointer to hold the minimum Contrast value.
1373 * @max_contrast: Pointer to hold the maximum Contrast value.
1375 void isppreview_get_contrast_range(u8 *min_contrast, u8 *max_contrast)
1377 *min_contrast = ISPPRV_CONTRAST_MIN;
1378 *max_contrast = ISPPRV_CONTRAST_MAX;
1380 EXPORT_SYMBOL_GPL(isppreview_get_contrast_range);
1383 * isppreview_update_brightness - Updates the brightness in preview module.
1384 * @brightness: Pointer to hold the current programmed brightness value.
1387 void isppreview_update_brightness(struct isp_prev_device *isp_prev,
1388 u8 *brightness)
1390 isp_prev->brightness = *brightness;
1392 EXPORT_SYMBOL_GPL(isppreview_update_brightness);
1395 * isppreview_config_brightness - Configures the brightness.
1396 * @contrast: 8bitvalue in U8Q0 format.
1398 void isppreview_config_brightness(struct isp_prev_device *isp_prev,
1399 u8 brightness)
1401 u32 brt_cnt_val = 0;
1403 DPRINTK_ISPPREV("\tConfiguring brightness in ISP: %d\n", brightness);
1404 brt_cnt_val = isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1405 ISPPRV_CNT_BRT);
1406 brt_cnt_val &= ~(0xff << ISPPRV_CNT_BRT_BRT_SHIFT);
1407 brightness &= 0xff;
1408 isp_reg_writel(isp_prev->dev,
1409 brt_cnt_val | brightness << ISPPRV_CNT_BRT_BRT_SHIFT,
1410 OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT);
1412 EXPORT_SYMBOL_GPL(isppreview_config_brightness);
1415 * isppreview_query_brightness - Query the brightness.
1416 * @brightness: Pointer to hold the current programmed brightness value.
1418 void isppreview_query_brightness(struct isp_prev_device *isp_prev,
1419 u8 *brightness)
1421 *brightness = isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1422 ISPPRV_CNT_BRT);
1424 EXPORT_SYMBOL_GPL(isppreview_query_brightness);
1427 * isppreview_get_brightness_range - Gets the range brightness value
1428 * @min_brightness: Pointer to hold the minimum brightness value
1429 * @max_brightness: Pointer to hold the maximum brightness value
1431 void isppreview_get_brightness_range(u8 *min_brightness, u8 *max_brightness)
1433 *min_brightness = ISPPRV_BRIGHT_MIN;
1434 *max_brightness = ISPPRV_BRIGHT_MAX;
1436 EXPORT_SYMBOL_GPL(isppreview_get_brightness_range);
1439 * isppreview_set_color - Sets the color effect.
1440 * @mode: Indicates the required color effect.
1442 void isppreview_set_color(struct isp_prev_device *isp_prev, u8 *mode)
1444 isp_prev->color = *mode;
1445 isp_prev->update_color_matrix = 1;
1447 EXPORT_SYMBOL_GPL(isppreview_set_color);
1450 * isppreview_get_color - Gets the current color effect.
1451 * @mode: Indicates the current color effect.
1453 void isppreview_get_color(struct isp_prev_device *isp_prev, u8 *mode)
1455 *mode = isp_prev->color;
1457 EXPORT_SYMBOL_GPL(isppreview_get_color);
1460 * isppreview_config_yc_range - Configures the max and min Y and C values.
1461 * @yclimit: Structure containing the range of Y and C values.
1463 void isppreview_config_yc_range(struct isp_prev_device *isp_prev,
1464 struct ispprev_yclimit yclimit)
1466 isp_reg_writel(isp_prev->dev,
1467 yclimit.maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
1468 yclimit.maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
1469 yclimit.minC << ISPPRV_SETUP_YC_MINC_SHIFT |
1470 yclimit.minY << ISPPRV_SETUP_YC_MINY_SHIFT,
1471 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
1473 EXPORT_SYMBOL_GPL(isppreview_config_yc_range);
1476 * isppreview_try_size - Calculates output dimensions with the modules enabled.
1477 * @input_w: input width for the preview in number of pixels per line
1478 * @input_h: input height for the preview in number of lines
1479 * @output_w: output width from the preview in number of pixels per line
1480 * @output_h: output height for the preview in number of lines
1482 * Calculates the number of pixels cropped in the submodules that are enabled,
1483 * Fills up the output width height variables in the isp_prev structure.
1485 int isppreview_try_pipeline(struct isp_prev_device *isp_prev,
1486 struct isp_pipeline *pipe)
1488 u32 div = 0;
1489 int max_out;
1491 if (pipe->ccdc_out_w_img < 32 || pipe->ccdc_out_h < 32) {
1492 dev_err(isp_prev->dev, "preview does not support "
1493 "width < 16 or height < 32 \n");
1494 return -EINVAL;
1496 if (omap_rev() == OMAP3430_REV_ES1_0)
1497 max_out = ISPPRV_MAXOUTPUT_WIDTH;
1498 else
1499 max_out = ISPPRV_MAXOUTPUT_WIDTH_ES2;
1501 pipe->prv_out_w = pipe->ccdc_out_w;
1502 pipe->prv_out_h = pipe->ccdc_out_h;
1503 pipe->prv_out_w_img = pipe->ccdc_out_w_img;
1504 pipe->prv_out_h_img = pipe->ccdc_out_h;
1506 isp_prev->fmtavg = 0;
1508 if (pipe->ccdc_out_w_img > max_out) {
1509 div = (pipe->ccdc_out_w_img/max_out);
1510 if (div >= 2 && div < 4) {
1511 isp_prev->fmtavg = 1;
1512 pipe->prv_out_w_img /= 2;
1513 } else if (div >= 4 && div < 8) {
1514 isp_prev->fmtavg = 2;
1515 pipe->prv_out_w_img /= 4;
1516 } else if (div >= 8) {
1517 isp_prev->fmtavg = 3;
1518 pipe->prv_out_w_img /= 8;
1522 /* if (isp_prev->hmed_en) */
1523 pipe->prv_out_w_img -= 4;
1524 /* if (isp_prev->nf_en) */
1525 pipe->prv_out_w_img -= 4;
1526 pipe->prv_out_h_img -= 4;
1527 /* if (isp_prev->cfa_en) */
1528 switch (isp_prev->cfafmt) {
1529 case CFAFMT_BAYER:
1530 case CFAFMT_SONYVGA:
1531 pipe->prv_out_w_img -= 4;
1532 pipe->prv_out_h_img -= 4;
1533 break;
1534 case CFAFMT_RGBFOVEON:
1535 case CFAFMT_RRGGBBFOVEON:
1536 case CFAFMT_DNSPL:
1537 case CFAFMT_HONEYCOMB:
1538 pipe->prv_out_h_img -= 2;
1539 break;
1541 /* if (isp_prev->yenh_en || isp_prev->csup_en) */
1542 pipe->prv_out_w_img -= 2;
1544 /* Start at the correct row/column by skipping
1545 * a Sensor specific amount.
1547 pipe->prv_out_w_img -= isp_prev->sph;
1548 pipe->prv_out_h_img -= isp_prev->slv;
1550 if (pipe->prv_out_w_img % 2)
1551 pipe->prv_out_w_img -= 1;
1553 /* FIXME: This doesn't apply for prv -> rsz. */
1554 pipe->prv_out_w = ALIGN(pipe->prv_out_w_img, 0x20);
1556 return 0;
1558 EXPORT_SYMBOL_GPL(isppreview_try_pipeline);
1561 * isppreview_config_size - Sets the size of ISP preview output.
1562 * @pipe->ccdc_out_w: input width for the preview in number of pixels per line
1563 * @pipe->ccdc_out_h: input height for the preview in number of lines
1564 * @output_w: output width from the preview in number of pixels per line
1565 * @output_h: output height for the preview in number of lines
1567 * Configures the appropriate values stored in the isp_prev structure to
1568 * HORZ/VERT_INFO. Configures PRV_AVE if needed for downsampling as calculated
1569 * in trysize.
1571 int isppreview_s_pipeline(struct isp_prev_device *isp_prev,
1572 struct isp_pipeline *pipe)
1574 u32 prevsdroff;
1575 int rval;
1577 rval = isppreview_config_datapath(isp_prev, pipe);
1578 if (rval)
1579 return rval;
1581 isp_reg_writel(isp_prev->dev,
1582 (isp_prev->sph << ISPPRV_HORZ_INFO_SPH_SHIFT) |
1583 (pipe->ccdc_out_w - 1),
1584 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1585 isp_reg_writel(isp_prev->dev,
1586 (isp_prev->slv << ISPPRV_VERT_INFO_SLV_SHIFT) |
1587 (pipe->ccdc_out_h - 2),
1588 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1590 if (isp_prev->cfafmt == CFAFMT_BAYER)
1591 isp_reg_writel(isp_prev->dev, ISPPRV_AVE_EVENDIST_2 <<
1592 ISPPRV_AVE_EVENDIST_SHIFT |
1593 ISPPRV_AVE_ODDDIST_2 <<
1594 ISPPRV_AVE_ODDDIST_SHIFT |
1595 isp_prev->fmtavg,
1596 OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
1598 if (pipe->prv_out == PREVIEW_MEM) {
1599 prevsdroff = pipe->prv_out_w * ISP_BYTES_PER_PIXEL;
1600 if ((prevsdroff & ISP_32B_BOUNDARY_OFFSET) != prevsdroff) {
1601 DPRINTK_ISPPREV("ISP_WARN: Preview output buffer line"
1602 " size is truncated"
1603 " to 32byte boundary\n");
1604 prevsdroff &= ISP_32B_BOUNDARY_BUF ;
1606 isppreview_config_outlineoffset(isp_prev, prevsdroff);
1609 if (pipe->pix.pixelformat == V4L2_PIX_FMT_UYVY)
1610 isppreview_config_ycpos(isp_prev, YCPOS_YCrYCb);
1611 else
1612 isppreview_config_ycpos(isp_prev, YCPOS_CrYCbY);
1614 return 0;
1616 EXPORT_SYMBOL_GPL(isppreview_s_pipeline);
1619 * isppreview_config_inlineoffset - Configures the Read address line offset.
1620 * @offset: Line Offset for the input image.
1622 int isppreview_config_inlineoffset(struct isp_prev_device *isp_prev, u32 offset)
1624 if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) {
1625 isp_reg_writel(isp_prev->dev, offset & 0xffff,
1626 OMAP3_ISP_IOMEM_PREV, ISPPRV_RADR_OFFSET);
1627 } else {
1628 dev_err(isp_prev->dev, "preview: Offset should be in 32 byte "
1629 "boundary\n");
1630 return -EINVAL;
1632 return 0;
1634 EXPORT_SYMBOL_GPL(isppreview_config_inlineoffset);
1637 * isppreview_set_inaddr - Sets memory address of input frame.
1638 * @addr: 32bit memory address aligned on 32byte boundary.
1640 * Configures the memory address from which the input frame is to be read.
1642 int isppreview_set_inaddr(struct isp_prev_device *isp_prev, u32 addr)
1644 if ((addr & ISP_32B_BOUNDARY_BUF) == addr)
1645 isp_reg_writel(isp_prev->dev, addr,
1646 OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1647 else {
1648 dev_err(isp_prev->dev, "preview: Address should be in 32 byte "
1649 "boundary\n");
1650 return -EINVAL;
1652 return 0;
1654 EXPORT_SYMBOL_GPL(isppreview_set_inaddr);
1657 * isppreview_config_outlineoffset - Configures the Write address line offset.
1658 * @offset: Line Offset for the preview output.
1660 int isppreview_config_outlineoffset(struct isp_prev_device *isp_prev,
1661 u32 offset)
1663 if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
1664 dev_err(isp_prev->dev, "preview: Offset should be in 32 byte "
1665 "boundary\n");
1666 return -EINVAL;
1668 isp_reg_writel(isp_prev->dev, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1669 ISPPRV_WADD_OFFSET);
1670 return 0;
1672 EXPORT_SYMBOL_GPL(isppreview_config_outlineoffset);
1675 * isppreview_set_outaddr - Sets the memory address to store output frame
1676 * @addr: 32bit memory address aligned on 32byte boundary.
1678 * Configures the memory address to which the output frame is written.
1680 int isppreview_set_outaddr(struct isp_prev_device *isp_prev, u32 addr)
1682 if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
1683 dev_err(isp_prev->dev, "preview: Address should be in 32 byte "
1684 "boundary\n");
1685 return -EINVAL;
1687 isp_reg_writel(isp_prev->dev, addr, OMAP3_ISP_IOMEM_PREV,
1688 ISPPRV_WSDR_ADDR);
1689 return 0;
1691 EXPORT_SYMBOL_GPL(isppreview_set_outaddr);
1694 * isppreview_config_darklineoffset - Sets the Dark frame address line offset.
1695 * @offset: Line Offset for the Darkframe.
1697 int isppreview_config_darklineoffset(struct isp_prev_device *isp_prev,
1698 u32 offset)
1700 if ((offset & ISP_32B_BOUNDARY_OFFSET) != offset) {
1701 dev_err(isp_prev->dev, "preview: Offset should be in 32 byte "
1702 "boundary\n");
1703 return -EINVAL;
1705 isp_reg_writel(isp_prev->dev, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1706 ISPPRV_DRKF_OFFSET);
1707 return 0;
1709 EXPORT_SYMBOL_GPL(isppreview_config_darklineoffset);
1712 * isppreview_set_darkaddr - Sets the memory address to store Dark frame.
1713 * @addr: 32bit memory address aligned on 32 bit boundary.
1715 int isppreview_set_darkaddr(struct isp_prev_device *isp_prev, u32 addr)
1717 if ((addr & ISP_32B_BOUNDARY_BUF) != addr) {
1718 dev_err(isp_prev->dev, "preview: Address should be in 32 byte "
1719 "boundary\n");
1720 return -EINVAL;
1722 isp_reg_writel(isp_prev->dev, addr, OMAP3_ISP_IOMEM_PREV,
1723 ISPPRV_DSDR_ADDR);
1724 return 0;
1726 EXPORT_SYMBOL_GPL(isppreview_set_darkaddr);
1729 * isppreview_enable - Enables the Preview module.
1730 * @enable: 1 - Enables the preview module.
1732 * Client should configure all the sub modules in Preview before this.
1734 void isppreview_enable(struct isp_prev_device *isp_prev)
1736 isp_reg_or(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1737 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1739 EXPORT_SYMBOL_GPL(isppreview_enable);
1742 * isppreview_busy - Gets busy state of preview module.
1744 int isppreview_busy(struct isp_prev_device *isp_prev)
1746 return isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1747 & ISPPRV_PCR_BUSY;
1749 EXPORT_SYMBOL_GPL(isppreview_busy);
1752 * isppreview_save_context - Saves the values of the preview module registers.
1754 void isppreview_save_context(struct device *dev)
1756 DPRINTK_ISPPREV("Saving context\n");
1757 isp_save_context(dev, ispprev_reg_list);
1759 EXPORT_SYMBOL_GPL(isppreview_save_context);
1762 * isppreview_restore_context - Restores the values of preview module registers
1764 void isppreview_restore_context(struct device *dev)
1766 DPRINTK_ISPPREV("Restoring context\n");
1767 isp_restore_context(dev, ispprev_reg_list);
1769 EXPORT_SYMBOL_GPL(isppreview_restore_context);
1772 * isppreview_print_status - Prints the values of the Preview Module registers.
1774 * Also prints other debug information stored in the preview moduel.
1776 void isppreview_print_status(struct isp_prev_device *isp_prev,
1777 struct isp_pipeline *pipe)
1779 DPRINTK_ISPPREV("Preview Input format =%d, Output Format =%d\n",
1780 pipe->prv_inp, pipe->prv_out);
1781 DPRINTK_ISPPREV("Accepted Preview Input (width = %d,Height = %d)\n",
1782 isp_prev->previn_w,
1783 isp_prev->previn_h);
1784 DPRINTK_ISPPREV("Accepted Preview Output (width = %d,Height = %d)\n",
1785 isp_prev->prevout_w,
1786 isp_prev->prevout_h);
1787 DPRINTK_ISPPREV("###ISP_CTRL in preview =0x%x\n",
1788 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_MAIN,
1789 ISP_CTRL));
1790 DPRINTK_ISPPREV("###ISP_IRQ0ENABLE in preview =0x%x\n",
1791 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_MAIN,
1792 ISP_IRQ0ENABLE));
1793 DPRINTK_ISPPREV("###ISP_IRQ0STATUS in preview =0x%x\n",
1794 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_MAIN,
1795 ISP_IRQ0STATUS));
1796 DPRINTK_ISPPREV("###PRV PCR =0x%x\n",
1797 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1798 ISPPRV_PCR));
1799 DPRINTK_ISPPREV("###PRV HORZ_INFO =0x%x\n",
1800 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1801 ISPPRV_HORZ_INFO));
1802 DPRINTK_ISPPREV("###PRV VERT_INFO =0x%x\n",
1803 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1804 ISPPRV_VERT_INFO));
1805 DPRINTK_ISPPREV("###PRV WSDR_ADDR =0x%x\n",
1806 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1807 ISPPRV_WSDR_ADDR));
1808 DPRINTK_ISPPREV("###PRV WADD_OFFSET =0x%x\n",
1809 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1810 ISPPRV_WADD_OFFSET));
1811 DPRINTK_ISPPREV("###PRV AVE =0x%x\n",
1812 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1813 ISPPRV_AVE));
1814 DPRINTK_ISPPREV("###PRV HMED =0x%x\n",
1815 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1816 ISPPRV_HMED));
1817 DPRINTK_ISPPREV("###PRV NF =0x%x\n",
1818 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1819 ISPPRV_NF));
1820 DPRINTK_ISPPREV("###PRV WB_DGAIN =0x%x\n",
1821 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1822 ISPPRV_WB_DGAIN));
1823 DPRINTK_ISPPREV("###PRV WBGAIN =0x%x\n",
1824 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1825 ISPPRV_WBGAIN));
1826 DPRINTK_ISPPREV("###PRV WBSEL =0x%x\n",
1827 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1828 ISPPRV_WBSEL));
1829 DPRINTK_ISPPREV("###PRV CFA =0x%x\n",
1830 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1831 ISPPRV_CFA));
1832 DPRINTK_ISPPREV("###PRV BLKADJOFF =0x%x\n",
1833 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1834 ISPPRV_BLKADJOFF));
1835 DPRINTK_ISPPREV("###PRV RGB_MAT1 =0x%x\n",
1836 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1837 ISPPRV_RGB_MAT1));
1838 DPRINTK_ISPPREV("###PRV RGB_MAT2 =0x%x\n",
1839 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1840 ISPPRV_RGB_MAT2));
1841 DPRINTK_ISPPREV("###PRV RGB_MAT3 =0x%x\n",
1842 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1843 ISPPRV_RGB_MAT3));
1844 DPRINTK_ISPPREV("###PRV RGB_MAT4 =0x%x\n",
1845 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1846 ISPPRV_RGB_MAT4));
1847 DPRINTK_ISPPREV("###PRV RGB_MAT5 =0x%x\n",
1848 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1849 ISPPRV_RGB_MAT5));
1850 DPRINTK_ISPPREV("###PRV RGB_OFF1 =0x%x\n",
1851 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1852 ISPPRV_RGB_OFF1));
1853 DPRINTK_ISPPREV("###PRV RGB_OFF2 =0x%x\n",
1854 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1855 ISPPRV_RGB_OFF2));
1856 DPRINTK_ISPPREV("###PRV CSC0 =0x%x\n",
1857 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1858 ISPPRV_CSC0));
1859 DPRINTK_ISPPREV("###PRV CSC1 =0x%x\n",
1860 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1861 ISPPRV_CSC1));
1862 DPRINTK_ISPPREV("###PRV CSC2 =0x%x\n",
1863 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1864 ISPPRV_CSC2));
1865 DPRINTK_ISPPREV("###PRV CSC_OFFSET =0x%x\n",
1866 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1867 ISPPRV_CSC_OFFSET));
1868 DPRINTK_ISPPREV("###PRV CNT_BRT =0x%x\n",
1869 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1870 ISPPRV_CNT_BRT));
1871 DPRINTK_ISPPREV("###PRV CSUP =0x%x\n",
1872 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1873 ISPPRV_CSUP));
1874 DPRINTK_ISPPREV("###PRV SETUP_YC =0x%x\n",
1875 isp_reg_readl(isp_prev->dev, OMAP3_ISP_IOMEM_PREV,
1876 ISPPRV_SETUP_YC));
1878 EXPORT_SYMBOL_GPL(isppreview_print_status);
1881 * isp_preview_init - Module Initialization.
1883 int __init isp_preview_init(struct device *dev)
1885 struct isp_device *isp = dev_get_drvdata(dev);
1886 struct isp_prev_device *isp_prev = &isp->isp_prev;
1887 struct prev_params *params = &isp_prev->params;
1888 int i = 0;
1890 isp_prev->dev = dev;
1892 /* Init values */
1893 isp_prev->sph = 2;
1894 isp_prev->slv = 0;
1895 isp_prev->color = V4L2_COLORFX_NONE;
1896 isp_prev->contrast = ISPPRV_CONTRAST_DEF;
1897 params->contrast = ISPPRV_CONTRAST_DEF;
1898 isp_prev->brightness = ISPPRV_BRIGHT_DEF;
1899 params->brightness = ISPPRV_BRIGHT_DEF;
1900 params->average = NO_AVE;
1901 params->lens_shading_shift = 0;
1902 params->cfa.cfafmt = CFAFMT_BAYER;
1903 params->cfa.cfa_table = cfa_coef_table;
1904 params->cfa.cfa_gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1905 params->cfa.cfa_gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1906 params->csup.gain = FLR_CSUP_GAIN;
1907 params->csup.thres = FLR_CSUP_THRES;
1908 params->csup.hypf_en = 0;
1909 params->ytable = kzalloc(sizeof(u32) * ISPPRV_YENH_TBL_SIZE,
1910 GFP_KERNEL);
1911 isppreview_set_luma_enhancement(isp_prev, luma_enhance_table);
1912 params->nf.spread = FLR_NF_STRGTH;
1913 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1914 params->dcor.couplet_mode_en = 1;
1915 for (i = 0; i < 4; i++)
1916 params->dcor.detect_correct[i] = 0xE;
1917 params->gtable.bluetable = bluegamma_table;
1918 params->gtable.greentable = greengamma_table;
1919 params->gtable.redtable = redgamma_table;
1920 params->wbal.dgain = FLR_WBAL_DGAIN;
1921 if (omap_rev() > OMAP3430_REV_ES1_0) {
1922 params->wbal.coef0 = FLR_WBAL_COEF0_ES1;
1923 params->wbal.coef1 = FLR_WBAL_COEF1_ES1;
1924 params->wbal.coef2 = FLR_WBAL_COEF2_ES1;
1925 params->wbal.coef3 = FLR_WBAL_COEF3_ES1;
1926 } else {
1927 params->wbal.coef0 = FLR_WBAL_COEF0;
1928 params->wbal.coef1 = FLR_WBAL_COEF1;
1929 params->wbal.coef2 = FLR_WBAL_COEF2;
1930 params->wbal.coef3 = FLR_WBAL_COEF3;
1932 params->blk_adj.red = FLR_BLKADJ_RED;
1933 params->blk_adj.green = FLR_BLKADJ_GREEN;
1934 params->blk_adj.blue = FLR_BLKADJ_BLUE;
1935 params->rgb2rgb = flr_rgb2rgb;
1936 params->rgb2ycbcr = flr_prev_csc[isp_prev->color];
1938 params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER;
1939 params->features &= ~(PREV_AVERAGER | PREV_INVERSE_ALAW |
1940 PREV_HORZ_MEDIAN_FILTER |
1941 PREV_GAMMA_BYPASS |
1942 PREV_DARK_FRAME_SUBTRACT |
1943 PREV_LENS_SHADING |
1944 PREV_DARK_FRAME_CAPTURE |
1945 PREV_CHROMA_SUPPRESS |
1946 PREV_LUMA_ENHANCE);
1948 spin_lock_init(&isp_prev->lock);
1950 return 0;
1954 * isp_preview_cleanup - Module Cleanup.
1956 void isp_preview_cleanup(struct device *dev)
1958 struct isp_device *isp = dev_get_drvdata(dev);
1959 struct isp_prev_device *isp_prev = &isp->isp_prev;
1960 struct prev_params *params = &isp_prev->params;
1962 kfree(params->ytable);