FRV: Use generic show_interrupts()
[cris-mirror.git] / drivers / media / video / omap3isp / isppreview.c
blobbaf9374201dc6c674bfc56a842f9bb390e240e46
1 /*
2 * isppreview.c
4 * TI OMAP3 ISP driver - Preview module
6 * Copyright (C) 2010 Nokia Corporation
7 * Copyright (C) 2009 Texas Instruments, Inc.
9 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10 * Sakari Ailus <sakari.ailus@iki.fi>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 * 02110-1301 USA
27 #include <linux/device.h>
28 #include <linux/mm.h>
29 #include <linux/module.h>
30 #include <linux/mutex.h>
31 #include <linux/uaccess.h>
33 #include "isp.h"
34 #include "ispreg.h"
35 #include "isppreview.h"
37 /* Default values in Office Flourescent Light for RGBtoRGB Blending */
38 static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
39 { /* RGB-RGB Matrix */
40 {0x01E2, 0x0F30, 0x0FEE},
41 {0x0F9B, 0x01AC, 0x0FB9},
42 {0x0FE0, 0x0EC0, 0x0260}
43 }, /* RGB Offset */
44 {0x0000, 0x0000, 0x0000}
47 /* Default values in Office Flourescent Light for RGB to YUV Conversion*/
48 static struct omap3isp_prev_csc flr_prev_csc = {
49 { /* CSC Coef Matrix */
50 {66, 129, 25},
51 {-38, -75, 112},
52 {112, -94 , -18}
53 }, /* CSC Offset */
54 {0x0, 0x0, 0x0}
57 /* Default values in Office Flourescent Light for CFA Gradient*/
58 #define FLR_CFA_GRADTHRS_HORZ 0x28
59 #define FLR_CFA_GRADTHRS_VERT 0x28
61 /* Default values in Office Flourescent Light for Chroma Suppression*/
62 #define FLR_CSUP_GAIN 0x0D
63 #define FLR_CSUP_THRES 0xEB
65 /* Default values in Office Flourescent Light for Noise Filter*/
66 #define FLR_NF_STRGTH 0x03
68 /* Default values for White Balance */
69 #define FLR_WBAL_DGAIN 0x100
70 #define FLR_WBAL_COEF 0x20
72 /* Default values in Office Flourescent Light for Black Adjustment*/
73 #define FLR_BLKADJ_BLUE 0x0
74 #define FLR_BLKADJ_GREEN 0x0
75 #define FLR_BLKADJ_RED 0x0
77 #define DEF_DETECT_CORRECT_VAL 0xe
79 #define PREV_MIN_WIDTH 64
80 #define PREV_MIN_HEIGHT 8
81 #define PREV_MAX_HEIGHT 16384
84 * Coeficient Tables for the submodules in Preview.
85 * Array is initialised with the values from.the tables text file.
89 * CFA Filter Coefficient Table
92 static u32 cfa_coef_table[] = {
93 #include "cfa_coef_table.h"
97 * Default Gamma Correction Table - All components
99 static u32 gamma_table[] = {
100 #include "gamma_table.h"
104 * Noise Filter Threshold table
106 static u32 noise_filter_table[] = {
107 #include "noise_filter_table.h"
111 * Luminance Enhancement Table
113 static u32 luma_enhance_table[] = {
114 #include "luma_enhance_table.h"
118 * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
119 * @enable: 1 - Reverse the A-Law done in CCDC.
121 static void
122 preview_enable_invalaw(struct isp_prev_device *prev, u8 enable)
124 struct isp_device *isp = to_isp_device(prev);
126 if (enable)
127 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
128 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
129 else
130 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
131 ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
135 * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
136 * @prev -
137 * @enable: 1 - Enable, 0 - Disable
139 * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
140 * The proccess is applied for each captured frame.
142 static void
143 preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable)
145 struct isp_device *isp = to_isp_device(prev);
147 if (enable)
148 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
149 ISPPRV_PCR_DRKFCAP);
150 else
151 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
152 ISPPRV_PCR_DRKFCAP);
156 * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
157 * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
158 * subtracted with the pixels in the current frame.
160 * The proccess is applied for each captured frame.
162 static void
163 preview_enable_drkframe(struct isp_prev_device *prev, u8 enable)
165 struct isp_device *isp = to_isp_device(prev);
167 if (enable)
168 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
169 ISPPRV_PCR_DRKFEN);
170 else
171 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
172 ISPPRV_PCR_DRKFEN);
176 * preview_config_drkf_shadcomp - Configures shift value in shading comp.
177 * @scomp_shtval: 3bit value of shift used in shading compensation.
179 static void
180 preview_config_drkf_shadcomp(struct isp_prev_device *prev,
181 const void *scomp_shtval)
183 struct isp_device *isp = to_isp_device(prev);
184 const u32 *shtval = scomp_shtval;
186 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
187 ISPPRV_PCR_SCOMP_SFT_MASK,
188 *shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT);
192 * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
193 * @enable: 1 - Enables Horizontal Median Filter.
195 static void
196 preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
198 struct isp_device *isp = to_isp_device(prev);
200 if (enable)
201 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
202 ISPPRV_PCR_HMEDEN);
203 else
204 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
205 ISPPRV_PCR_HMEDEN);
209 * preview_config_hmed - Configures the Horizontal Median Filter.
210 * @prev_hmed: Structure containing the odd and even distance between the
211 * pixels in the image along with the filter threshold.
213 static void
214 preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed)
216 struct isp_device *isp = to_isp_device(prev);
217 const struct omap3isp_prev_hmed *hmed = prev_hmed;
219 isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
220 (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
221 (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
222 OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
226 * preview_config_noisefilter - Configures the Noise Filter.
227 * @prev_nf: Structure containing the noisefilter table, strength to be used
228 * for the noise filter and the defect correction enable flag.
230 static void
231 preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf)
233 struct isp_device *isp = to_isp_device(prev);
234 const struct omap3isp_prev_nf *nf = prev_nf;
235 unsigned int i;
237 isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
238 isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
239 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
240 for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
241 isp_reg_writel(isp, nf->table[i],
242 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
247 * preview_config_dcor - Configures the defect correction
248 * @prev_dcor: Structure containing the defect correct thresholds
250 static void
251 preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor)
253 struct isp_device *isp = to_isp_device(prev);
254 const struct omap3isp_prev_dcor *dcor = prev_dcor;
256 isp_reg_writel(isp, dcor->detect_correct[0],
257 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
258 isp_reg_writel(isp, dcor->detect_correct[1],
259 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
260 isp_reg_writel(isp, dcor->detect_correct[2],
261 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
262 isp_reg_writel(isp, dcor->detect_correct[3],
263 OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
264 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
265 ISPPRV_PCR_DCCOUP,
266 dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
270 * preview_config_cfa - Configures the CFA Interpolation parameters.
271 * @prev_cfa: Structure containing the CFA interpolation table, CFA format
272 * in the image, vertical and horizontal gradient threshold.
274 static void
275 preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
277 struct isp_device *isp = to_isp_device(prev);
278 const struct omap3isp_prev_cfa *cfa = prev_cfa;
279 unsigned int i;
281 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
282 ISPPRV_PCR_CFAFMT_MASK,
283 cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
285 isp_reg_writel(isp,
286 (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
287 (cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
288 OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
290 isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
291 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
293 for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) {
294 isp_reg_writel(isp, cfa->table[i],
295 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
300 * preview_config_gammacorrn - Configures the Gamma Correction table values
301 * @gtable: Structure containing the table for red, blue, green gamma table.
303 static void
304 preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable)
306 struct isp_device *isp = to_isp_device(prev);
307 const struct omap3isp_prev_gtables *gt = gtable;
308 unsigned int i;
310 isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
311 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
312 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
313 isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
314 ISPPRV_SET_TBL_DATA);
316 isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
317 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
318 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
319 isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
320 ISPPRV_SET_TBL_DATA);
322 isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
323 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
324 for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
325 isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
326 ISPPRV_SET_TBL_DATA);
330 * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
331 * @ytable: Structure containing the table for Luminance Enhancement table.
333 static void
334 preview_config_luma_enhancement(struct isp_prev_device *prev,
335 const void *ytable)
337 struct isp_device *isp = to_isp_device(prev);
338 const struct omap3isp_prev_luma *yt = ytable;
339 unsigned int i;
341 isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
342 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
343 for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
344 isp_reg_writel(isp, yt->table[i],
345 OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
350 * preview_config_chroma_suppression - Configures the Chroma Suppression.
351 * @csup: Structure containing the threshold value for suppression
352 * and the hypass filter enable flag.
354 static void
355 preview_config_chroma_suppression(struct isp_prev_device *prev,
356 const void *csup)
358 struct isp_device *isp = to_isp_device(prev);
359 const struct omap3isp_prev_csup *cs = csup;
361 isp_reg_writel(isp,
362 cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
363 (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
364 OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
368 * preview_enable_noisefilter - Enables/Disables the Noise Filter.
369 * @enable: 1 - Enables the Noise Filter.
371 static void
372 preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable)
374 struct isp_device *isp = to_isp_device(prev);
376 if (enable)
377 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
378 ISPPRV_PCR_NFEN);
379 else
380 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
381 ISPPRV_PCR_NFEN);
385 * preview_enable_dcor - Enables/Disables the defect correction.
386 * @enable: 1 - Enables the defect correction.
388 static void
389 preview_enable_dcor(struct isp_prev_device *prev, u8 enable)
391 struct isp_device *isp = to_isp_device(prev);
393 if (enable)
394 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
395 ISPPRV_PCR_DCOREN);
396 else
397 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
398 ISPPRV_PCR_DCOREN);
402 * preview_enable_cfa - Enable/Disable the CFA Interpolation.
403 * @enable: 1 - Enables the CFA.
405 static void
406 preview_enable_cfa(struct isp_prev_device *prev, u8 enable)
408 struct isp_device *isp = to_isp_device(prev);
410 if (enable)
411 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
412 ISPPRV_PCR_CFAEN);
413 else
414 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
415 ISPPRV_PCR_CFAEN);
419 * preview_enable_gammabypass - Enables/Disables the GammaByPass
420 * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
421 * 0 - Goes through Gamma Correction. input and output is 10bit.
423 static void
424 preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable)
426 struct isp_device *isp = to_isp_device(prev);
428 if (enable)
429 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
430 ISPPRV_PCR_GAMMA_BYPASS);
431 else
432 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
433 ISPPRV_PCR_GAMMA_BYPASS);
437 * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
438 * @enable: 1 - Enable the Luminance Enhancement.
440 static void
441 preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable)
443 struct isp_device *isp = to_isp_device(prev);
445 if (enable)
446 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
447 ISPPRV_PCR_YNENHEN);
448 else
449 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
450 ISPPRV_PCR_YNENHEN);
454 * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
455 * @enable: 1 - Enable the Chrominance Suppression.
457 static void
458 preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
460 struct isp_device *isp = to_isp_device(prev);
462 if (enable)
463 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
464 ISPPRV_PCR_SUPEN);
465 else
466 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
467 ISPPRV_PCR_SUPEN);
471 * preview_config_whitebalance - Configures the White Balance parameters.
472 * @prev_wbal: Structure containing the digital gain and white balance
473 * coefficient.
475 * Coefficient matrix always with default values.
477 static void
478 preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
480 struct isp_device *isp = to_isp_device(prev);
481 const struct omap3isp_prev_wbal *wbal = prev_wbal;
482 u32 val;
484 isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
486 val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
487 val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
488 val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
489 val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
490 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
492 isp_reg_writel(isp,
493 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
494 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
495 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
496 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
497 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
498 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
499 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
500 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
501 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
502 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
503 ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
504 ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
505 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
506 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
507 ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
508 ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
509 OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
513 * preview_config_blkadj - Configures the Black Adjustment parameters.
514 * @prev_blkadj: Structure containing the black adjustment towards red, green,
515 * blue.
517 static void
518 preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
520 struct isp_device *isp = to_isp_device(prev);
521 const struct omap3isp_prev_blkadj *blkadj = prev_blkadj;
523 isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
524 (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
525 (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
526 OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
530 * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
531 * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
532 * offset.
534 static void
535 preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
537 struct isp_device *isp = to_isp_device(prev);
538 const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb;
539 u32 val;
541 val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
542 val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
543 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
545 val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
546 val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
547 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
549 val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
550 val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
551 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
553 val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
554 val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
555 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
557 val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
558 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
560 val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
561 val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
562 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
564 val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
565 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
569 * Configures the RGB-YCbYCr conversion matrix
570 * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
571 * YCbCr offset.
573 static void
574 preview_config_rgb_to_ycbcr(struct isp_prev_device *prev, const void *prev_csc)
576 struct isp_device *isp = to_isp_device(prev);
577 const struct omap3isp_prev_csc *csc = prev_csc;
578 u32 val;
580 val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
581 val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
582 val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
583 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
585 val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
586 val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
587 val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
588 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
590 val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
591 val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
592 val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
593 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
595 val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
596 val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
597 val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
598 isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
602 * preview_update_contrast - Updates the contrast.
603 * @contrast: Pointer to hold the current programmed contrast value.
605 * Value should be programmed before enabling the module.
607 static void
608 preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
610 struct prev_params *params = &prev->params;
612 if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
613 params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
614 prev->update |= PREV_CONTRAST;
619 * preview_config_contrast - Configures the Contrast.
620 * @params: Contrast value (u8 pointer, U8Q0 format).
622 * Value should be programmed before enabling the module.
624 static void
625 preview_config_contrast(struct isp_prev_device *prev, const void *params)
627 struct isp_device *isp = to_isp_device(prev);
629 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
630 0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
631 *(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT);
635 * preview_update_brightness - Updates the brightness in preview module.
636 * @brightness: Pointer to hold the current programmed brightness value.
639 static void
640 preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
642 struct prev_params *params = &prev->params;
644 if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
645 params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
646 prev->update |= PREV_BRIGHTNESS;
651 * preview_config_brightness - Configures the brightness.
652 * @params: Brightness value (u8 pointer, U8Q0 format).
654 static void
655 preview_config_brightness(struct isp_prev_device *prev, const void *params)
657 struct isp_device *isp = to_isp_device(prev);
659 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
660 0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
661 *(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT);
665 * preview_config_yc_range - Configures the max and min Y and C values.
666 * @yclimit: Structure containing the range of Y and C values.
668 static void
669 preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit)
671 struct isp_device *isp = to_isp_device(prev);
672 const struct omap3isp_prev_yclimit *yc = yclimit;
674 isp_reg_writel(isp,
675 yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
676 yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
677 yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
678 yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
679 OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
682 /* preview parameters update structure */
683 struct preview_update {
684 int cfg_bit;
685 int feature_bit;
686 void (*config)(struct isp_prev_device *, const void *);
687 void (*enable)(struct isp_prev_device *, u8);
690 static struct preview_update update_attrs[] = {
691 {OMAP3ISP_PREV_LUMAENH, PREV_LUMA_ENHANCE,
692 preview_config_luma_enhancement,
693 preview_enable_luma_enhancement},
694 {OMAP3ISP_PREV_INVALAW, PREV_INVERSE_ALAW,
695 NULL,
696 preview_enable_invalaw},
697 {OMAP3ISP_PREV_HRZ_MED, PREV_HORZ_MEDIAN_FILTER,
698 preview_config_hmed,
699 preview_enable_hmed},
700 {OMAP3ISP_PREV_CFA, PREV_CFA,
701 preview_config_cfa,
702 preview_enable_cfa},
703 {OMAP3ISP_PREV_CHROMA_SUPP, PREV_CHROMA_SUPPRESS,
704 preview_config_chroma_suppression,
705 preview_enable_chroma_suppression},
706 {OMAP3ISP_PREV_WB, PREV_WB,
707 preview_config_whitebalance,
708 NULL},
709 {OMAP3ISP_PREV_BLKADJ, PREV_BLKADJ,
710 preview_config_blkadj,
711 NULL},
712 {OMAP3ISP_PREV_RGB2RGB, PREV_RGB2RGB,
713 preview_config_rgb_blending,
714 NULL},
715 {OMAP3ISP_PREV_COLOR_CONV, PREV_COLOR_CONV,
716 preview_config_rgb_to_ycbcr,
717 NULL},
718 {OMAP3ISP_PREV_YC_LIMIT, PREV_YCLIMITS,
719 preview_config_yc_range,
720 NULL},
721 {OMAP3ISP_PREV_DEFECT_COR, PREV_DEFECT_COR,
722 preview_config_dcor,
723 preview_enable_dcor},
724 {OMAP3ISP_PREV_GAMMABYPASS, PREV_GAMMA_BYPASS,
725 NULL,
726 preview_enable_gammabypass},
727 {OMAP3ISP_PREV_DRK_FRM_CAPTURE, PREV_DARK_FRAME_CAPTURE,
728 NULL,
729 preview_enable_drkframe_capture},
730 {OMAP3ISP_PREV_DRK_FRM_SUBTRACT, PREV_DARK_FRAME_SUBTRACT,
731 NULL,
732 preview_enable_drkframe},
733 {OMAP3ISP_PREV_LENS_SHADING, PREV_LENS_SHADING,
734 preview_config_drkf_shadcomp,
735 preview_enable_drkframe},
736 {OMAP3ISP_PREV_NF, PREV_NOISE_FILTER,
737 preview_config_noisefilter,
738 preview_enable_noisefilter},
739 {OMAP3ISP_PREV_GAMMA, PREV_GAMMA,
740 preview_config_gammacorrn,
741 NULL},
742 {-1, PREV_CONTRAST,
743 preview_config_contrast,
744 NULL},
745 {-1, PREV_BRIGHTNESS,
746 preview_config_brightness,
747 NULL},
751 * __preview_get_ptrs - helper function which return pointers to members
752 * of params and config structures.
753 * @params - pointer to preview_params structure.
754 * @param - return pointer to appropriate structure field.
755 * @configs - pointer to update config structure.
756 * @config - return pointer to appropriate structure field.
757 * @bit - for which feature to return pointers.
758 * Return size of coresponding prev_params member
760 static u32
761 __preview_get_ptrs(struct prev_params *params, void **param,
762 struct omap3isp_prev_update_config *configs,
763 void __user **config, u32 bit)
765 #define CHKARG(cfgs, cfg, field) \
766 if (cfgs && cfg) { \
767 *(cfg) = (cfgs)->field; \
770 switch (bit) {
771 case PREV_HORZ_MEDIAN_FILTER:
772 *param = &params->hmed;
773 CHKARG(configs, config, hmed)
774 return sizeof(params->hmed);
775 case PREV_NOISE_FILTER:
776 *param = &params->nf;
777 CHKARG(configs, config, nf)
778 return sizeof(params->nf);
779 break;
780 case PREV_CFA:
781 *param = &params->cfa;
782 CHKARG(configs, config, cfa)
783 return sizeof(params->cfa);
784 case PREV_LUMA_ENHANCE:
785 *param = &params->luma;
786 CHKARG(configs, config, luma)
787 return sizeof(params->luma);
788 case PREV_CHROMA_SUPPRESS:
789 *param = &params->csup;
790 CHKARG(configs, config, csup)
791 return sizeof(params->csup);
792 case PREV_DEFECT_COR:
793 *param = &params->dcor;
794 CHKARG(configs, config, dcor)
795 return sizeof(params->dcor);
796 case PREV_BLKADJ:
797 *param = &params->blk_adj;
798 CHKARG(configs, config, blkadj)
799 return sizeof(params->blk_adj);
800 case PREV_YCLIMITS:
801 *param = &params->yclimit;
802 CHKARG(configs, config, yclimit)
803 return sizeof(params->yclimit);
804 case PREV_RGB2RGB:
805 *param = &params->rgb2rgb;
806 CHKARG(configs, config, rgb2rgb)
807 return sizeof(params->rgb2rgb);
808 case PREV_COLOR_CONV:
809 *param = &params->rgb2ycbcr;
810 CHKARG(configs, config, csc)
811 return sizeof(params->rgb2ycbcr);
812 case PREV_WB:
813 *param = &params->wbal;
814 CHKARG(configs, config, wbal)
815 return sizeof(params->wbal);
816 case PREV_GAMMA:
817 *param = &params->gamma;
818 CHKARG(configs, config, gamma)
819 return sizeof(params->gamma);
820 case PREV_CONTRAST:
821 *param = &params->contrast;
822 return 0;
823 case PREV_BRIGHTNESS:
824 *param = &params->brightness;
825 return 0;
826 default:
827 *param = NULL;
828 *config = NULL;
829 break;
831 return 0;
835 * preview_config - Copy and update local structure with userspace preview
836 * configuration.
837 * @prev: ISP preview engine
838 * @cfg: Configuration
840 * Return zero if success or -EFAULT if the configuration can't be copied from
841 * userspace.
843 static int preview_config(struct isp_prev_device *prev,
844 struct omap3isp_prev_update_config *cfg)
846 struct prev_params *params;
847 struct preview_update *attr;
848 int i, bit, rval = 0;
850 params = &prev->params;
852 if (prev->state != ISP_PIPELINE_STREAM_STOPPED) {
853 unsigned long flags;
855 spin_lock_irqsave(&prev->lock, flags);
856 prev->shadow_update = 1;
857 spin_unlock_irqrestore(&prev->lock, flags);
860 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
861 attr = &update_attrs[i];
862 bit = 0;
864 if (!(cfg->update & attr->cfg_bit))
865 continue;
867 bit = cfg->flag & attr->cfg_bit;
868 if (bit) {
869 void *to = NULL, __user *from = NULL;
870 unsigned long sz = 0;
872 sz = __preview_get_ptrs(params, &to, cfg, &from,
873 bit);
874 if (to && from && sz) {
875 if (copy_from_user(to, from, sz)) {
876 rval = -EFAULT;
877 break;
880 params->features |= attr->feature_bit;
881 } else {
882 params->features &= ~attr->feature_bit;
885 prev->update |= attr->feature_bit;
888 prev->shadow_update = 0;
889 return rval;
893 * preview_setup_hw - Setup preview registers and/or internal memory
894 * @prev: pointer to preview private structure
895 * Note: can be called from interrupt context
896 * Return none
898 static void preview_setup_hw(struct isp_prev_device *prev)
900 struct prev_params *params = &prev->params;
901 struct preview_update *attr;
902 int i, bit;
903 void *param_ptr;
905 for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
906 attr = &update_attrs[i];
908 if (!(prev->update & attr->feature_bit))
909 continue;
910 bit = params->features & attr->feature_bit;
911 if (bit) {
912 if (attr->config) {
913 __preview_get_ptrs(params, &param_ptr, NULL,
914 NULL, bit);
915 attr->config(prev, param_ptr);
917 if (attr->enable)
918 attr->enable(prev, 1);
919 } else
920 if (attr->enable)
921 attr->enable(prev, 0);
923 prev->update &= ~attr->feature_bit;
928 * preview_config_ycpos - Configure byte layout of YUV image.
929 * @mode: Indicates the required byte layout.
931 static void
932 preview_config_ycpos(struct isp_prev_device *prev,
933 enum v4l2_mbus_pixelcode pixelcode)
935 struct isp_device *isp = to_isp_device(prev);
936 enum preview_ycpos_mode mode;
938 switch (pixelcode) {
939 case V4L2_MBUS_FMT_YUYV8_1X16:
940 mode = YCPOS_CrYCbY;
941 break;
942 case V4L2_MBUS_FMT_UYVY8_1X16:
943 mode = YCPOS_YCrYCb;
944 break;
945 default:
946 return;
949 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
950 ISPPRV_PCR_YCPOS_CrYCbY,
951 mode << ISPPRV_PCR_YCPOS_SHIFT);
955 * preview_config_averager - Enable / disable / configure averager
956 * @average: Average value to be configured.
958 static void preview_config_averager(struct isp_prev_device *prev, u8 average)
960 struct isp_device *isp = to_isp_device(prev);
961 int reg = 0;
963 if (prev->params.cfa.format == OMAP3ISP_CFAFMT_BAYER)
964 reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
965 ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
966 average;
967 else if (prev->params.cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
968 reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
969 ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
970 average;
971 isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
975 * preview_config_input_size - Configure the input frame size
977 * The preview engine crops several rows and columns internally depending on
978 * which processing blocks are enabled. The driver assumes all those blocks are
979 * enabled when reporting source pad formats to userspace. If this assumption is
980 * not true, rows and columns must be manually cropped at the preview engine
981 * input to avoid overflows at the end of lines and frames.
983 static void preview_config_input_size(struct isp_prev_device *prev)
985 struct isp_device *isp = to_isp_device(prev);
986 struct prev_params *params = &prev->params;
987 struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
988 unsigned int sph = 0;
989 unsigned int eph = format->width - 1;
990 unsigned int slv = 0;
991 unsigned int elv = format->height - 1;
993 if (prev->input == PREVIEW_INPUT_CCDC) {
994 sph += 2;
995 eph -= 2;
999 * Median filter 4 pixels
1000 * Noise filter 4 pixels, 4 lines
1001 * or faulty pixels correction
1002 * CFA filter 4 pixels, 4 lines in Bayer mode
1003 * 2 lines in other modes
1004 * Color suppression 2 pixels
1005 * or luma enhancement
1006 * -------------------------------------------------------------
1007 * Maximum total 14 pixels, 8 lines
1010 if (!(params->features & PREV_CFA)) {
1011 sph += 2;
1012 eph -= 2;
1013 slv += 2;
1014 elv -= 2;
1016 if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
1017 sph += 2;
1018 eph -= 2;
1019 slv += 2;
1020 elv -= 2;
1022 if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
1023 sph += 2;
1024 eph -= 2;
1026 if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
1027 sph += 2;
1029 isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
1030 OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
1031 isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
1032 OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
1036 * preview_config_inlineoffset - Configures the Read address line offset.
1037 * @prev: Preview module
1038 * @offset: Line offset
1040 * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
1041 * However, a hardware bug requires the memory start address to be aligned on a
1042 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
1043 * well.
1045 static void
1046 preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
1048 struct isp_device *isp = to_isp_device(prev);
1050 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1051 ISPPRV_RADR_OFFSET);
1055 * preview_set_inaddr - Sets memory address of input frame.
1056 * @addr: 32bit memory address aligned on 32byte boundary.
1058 * Configures the memory address from which the input frame is to be read.
1060 static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
1062 struct isp_device *isp = to_isp_device(prev);
1064 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
1068 * preview_config_outlineoffset - Configures the Write address line offset.
1069 * @offset: Line Offset for the preview output.
1071 * The offset must be a multiple of 32 bytes.
1073 static void preview_config_outlineoffset(struct isp_prev_device *prev,
1074 u32 offset)
1076 struct isp_device *isp = to_isp_device(prev);
1078 isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
1079 ISPPRV_WADD_OFFSET);
1083 * preview_set_outaddr - Sets the memory address to store output frame
1084 * @addr: 32bit memory address aligned on 32byte boundary.
1086 * Configures the memory address to which the output frame is written.
1088 static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
1090 struct isp_device *isp = to_isp_device(prev);
1092 isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
1095 static void preview_adjust_bandwidth(struct isp_prev_device *prev)
1097 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1098 struct isp_device *isp = to_isp_device(prev);
1099 const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
1100 unsigned long l3_ick = pipe->l3_ick;
1101 struct v4l2_fract *timeperframe;
1102 unsigned int cycles_per_frame;
1103 unsigned int requests_per_frame;
1104 unsigned int cycles_per_request;
1105 unsigned int minimum;
1106 unsigned int maximum;
1107 unsigned int value;
1109 if (prev->input != PREVIEW_INPUT_MEMORY) {
1110 isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1111 ISPSBL_SDR_REQ_PRV_EXP_MASK);
1112 return;
1115 /* Compute the minimum number of cycles per request, based on the
1116 * pipeline maximum data rate. This is an absolute lower bound if we
1117 * don't want SBL overflows, so round the value up.
1119 cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
1120 pipe->max_rate);
1121 minimum = DIV_ROUND_UP(cycles_per_request, 32);
1123 /* Compute the maximum number of cycles per request, based on the
1124 * requested frame rate. This is a soft upper bound to achieve a frame
1125 * rate equal or higher than the requested value, so round the value
1126 * down.
1128 timeperframe = &pipe->max_timeperframe;
1130 requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
1131 cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
1132 timeperframe->denominator);
1133 cycles_per_request = cycles_per_frame / requests_per_frame;
1135 maximum = cycles_per_request / 32;
1137 value = max(minimum, maximum);
1139 dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
1140 isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
1141 ISPSBL_SDR_REQ_PRV_EXP_MASK,
1142 value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
1146 * omap3isp_preview_busy - Gets busy state of preview module.
1148 int omap3isp_preview_busy(struct isp_prev_device *prev)
1150 struct isp_device *isp = to_isp_device(prev);
1152 return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
1153 & ISPPRV_PCR_BUSY;
1157 * omap3isp_preview_restore_context - Restores the values of preview registers
1159 void omap3isp_preview_restore_context(struct isp_device *isp)
1161 isp->isp_prev.update = PREV_FEATURES_END - 1;
1162 preview_setup_hw(&isp->isp_prev);
1166 * preview_print_status - Dump preview module registers to the kernel log
1168 #define PREV_PRINT_REGISTER(isp, name)\
1169 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1170 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1172 static void preview_print_status(struct isp_prev_device *prev)
1174 struct isp_device *isp = to_isp_device(prev);
1176 dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
1178 PREV_PRINT_REGISTER(isp, PCR);
1179 PREV_PRINT_REGISTER(isp, HORZ_INFO);
1180 PREV_PRINT_REGISTER(isp, VERT_INFO);
1181 PREV_PRINT_REGISTER(isp, RSDR_ADDR);
1182 PREV_PRINT_REGISTER(isp, RADR_OFFSET);
1183 PREV_PRINT_REGISTER(isp, DSDR_ADDR);
1184 PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
1185 PREV_PRINT_REGISTER(isp, WSDR_ADDR);
1186 PREV_PRINT_REGISTER(isp, WADD_OFFSET);
1187 PREV_PRINT_REGISTER(isp, AVE);
1188 PREV_PRINT_REGISTER(isp, HMED);
1189 PREV_PRINT_REGISTER(isp, NF);
1190 PREV_PRINT_REGISTER(isp, WB_DGAIN);
1191 PREV_PRINT_REGISTER(isp, WBGAIN);
1192 PREV_PRINT_REGISTER(isp, WBSEL);
1193 PREV_PRINT_REGISTER(isp, CFA);
1194 PREV_PRINT_REGISTER(isp, BLKADJOFF);
1195 PREV_PRINT_REGISTER(isp, RGB_MAT1);
1196 PREV_PRINT_REGISTER(isp, RGB_MAT2);
1197 PREV_PRINT_REGISTER(isp, RGB_MAT3);
1198 PREV_PRINT_REGISTER(isp, RGB_MAT4);
1199 PREV_PRINT_REGISTER(isp, RGB_MAT5);
1200 PREV_PRINT_REGISTER(isp, RGB_OFF1);
1201 PREV_PRINT_REGISTER(isp, RGB_OFF2);
1202 PREV_PRINT_REGISTER(isp, CSC0);
1203 PREV_PRINT_REGISTER(isp, CSC1);
1204 PREV_PRINT_REGISTER(isp, CSC2);
1205 PREV_PRINT_REGISTER(isp, CSC_OFFSET);
1206 PREV_PRINT_REGISTER(isp, CNT_BRT);
1207 PREV_PRINT_REGISTER(isp, CSUP);
1208 PREV_PRINT_REGISTER(isp, SETUP_YC);
1209 PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
1210 PREV_PRINT_REGISTER(isp, CDC_THR0);
1211 PREV_PRINT_REGISTER(isp, CDC_THR1);
1212 PREV_PRINT_REGISTER(isp, CDC_THR2);
1213 PREV_PRINT_REGISTER(isp, CDC_THR3);
1215 dev_dbg(isp->dev, "--------------------------------------------\n");
1219 * preview_init_params - init image processing parameters.
1220 * @prev: pointer to previewer private structure
1221 * return none
1223 static void preview_init_params(struct isp_prev_device *prev)
1225 struct prev_params *params = &prev->params;
1226 int i = 0;
1228 /* Init values */
1229 params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
1230 params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
1231 params->average = NO_AVE;
1232 params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
1233 memcpy(params->cfa.table, cfa_coef_table,
1234 sizeof(params->cfa.table));
1235 params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
1236 params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
1237 params->csup.gain = FLR_CSUP_GAIN;
1238 params->csup.thres = FLR_CSUP_THRES;
1239 params->csup.hypf_en = 0;
1240 memcpy(params->luma.table, luma_enhance_table,
1241 sizeof(params->luma.table));
1242 params->nf.spread = FLR_NF_STRGTH;
1243 memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
1244 params->dcor.couplet_mode_en = 1;
1245 for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
1246 params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
1247 memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
1248 memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
1249 memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
1250 params->wbal.dgain = FLR_WBAL_DGAIN;
1251 params->wbal.coef0 = FLR_WBAL_COEF;
1252 params->wbal.coef1 = FLR_WBAL_COEF;
1253 params->wbal.coef2 = FLR_WBAL_COEF;
1254 params->wbal.coef3 = FLR_WBAL_COEF;
1255 params->blk_adj.red = FLR_BLKADJ_RED;
1256 params->blk_adj.green = FLR_BLKADJ_GREEN;
1257 params->blk_adj.blue = FLR_BLKADJ_BLUE;
1258 params->rgb2rgb = flr_rgb2rgb;
1259 params->rgb2ycbcr = flr_prev_csc;
1260 params->yclimit.minC = ISPPRV_YC_MIN;
1261 params->yclimit.maxC = ISPPRV_YC_MAX;
1262 params->yclimit.minY = ISPPRV_YC_MIN;
1263 params->yclimit.maxY = ISPPRV_YC_MAX;
1265 params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER
1266 | PREV_GAMMA | PREV_BLKADJ | PREV_YCLIMITS
1267 | PREV_RGB2RGB | PREV_COLOR_CONV | PREV_WB
1268 | PREV_BRIGHTNESS | PREV_CONTRAST;
1270 prev->update = PREV_FEATURES_END - 1;
1274 * preview_max_out_width - Handle previewer hardware ouput limitations
1275 * @isp_revision : ISP revision
1276 * returns maximum width output for current isp revision
1278 static unsigned int preview_max_out_width(struct isp_prev_device *prev)
1280 struct isp_device *isp = to_isp_device(prev);
1282 switch (isp->revision) {
1283 case ISP_REVISION_1_0:
1284 return ISPPRV_MAXOUTPUT_WIDTH;
1286 case ISP_REVISION_2_0:
1287 default:
1288 return ISPPRV_MAXOUTPUT_WIDTH_ES2;
1290 case ISP_REVISION_15_0:
1291 return ISPPRV_MAXOUTPUT_WIDTH_3630;
1295 static void preview_configure(struct isp_prev_device *prev)
1297 struct isp_device *isp = to_isp_device(prev);
1298 struct v4l2_mbus_framefmt *format;
1299 unsigned int max_out_width;
1300 unsigned int format_avg;
1302 preview_setup_hw(prev);
1304 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1305 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1306 ISPPRV_PCR_SDRPORT);
1307 else
1308 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1309 ISPPRV_PCR_SDRPORT);
1311 if (prev->output & PREVIEW_OUTPUT_RESIZER)
1312 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1313 ISPPRV_PCR_RSZPORT);
1314 else
1315 isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1316 ISPPRV_PCR_RSZPORT);
1318 /* PREV_PAD_SINK */
1319 format = &prev->formats[PREV_PAD_SINK];
1321 preview_adjust_bandwidth(prev);
1323 preview_config_input_size(prev);
1325 if (prev->input == PREVIEW_INPUT_CCDC)
1326 preview_config_inlineoffset(prev, 0);
1327 else
1328 preview_config_inlineoffset(prev,
1329 ALIGN(format->width, 0x20) * 2);
1331 /* PREV_PAD_SOURCE */
1332 format = &prev->formats[PREV_PAD_SOURCE];
1334 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1335 preview_config_outlineoffset(prev,
1336 ALIGN(format->width, 0x10) * 2);
1338 max_out_width = preview_max_out_width(prev);
1340 format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
1341 preview_config_averager(prev, format_avg);
1342 preview_config_ycpos(prev, format->code);
1345 /* -----------------------------------------------------------------------------
1346 * Interrupt handling
1349 static void preview_enable_oneshot(struct isp_prev_device *prev)
1351 struct isp_device *isp = to_isp_device(prev);
1353 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
1354 * bit is set. As the preview engine is used in single-shot mode, we
1355 * need to set PCR.SOURCE before enabling the preview engine.
1357 if (prev->input == PREVIEW_INPUT_MEMORY)
1358 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1359 ISPPRV_PCR_SOURCE);
1361 isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
1362 ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
1365 void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
1368 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1369 * condition, the module was paused and now we have a buffer queued
1370 * on the output again. Restart the pipeline if running in continuous
1371 * mode.
1373 if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
1374 prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
1375 preview_enable_oneshot(prev);
1376 isp_video_dmaqueue_flags_clr(&prev->video_out);
1380 static void preview_isr_buffer(struct isp_prev_device *prev)
1382 struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
1383 struct isp_buffer *buffer;
1384 int restart = 0;
1386 if (prev->input == PREVIEW_INPUT_MEMORY) {
1387 buffer = omap3isp_video_buffer_next(&prev->video_in,
1388 prev->error);
1389 if (buffer != NULL)
1390 preview_set_inaddr(prev, buffer->isp_addr);
1391 pipe->state |= ISP_PIPELINE_IDLE_INPUT;
1394 if (prev->output & PREVIEW_OUTPUT_MEMORY) {
1395 buffer = omap3isp_video_buffer_next(&prev->video_out,
1396 prev->error);
1397 if (buffer != NULL) {
1398 preview_set_outaddr(prev, buffer->isp_addr);
1399 restart = 1;
1401 pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
1404 switch (prev->state) {
1405 case ISP_PIPELINE_STREAM_SINGLESHOT:
1406 if (isp_pipeline_ready(pipe))
1407 omap3isp_pipeline_set_stream(pipe,
1408 ISP_PIPELINE_STREAM_SINGLESHOT);
1409 break;
1411 case ISP_PIPELINE_STREAM_CONTINUOUS:
1412 /* If an underrun occurs, the video queue operation handler will
1413 * restart the preview engine. Otherwise restart it immediately.
1415 if (restart)
1416 preview_enable_oneshot(prev);
1417 break;
1419 case ISP_PIPELINE_STREAM_STOPPED:
1420 default:
1421 return;
1424 prev->error = 0;
1428 * omap3isp_preview_isr - ISP preview engine interrupt handler
1430 * Manage the preview engine video buffers and configure shadowed registers.
1432 void omap3isp_preview_isr(struct isp_prev_device *prev)
1434 unsigned long flags;
1436 if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
1437 return;
1439 spin_lock_irqsave(&prev->lock, flags);
1440 if (prev->shadow_update)
1441 goto done;
1443 preview_setup_hw(prev);
1444 preview_config_input_size(prev);
1446 done:
1447 spin_unlock_irqrestore(&prev->lock, flags);
1449 if (prev->input == PREVIEW_INPUT_MEMORY ||
1450 prev->output & PREVIEW_OUTPUT_MEMORY)
1451 preview_isr_buffer(prev);
1452 else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
1453 preview_enable_oneshot(prev);
1456 /* -----------------------------------------------------------------------------
1457 * ISP video operations
1460 static int preview_video_queue(struct isp_video *video,
1461 struct isp_buffer *buffer)
1463 struct isp_prev_device *prev = &video->isp->isp_prev;
1465 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
1466 preview_set_inaddr(prev, buffer->isp_addr);
1468 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1469 preview_set_outaddr(prev, buffer->isp_addr);
1471 return 0;
1474 static const struct isp_video_operations preview_video_ops = {
1475 .queue = preview_video_queue,
1478 /* -----------------------------------------------------------------------------
1479 * V4L2 subdev operations
1483 * preview_s_ctrl - Handle set control subdev method
1484 * @ctrl: pointer to v4l2 control structure
1486 static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
1488 struct isp_prev_device *prev =
1489 container_of(ctrl->handler, struct isp_prev_device, ctrls);
1491 switch (ctrl->id) {
1492 case V4L2_CID_BRIGHTNESS:
1493 preview_update_brightness(prev, ctrl->val);
1494 break;
1495 case V4L2_CID_CONTRAST:
1496 preview_update_contrast(prev, ctrl->val);
1497 break;
1500 return 0;
1503 static const struct v4l2_ctrl_ops preview_ctrl_ops = {
1504 .s_ctrl = preview_s_ctrl,
1508 * preview_ioctl - Handle preview module private ioctl's
1509 * @prev: pointer to preview context structure
1510 * @cmd: configuration command
1511 * @arg: configuration argument
1512 * return -EINVAL or zero on success
1514 static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1516 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1518 switch (cmd) {
1519 case VIDIOC_OMAP3ISP_PRV_CFG:
1520 return preview_config(prev, arg);
1522 default:
1523 return -ENOIOCTLCMD;
1528 * preview_set_stream - Enable/Disable streaming on preview subdev
1529 * @sd : pointer to v4l2 subdev structure
1530 * @enable: 1 == Enable, 0 == Disable
1531 * return -EINVAL or zero on sucess
1533 static int preview_set_stream(struct v4l2_subdev *sd, int enable)
1535 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1536 struct isp_video *video_out = &prev->video_out;
1537 struct isp_device *isp = to_isp_device(prev);
1538 struct device *dev = to_device(prev);
1539 unsigned long flags;
1541 if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
1542 if (enable == ISP_PIPELINE_STREAM_STOPPED)
1543 return 0;
1545 omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1546 preview_configure(prev);
1547 atomic_set(&prev->stopping, 0);
1548 prev->error = 0;
1549 preview_print_status(prev);
1552 switch (enable) {
1553 case ISP_PIPELINE_STREAM_CONTINUOUS:
1554 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1555 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1557 if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
1558 !(prev->output & PREVIEW_OUTPUT_MEMORY))
1559 preview_enable_oneshot(prev);
1561 isp_video_dmaqueue_flags_clr(video_out);
1562 break;
1564 case ISP_PIPELINE_STREAM_SINGLESHOT:
1565 if (prev->input == PREVIEW_INPUT_MEMORY)
1566 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1567 if (prev->output & PREVIEW_OUTPUT_MEMORY)
1568 omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1570 preview_enable_oneshot(prev);
1571 break;
1573 case ISP_PIPELINE_STREAM_STOPPED:
1574 if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
1575 &prev->stopping))
1576 dev_dbg(dev, "%s: stop timeout.\n", sd->name);
1577 spin_lock_irqsave(&prev->lock, flags);
1578 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
1579 omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
1580 omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
1581 spin_unlock_irqrestore(&prev->lock, flags);
1582 isp_video_dmaqueue_flags_clr(video_out);
1583 break;
1586 prev->state = enable;
1587 return 0;
1590 static struct v4l2_mbus_framefmt *
1591 __preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
1592 unsigned int pad, enum v4l2_subdev_format_whence which)
1594 if (which == V4L2_SUBDEV_FORMAT_TRY)
1595 return v4l2_subdev_get_try_format(fh, pad);
1596 else
1597 return &prev->formats[pad];
1600 /* previewer format descriptions */
1601 static const unsigned int preview_input_fmts[] = {
1602 V4L2_MBUS_FMT_SGRBG10_1X10,
1603 V4L2_MBUS_FMT_SRGGB10_1X10,
1604 V4L2_MBUS_FMT_SBGGR10_1X10,
1605 V4L2_MBUS_FMT_SGBRG10_1X10,
1608 static const unsigned int preview_output_fmts[] = {
1609 V4L2_MBUS_FMT_UYVY8_1X16,
1610 V4L2_MBUS_FMT_YUYV8_1X16,
1614 * preview_try_format - Handle try format by pad subdev method
1615 * @prev: ISP preview device
1616 * @fh : V4L2 subdev file handle
1617 * @pad: pad num
1618 * @fmt: pointer to v4l2 format structure
1620 static void preview_try_format(struct isp_prev_device *prev,
1621 struct v4l2_subdev_fh *fh, unsigned int pad,
1622 struct v4l2_mbus_framefmt *fmt,
1623 enum v4l2_subdev_format_whence which)
1625 struct v4l2_mbus_framefmt *format;
1626 unsigned int max_out_width;
1627 enum v4l2_mbus_pixelcode pixelcode;
1628 unsigned int i;
1630 max_out_width = preview_max_out_width(prev);
1632 switch (pad) {
1633 case PREV_PAD_SINK:
1634 /* When reading data from the CCDC, the input size has already
1635 * been mangled by the CCDC output pad so it can be accepted
1636 * as-is.
1638 * When reading data from memory, clamp the requested width and
1639 * height. The TRM doesn't specify a minimum input height, make
1640 * sure we got enough lines to enable the noise filter and color
1641 * filter array interpolation.
1643 if (prev->input == PREVIEW_INPUT_MEMORY) {
1644 fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
1645 max_out_width * 8);
1646 fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
1647 PREV_MAX_HEIGHT);
1650 fmt->colorspace = V4L2_COLORSPACE_SRGB;
1652 for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
1653 if (fmt->code == preview_input_fmts[i])
1654 break;
1657 /* If not found, use SGRBG10 as default */
1658 if (i >= ARRAY_SIZE(preview_input_fmts))
1659 fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
1660 break;
1662 case PREV_PAD_SOURCE:
1663 pixelcode = fmt->code;
1664 format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
1665 memcpy(fmt, format, sizeof(*fmt));
1667 /* The preview module output size is configurable through the
1668 * input interface (horizontal and vertical cropping) and the
1669 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
1670 * spite of this, hardcode the output size to the biggest
1671 * possible value for simplicity reasons.
1673 switch (pixelcode) {
1674 case V4L2_MBUS_FMT_YUYV8_1X16:
1675 case V4L2_MBUS_FMT_UYVY8_1X16:
1676 fmt->code = pixelcode;
1677 break;
1679 default:
1680 fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
1681 break;
1684 /* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
1685 * from the left and right sides when the input source is the
1686 * CCDC. This seems not to be needed in practice, investigation
1687 * is required.
1689 if (prev->input == PREVIEW_INPUT_CCDC)
1690 fmt->width -= 4;
1692 /* The preview module can output a maximum of 3312 pixels
1693 * horizontally due to fixed memory-line sizes. Compute the
1694 * horizontal averaging factor accordingly. Note that the limit
1695 * applies to the noise filter and CFA interpolation blocks, so
1696 * it doesn't take cropping by further blocks into account.
1698 * ES 1.0 hardware revision is limited to 1280 pixels
1699 * horizontally.
1701 fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
1703 /* Assume that all blocks are enabled and crop pixels and lines
1704 * accordingly. See preview_config_input_size() for more
1705 * information.
1707 fmt->width -= 14;
1708 fmt->height -= 8;
1710 fmt->colorspace = V4L2_COLORSPACE_JPEG;
1711 break;
1714 fmt->field = V4L2_FIELD_NONE;
1718 * preview_enum_mbus_code - Handle pixel format enumeration
1719 * @sd : pointer to v4l2 subdev structure
1720 * @fh : V4L2 subdev file handle
1721 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1722 * return -EINVAL or zero on success
1724 static int preview_enum_mbus_code(struct v4l2_subdev *sd,
1725 struct v4l2_subdev_fh *fh,
1726 struct v4l2_subdev_mbus_code_enum *code)
1728 switch (code->pad) {
1729 case PREV_PAD_SINK:
1730 if (code->index >= ARRAY_SIZE(preview_input_fmts))
1731 return -EINVAL;
1733 code->code = preview_input_fmts[code->index];
1734 break;
1735 case PREV_PAD_SOURCE:
1736 if (code->index >= ARRAY_SIZE(preview_output_fmts))
1737 return -EINVAL;
1739 code->code = preview_output_fmts[code->index];
1740 break;
1741 default:
1742 return -EINVAL;
1745 return 0;
1748 static int preview_enum_frame_size(struct v4l2_subdev *sd,
1749 struct v4l2_subdev_fh *fh,
1750 struct v4l2_subdev_frame_size_enum *fse)
1752 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1753 struct v4l2_mbus_framefmt format;
1755 if (fse->index != 0)
1756 return -EINVAL;
1758 format.code = fse->code;
1759 format.width = 1;
1760 format.height = 1;
1761 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1762 fse->min_width = format.width;
1763 fse->min_height = format.height;
1765 if (format.code != fse->code)
1766 return -EINVAL;
1768 format.code = fse->code;
1769 format.width = -1;
1770 format.height = -1;
1771 preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
1772 fse->max_width = format.width;
1773 fse->max_height = format.height;
1775 return 0;
1779 * preview_get_format - Handle get format by pads subdev method
1780 * @sd : pointer to v4l2 subdev structure
1781 * @fh : V4L2 subdev file handle
1782 * @fmt: pointer to v4l2 subdev format structure
1783 * return -EINVAL or zero on sucess
1785 static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1786 struct v4l2_subdev_format *fmt)
1788 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1789 struct v4l2_mbus_framefmt *format;
1791 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1792 if (format == NULL)
1793 return -EINVAL;
1795 fmt->format = *format;
1796 return 0;
1800 * preview_set_format - Handle set format by pads subdev method
1801 * @sd : pointer to v4l2 subdev structure
1802 * @fh : V4L2 subdev file handle
1803 * @fmt: pointer to v4l2 subdev format structure
1804 * return -EINVAL or zero on success
1806 static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1807 struct v4l2_subdev_format *fmt)
1809 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1810 struct v4l2_mbus_framefmt *format;
1812 format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
1813 if (format == NULL)
1814 return -EINVAL;
1816 preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
1817 *format = fmt->format;
1819 /* Propagate the format from sink to source */
1820 if (fmt->pad == PREV_PAD_SINK) {
1821 format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
1822 fmt->which);
1823 *format = fmt->format;
1824 preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
1825 fmt->which);
1828 return 0;
1832 * preview_init_formats - Initialize formats on all pads
1833 * @sd: ISP preview V4L2 subdevice
1834 * @fh: V4L2 subdev file handle
1836 * Initialize all pad formats with default values. If fh is not NULL, try
1837 * formats are initialized on the file handle. Otherwise active formats are
1838 * initialized on the device.
1840 static int preview_init_formats(struct v4l2_subdev *sd,
1841 struct v4l2_subdev_fh *fh)
1843 struct v4l2_subdev_format format;
1845 memset(&format, 0, sizeof(format));
1846 format.pad = PREV_PAD_SINK;
1847 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1848 format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
1849 format.format.width = 4096;
1850 format.format.height = 4096;
1851 preview_set_format(sd, fh, &format);
1853 return 0;
1856 /* subdev core operations */
1857 static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
1858 .ioctl = preview_ioctl,
1861 /* subdev video operations */
1862 static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
1863 .s_stream = preview_set_stream,
1866 /* subdev pad operations */
1867 static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
1868 .enum_mbus_code = preview_enum_mbus_code,
1869 .enum_frame_size = preview_enum_frame_size,
1870 .get_fmt = preview_get_format,
1871 .set_fmt = preview_set_format,
1874 /* subdev operations */
1875 static const struct v4l2_subdev_ops preview_v4l2_ops = {
1876 .core = &preview_v4l2_core_ops,
1877 .video = &preview_v4l2_video_ops,
1878 .pad = &preview_v4l2_pad_ops,
1881 /* subdev internal operations */
1882 static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
1883 .open = preview_init_formats,
1886 /* -----------------------------------------------------------------------------
1887 * Media entity operations
1891 * preview_link_setup - Setup previewer connections.
1892 * @entity : Pointer to media entity structure
1893 * @local : Pointer to local pad array
1894 * @remote : Pointer to remote pad array
1895 * @flags : Link flags
1896 * return -EINVAL or zero on success
1898 static int preview_link_setup(struct media_entity *entity,
1899 const struct media_pad *local,
1900 const struct media_pad *remote, u32 flags)
1902 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1903 struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
1905 switch (local->index | media_entity_type(remote->entity)) {
1906 case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
1907 /* read from memory */
1908 if (flags & MEDIA_LNK_FL_ENABLED) {
1909 if (prev->input == PREVIEW_INPUT_CCDC)
1910 return -EBUSY;
1911 prev->input = PREVIEW_INPUT_MEMORY;
1912 } else {
1913 if (prev->input == PREVIEW_INPUT_MEMORY)
1914 prev->input = PREVIEW_INPUT_NONE;
1916 break;
1918 case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1919 /* read from ccdc */
1920 if (flags & MEDIA_LNK_FL_ENABLED) {
1921 if (prev->input == PREVIEW_INPUT_MEMORY)
1922 return -EBUSY;
1923 prev->input = PREVIEW_INPUT_CCDC;
1924 } else {
1925 if (prev->input == PREVIEW_INPUT_CCDC)
1926 prev->input = PREVIEW_INPUT_NONE;
1928 break;
1931 * The ISP core doesn't support pipelines with multiple video outputs.
1932 * Revisit this when it will be implemented, and return -EBUSY for now.
1935 case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1936 /* write to memory */
1937 if (flags & MEDIA_LNK_FL_ENABLED) {
1938 if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
1939 return -EBUSY;
1940 prev->output |= PREVIEW_OUTPUT_MEMORY;
1941 } else {
1942 prev->output &= ~PREVIEW_OUTPUT_MEMORY;
1944 break;
1946 case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1947 /* write to resizer */
1948 if (flags & MEDIA_LNK_FL_ENABLED) {
1949 if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
1950 return -EBUSY;
1951 prev->output |= PREVIEW_OUTPUT_RESIZER;
1952 } else {
1953 prev->output &= ~PREVIEW_OUTPUT_RESIZER;
1955 break;
1957 default:
1958 return -EINVAL;
1961 return 0;
1964 /* media operations */
1965 static const struct media_entity_operations preview_media_ops = {
1966 .link_setup = preview_link_setup,
1970 * review_init_entities - Initialize subdev and media entity.
1971 * @prev : Pointer to preview structure
1972 * return -ENOMEM or zero on success
1974 static int preview_init_entities(struct isp_prev_device *prev)
1976 struct v4l2_subdev *sd = &prev->subdev;
1977 struct media_pad *pads = prev->pads;
1978 struct media_entity *me = &sd->entity;
1979 int ret;
1981 prev->input = PREVIEW_INPUT_NONE;
1983 v4l2_subdev_init(sd, &preview_v4l2_ops);
1984 sd->internal_ops = &preview_v4l2_internal_ops;
1985 strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
1986 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
1987 v4l2_set_subdevdata(sd, prev);
1988 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1990 v4l2_ctrl_handler_init(&prev->ctrls, 2);
1991 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
1992 ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
1993 ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
1994 v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
1995 ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
1996 ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
1997 v4l2_ctrl_handler_setup(&prev->ctrls);
1998 sd->ctrl_handler = &prev->ctrls;
2000 pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2001 pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2003 me->ops = &preview_media_ops;
2004 ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
2005 if (ret < 0)
2006 return ret;
2008 preview_init_formats(sd, NULL);
2010 /* According to the OMAP34xx TRM, video buffers need to be aligned on a
2011 * 32 bytes boundary. However, an undocumented hardware bug requires a
2012 * 64 bytes boundary at the preview engine input.
2014 prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
2015 prev->video_in.ops = &preview_video_ops;
2016 prev->video_in.isp = to_isp_device(prev);
2017 prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2018 prev->video_in.bpl_alignment = 64;
2019 prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2020 prev->video_out.ops = &preview_video_ops;
2021 prev->video_out.isp = to_isp_device(prev);
2022 prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
2023 prev->video_out.bpl_alignment = 32;
2025 ret = omap3isp_video_init(&prev->video_in, "preview");
2026 if (ret < 0)
2027 return ret;
2029 ret = omap3isp_video_init(&prev->video_out, "preview");
2030 if (ret < 0)
2031 return ret;
2033 /* Connect the video nodes to the previewer subdev. */
2034 ret = media_entity_create_link(&prev->video_in.video.entity, 0,
2035 &prev->subdev.entity, PREV_PAD_SINK, 0);
2036 if (ret < 0)
2037 return ret;
2039 ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
2040 &prev->video_out.video.entity, 0, 0);
2041 if (ret < 0)
2042 return ret;
2044 return 0;
2047 void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
2049 media_entity_cleanup(&prev->subdev.entity);
2051 v4l2_device_unregister_subdev(&prev->subdev);
2052 v4l2_ctrl_handler_free(&prev->ctrls);
2053 omap3isp_video_unregister(&prev->video_in);
2054 omap3isp_video_unregister(&prev->video_out);
2057 int omap3isp_preview_register_entities(struct isp_prev_device *prev,
2058 struct v4l2_device *vdev)
2060 int ret;
2062 /* Register the subdev and video nodes. */
2063 ret = v4l2_device_register_subdev(vdev, &prev->subdev);
2064 if (ret < 0)
2065 goto error;
2067 ret = omap3isp_video_register(&prev->video_in, vdev);
2068 if (ret < 0)
2069 goto error;
2071 ret = omap3isp_video_register(&prev->video_out, vdev);
2072 if (ret < 0)
2073 goto error;
2075 return 0;
2077 error:
2078 omap3isp_preview_unregister_entities(prev);
2079 return ret;
2082 /* -----------------------------------------------------------------------------
2083 * ISP previewer initialisation and cleanup
2086 void omap3isp_preview_cleanup(struct isp_device *isp)
2091 * isp_preview_init - Previewer initialization.
2092 * @dev : Pointer to ISP device
2093 * return -ENOMEM or zero on success
2095 int omap3isp_preview_init(struct isp_device *isp)
2097 struct isp_prev_device *prev = &isp->isp_prev;
2098 int ret;
2100 spin_lock_init(&prev->lock);
2101 init_waitqueue_head(&prev->wait);
2102 preview_init_params(prev);
2104 ret = preview_init_entities(prev);
2105 if (ret < 0)
2106 goto out;
2108 out:
2109 if (ret)
2110 omap3isp_preview_cleanup(isp);
2112 return ret;