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
27 #include <linux/device.h>
29 #include <linux/module.h>
30 #include <linux/mutex.h>
31 #include <linux/uaccess.h>
35 #include "isppreview.h"
37 /* Default values in Office Fluorescent 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}
44 {0x0000, 0x0000, 0x0000}
47 /* Default values in Office Fluorescent Light for RGB to YUV Conversion*/
48 static struct omap3isp_prev_csc flr_prev_csc
= {
49 { /* CSC Coef Matrix */
57 /* Default values in Office Fluorescent Light for CFA Gradient*/
58 #define FLR_CFA_GRADTHRS_HORZ 0x28
59 #define FLR_CFA_GRADTHRS_VERT 0x28
61 /* Default values in Office Fluorescent Light for Chroma Suppression*/
62 #define FLR_CSUP_GAIN 0x0D
63 #define FLR_CSUP_THRES 0xEB
65 /* Default values in Office Fluorescent 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 Fluorescent 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
80 * Margins and image size limits.
82 * The preview engine crops several rows and columns internally depending on
83 * which filters are enabled. To avoid format changes when the filters are
84 * enabled or disabled (which would prevent them from being turned on or off
85 * during streaming), the driver assumes all the filters are enabled when
86 * computing sink crop and source format limits.
88 * If a filter is disabled, additional cropping is automatically added at the
89 * preview engine input by the driver to avoid overflow at line and frame end.
90 * This is completely transparent for applications.
92 * Median filter 4 pixels
94 * Faulty pixels correction 4 pixels, 4 lines
95 * CFA filter 4 pixels, 4 lines in Bayer mode
96 * 2 lines in other modes
97 * Color suppression 2 pixels
99 * -------------------------------------------------------------
100 * Maximum total 14 pixels, 8 lines
102 * The color suppression and luma enhancement filters are applied after bayer to
103 * YUV conversion. They thus can crop one pixel on the left and one pixel on the
104 * right side of the image without changing the color pattern. When both those
105 * filters are disabled, the driver must crop the two pixels on the same side of
106 * the image to avoid changing the bayer pattern. The left margin is thus set to
107 * 8 pixels and the right margin to 6 pixels.
110 #define PREV_MARGIN_LEFT 8
111 #define PREV_MARGIN_RIGHT 6
112 #define PREV_MARGIN_TOP 4
113 #define PREV_MARGIN_BOTTOM 4
115 #define PREV_MIN_IN_WIDTH 64
116 #define PREV_MIN_IN_HEIGHT 8
117 #define PREV_MAX_IN_HEIGHT 16384
119 #define PREV_MIN_OUT_WIDTH 0
120 #define PREV_MIN_OUT_HEIGHT 0
121 #define PREV_MAX_OUT_WIDTH_REV_1 1280
122 #define PREV_MAX_OUT_WIDTH_REV_2 3300
123 #define PREV_MAX_OUT_WIDTH_REV_15 4096
126 * Coeficient Tables for the submodules in Preview.
127 * Array is initialised with the values from.the tables text file.
131 * CFA Filter Coefficient Table
134 static u32 cfa_coef_table
[] = {
135 #include "cfa_coef_table.h"
139 * Default Gamma Correction Table - All components
141 static u32 gamma_table
[] = {
142 #include "gamma_table.h"
146 * Noise Filter Threshold table
148 static u32 noise_filter_table
[] = {
149 #include "noise_filter_table.h"
153 * Luminance Enhancement Table
155 static u32 luma_enhance_table
[] = {
156 #include "luma_enhance_table.h"
160 * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
161 * @enable: 1 - Reverse the A-Law done in CCDC.
164 preview_enable_invalaw(struct isp_prev_device
*prev
, u8 enable
)
166 struct isp_device
*isp
= to_isp_device(prev
);
169 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
170 ISPPRV_PCR_WIDTH
| ISPPRV_PCR_INVALAW
);
172 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
173 ISPPRV_PCR_WIDTH
| ISPPRV_PCR_INVALAW
);
177 * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
179 * @enable: 1 - Enable, 0 - Disable
181 * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
182 * The process is applied for each captured frame.
185 preview_enable_drkframe_capture(struct isp_prev_device
*prev
, u8 enable
)
187 struct isp_device
*isp
= to_isp_device(prev
);
190 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
193 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
198 * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
199 * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
200 * subtracted with the pixels in the current frame.
202 * The process is applied for each captured frame.
205 preview_enable_drkframe(struct isp_prev_device
*prev
, u8 enable
)
207 struct isp_device
*isp
= to_isp_device(prev
);
210 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
213 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
218 * preview_config_drkf_shadcomp - Configures shift value in shading comp.
219 * @scomp_shtval: 3bit value of shift used in shading compensation.
222 preview_config_drkf_shadcomp(struct isp_prev_device
*prev
,
223 const void *scomp_shtval
)
225 struct isp_device
*isp
= to_isp_device(prev
);
226 const u32
*shtval
= scomp_shtval
;
228 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
229 ISPPRV_PCR_SCOMP_SFT_MASK
,
230 *shtval
<< ISPPRV_PCR_SCOMP_SFT_SHIFT
);
234 * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
235 * @enable: 1 - Enables Horizontal Median Filter.
238 preview_enable_hmed(struct isp_prev_device
*prev
, u8 enable
)
240 struct isp_device
*isp
= to_isp_device(prev
);
243 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
246 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
251 * preview_config_hmed - Configures the Horizontal Median Filter.
252 * @prev_hmed: Structure containing the odd and even distance between the
253 * pixels in the image along with the filter threshold.
256 preview_config_hmed(struct isp_prev_device
*prev
, const void *prev_hmed
)
258 struct isp_device
*isp
= to_isp_device(prev
);
259 const struct omap3isp_prev_hmed
*hmed
= prev_hmed
;
261 isp_reg_writel(isp
, (hmed
->odddist
== 1 ? 0 : ISPPRV_HMED_ODDDIST
) |
262 (hmed
->evendist
== 1 ? 0 : ISPPRV_HMED_EVENDIST
) |
263 (hmed
->thres
<< ISPPRV_HMED_THRESHOLD_SHIFT
),
264 OMAP3_ISP_IOMEM_PREV
, ISPPRV_HMED
);
268 * preview_config_noisefilter - Configures the Noise Filter.
269 * @prev_nf: Structure containing the noisefilter table, strength to be used
270 * for the noise filter and the defect correction enable flag.
273 preview_config_noisefilter(struct isp_prev_device
*prev
, const void *prev_nf
)
275 struct isp_device
*isp
= to_isp_device(prev
);
276 const struct omap3isp_prev_nf
*nf
= prev_nf
;
279 isp_reg_writel(isp
, nf
->spread
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_NF
);
280 isp_reg_writel(isp
, ISPPRV_NF_TABLE_ADDR
,
281 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
282 for (i
= 0; i
< OMAP3ISP_PREV_NF_TBL_SIZE
; i
++) {
283 isp_reg_writel(isp
, nf
->table
[i
],
284 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_DATA
);
289 * preview_config_dcor - Configures the defect correction
290 * @prev_dcor: Structure containing the defect correct thresholds
293 preview_config_dcor(struct isp_prev_device
*prev
, const void *prev_dcor
)
295 struct isp_device
*isp
= to_isp_device(prev
);
296 const struct omap3isp_prev_dcor
*dcor
= prev_dcor
;
298 isp_reg_writel(isp
, dcor
->detect_correct
[0],
299 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR0
);
300 isp_reg_writel(isp
, dcor
->detect_correct
[1],
301 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR1
);
302 isp_reg_writel(isp
, dcor
->detect_correct
[2],
303 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR2
);
304 isp_reg_writel(isp
, dcor
->detect_correct
[3],
305 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR3
);
306 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
308 dcor
->couplet_mode_en
? ISPPRV_PCR_DCCOUP
: 0);
312 * preview_config_cfa - Configures the CFA Interpolation parameters.
313 * @prev_cfa: Structure containing the CFA interpolation table, CFA format
314 * in the image, vertical and horizontal gradient threshold.
317 preview_config_cfa(struct isp_prev_device
*prev
, const void *prev_cfa
)
319 struct isp_device
*isp
= to_isp_device(prev
);
320 const struct omap3isp_prev_cfa
*cfa
= prev_cfa
;
323 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
324 ISPPRV_PCR_CFAFMT_MASK
,
325 cfa
->format
<< ISPPRV_PCR_CFAFMT_SHIFT
);
328 (cfa
->gradthrs_vert
<< ISPPRV_CFA_GRADTH_VER_SHIFT
) |
329 (cfa
->gradthrs_horz
<< ISPPRV_CFA_GRADTH_HOR_SHIFT
),
330 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CFA
);
332 isp_reg_writel(isp
, ISPPRV_CFA_TABLE_ADDR
,
333 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
335 for (i
= 0; i
< OMAP3ISP_PREV_CFA_TBL_SIZE
; i
++) {
336 isp_reg_writel(isp
, cfa
->table
[i
],
337 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_DATA
);
342 * preview_config_gammacorrn - Configures the Gamma Correction table values
343 * @gtable: Structure containing the table for red, blue, green gamma table.
346 preview_config_gammacorrn(struct isp_prev_device
*prev
, const void *gtable
)
348 struct isp_device
*isp
= to_isp_device(prev
);
349 const struct omap3isp_prev_gtables
*gt
= gtable
;
352 isp_reg_writel(isp
, ISPPRV_REDGAMMA_TABLE_ADDR
,
353 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
354 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
355 isp_reg_writel(isp
, gt
->red
[i
], OMAP3_ISP_IOMEM_PREV
,
356 ISPPRV_SET_TBL_DATA
);
358 isp_reg_writel(isp
, ISPPRV_GREENGAMMA_TABLE_ADDR
,
359 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
360 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
361 isp_reg_writel(isp
, gt
->green
[i
], OMAP3_ISP_IOMEM_PREV
,
362 ISPPRV_SET_TBL_DATA
);
364 isp_reg_writel(isp
, ISPPRV_BLUEGAMMA_TABLE_ADDR
,
365 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
366 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
367 isp_reg_writel(isp
, gt
->blue
[i
], OMAP3_ISP_IOMEM_PREV
,
368 ISPPRV_SET_TBL_DATA
);
372 * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
373 * @ytable: Structure containing the table for Luminance Enhancement table.
376 preview_config_luma_enhancement(struct isp_prev_device
*prev
,
379 struct isp_device
*isp
= to_isp_device(prev
);
380 const struct omap3isp_prev_luma
*yt
= ytable
;
383 isp_reg_writel(isp
, ISPPRV_YENH_TABLE_ADDR
,
384 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
385 for (i
= 0; i
< OMAP3ISP_PREV_YENH_TBL_SIZE
; i
++) {
386 isp_reg_writel(isp
, yt
->table
[i
],
387 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_DATA
);
392 * preview_config_chroma_suppression - Configures the Chroma Suppression.
393 * @csup: Structure containing the threshold value for suppression
394 * and the hypass filter enable flag.
397 preview_config_chroma_suppression(struct isp_prev_device
*prev
,
400 struct isp_device
*isp
= to_isp_device(prev
);
401 const struct omap3isp_prev_csup
*cs
= csup
;
404 cs
->gain
| (cs
->thres
<< ISPPRV_CSUP_THRES_SHIFT
) |
405 (cs
->hypf_en
<< ISPPRV_CSUP_HPYF_SHIFT
),
406 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSUP
);
410 * preview_enable_noisefilter - Enables/Disables the Noise Filter.
411 * @enable: 1 - Enables the Noise Filter.
414 preview_enable_noisefilter(struct isp_prev_device
*prev
, u8 enable
)
416 struct isp_device
*isp
= to_isp_device(prev
);
419 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
422 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
427 * preview_enable_dcor - Enables/Disables the defect correction.
428 * @enable: 1 - Enables the defect correction.
431 preview_enable_dcor(struct isp_prev_device
*prev
, u8 enable
)
433 struct isp_device
*isp
= to_isp_device(prev
);
436 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
439 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
444 * preview_enable_cfa - Enable/Disable the CFA Interpolation.
445 * @enable: 1 - Enables the CFA.
448 preview_enable_cfa(struct isp_prev_device
*prev
, u8 enable
)
450 struct isp_device
*isp
= to_isp_device(prev
);
453 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
456 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
461 * preview_enable_gammabypass - Enables/Disables the GammaByPass
462 * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
463 * 0 - Goes through Gamma Correction. input and output is 10bit.
466 preview_enable_gammabypass(struct isp_prev_device
*prev
, u8 enable
)
468 struct isp_device
*isp
= to_isp_device(prev
);
471 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
472 ISPPRV_PCR_GAMMA_BYPASS
);
474 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
475 ISPPRV_PCR_GAMMA_BYPASS
);
479 * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
480 * @enable: 1 - Enable the Luminance Enhancement.
483 preview_enable_luma_enhancement(struct isp_prev_device
*prev
, u8 enable
)
485 struct isp_device
*isp
= to_isp_device(prev
);
488 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
491 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
496 * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
497 * @enable: 1 - Enable the Chrominance Suppression.
500 preview_enable_chroma_suppression(struct isp_prev_device
*prev
, u8 enable
)
502 struct isp_device
*isp
= to_isp_device(prev
);
505 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
508 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
513 * preview_config_whitebalance - Configures the White Balance parameters.
514 * @prev_wbal: Structure containing the digital gain and white balance
517 * Coefficient matrix always with default values.
520 preview_config_whitebalance(struct isp_prev_device
*prev
, const void *prev_wbal
)
522 struct isp_device
*isp
= to_isp_device(prev
);
523 const struct omap3isp_prev_wbal
*wbal
= prev_wbal
;
526 isp_reg_writel(isp
, wbal
->dgain
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WB_DGAIN
);
528 val
= wbal
->coef0
<< ISPPRV_WBGAIN_COEF0_SHIFT
;
529 val
|= wbal
->coef1
<< ISPPRV_WBGAIN_COEF1_SHIFT
;
530 val
|= wbal
->coef2
<< ISPPRV_WBGAIN_COEF2_SHIFT
;
531 val
|= wbal
->coef3
<< ISPPRV_WBGAIN_COEF3_SHIFT
;
532 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WBGAIN
);
535 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N0_0_SHIFT
|
536 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N0_1_SHIFT
|
537 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N0_2_SHIFT
|
538 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N0_3_SHIFT
|
539 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N1_0_SHIFT
|
540 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N1_1_SHIFT
|
541 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N1_2_SHIFT
|
542 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N1_3_SHIFT
|
543 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N2_0_SHIFT
|
544 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N2_1_SHIFT
|
545 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N2_2_SHIFT
|
546 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N2_3_SHIFT
|
547 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N3_0_SHIFT
|
548 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N3_1_SHIFT
|
549 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N3_2_SHIFT
|
550 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N3_3_SHIFT
,
551 OMAP3_ISP_IOMEM_PREV
, ISPPRV_WBSEL
);
555 * preview_config_blkadj - Configures the Black Adjustment parameters.
556 * @prev_blkadj: Structure containing the black adjustment towards red, green,
560 preview_config_blkadj(struct isp_prev_device
*prev
, const void *prev_blkadj
)
562 struct isp_device
*isp
= to_isp_device(prev
);
563 const struct omap3isp_prev_blkadj
*blkadj
= prev_blkadj
;
565 isp_reg_writel(isp
, (blkadj
->blue
<< ISPPRV_BLKADJOFF_B_SHIFT
) |
566 (blkadj
->green
<< ISPPRV_BLKADJOFF_G_SHIFT
) |
567 (blkadj
->red
<< ISPPRV_BLKADJOFF_R_SHIFT
),
568 OMAP3_ISP_IOMEM_PREV
, ISPPRV_BLKADJOFF
);
572 * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
573 * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
577 preview_config_rgb_blending(struct isp_prev_device
*prev
, const void *rgb2rgb
)
579 struct isp_device
*isp
= to_isp_device(prev
);
580 const struct omap3isp_prev_rgbtorgb
*rgbrgb
= rgb2rgb
;
583 val
= (rgbrgb
->matrix
[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT
;
584 val
|= (rgbrgb
->matrix
[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT
;
585 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT1
);
587 val
= (rgbrgb
->matrix
[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT
;
588 val
|= (rgbrgb
->matrix
[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT
;
589 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT2
);
591 val
= (rgbrgb
->matrix
[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT
;
592 val
|= (rgbrgb
->matrix
[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT
;
593 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT3
);
595 val
= (rgbrgb
->matrix
[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT
;
596 val
|= (rgbrgb
->matrix
[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT
;
597 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT4
);
599 val
= (rgbrgb
->matrix
[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT
;
600 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT5
);
602 val
= (rgbrgb
->offset
[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT
;
603 val
|= (rgbrgb
->offset
[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT
;
604 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_OFF1
);
606 val
= (rgbrgb
->offset
[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT
;
607 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_OFF2
);
611 * Configures the RGB-YCbYCr conversion matrix
612 * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
616 preview_config_rgb_to_ycbcr(struct isp_prev_device
*prev
, const void *prev_csc
)
618 struct isp_device
*isp
= to_isp_device(prev
);
619 const struct omap3isp_prev_csc
*csc
= prev_csc
;
622 val
= (csc
->matrix
[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT
;
623 val
|= (csc
->matrix
[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT
;
624 val
|= (csc
->matrix
[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT
;
625 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC0
);
627 val
= (csc
->matrix
[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT
;
628 val
|= (csc
->matrix
[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT
;
629 val
|= (csc
->matrix
[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT
;
630 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC1
);
632 val
= (csc
->matrix
[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT
;
633 val
|= (csc
->matrix
[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT
;
634 val
|= (csc
->matrix
[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT
;
635 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC2
);
637 val
= (csc
->offset
[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT
;
638 val
|= (csc
->offset
[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT
;
639 val
|= (csc
->offset
[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT
;
640 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC_OFFSET
);
644 * preview_update_contrast - Updates the contrast.
645 * @contrast: Pointer to hold the current programmed contrast value.
647 * Value should be programmed before enabling the module.
650 preview_update_contrast(struct isp_prev_device
*prev
, u8 contrast
)
652 struct prev_params
*params
= &prev
->params
;
654 if (params
->contrast
!= (contrast
* ISPPRV_CONTRAST_UNITS
)) {
655 params
->contrast
= contrast
* ISPPRV_CONTRAST_UNITS
;
656 prev
->update
|= PREV_CONTRAST
;
661 * preview_config_contrast - Configures the Contrast.
662 * @params: Contrast value (u8 pointer, U8Q0 format).
664 * Value should be programmed before enabling the module.
667 preview_config_contrast(struct isp_prev_device
*prev
, const void *params
)
669 struct isp_device
*isp
= to_isp_device(prev
);
671 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CNT_BRT
,
672 0xff << ISPPRV_CNT_BRT_CNT_SHIFT
,
673 *(u8
*)params
<< ISPPRV_CNT_BRT_CNT_SHIFT
);
677 * preview_update_brightness - Updates the brightness in preview module.
678 * @brightness: Pointer to hold the current programmed brightness value.
682 preview_update_brightness(struct isp_prev_device
*prev
, u8 brightness
)
684 struct prev_params
*params
= &prev
->params
;
686 if (params
->brightness
!= (brightness
* ISPPRV_BRIGHT_UNITS
)) {
687 params
->brightness
= brightness
* ISPPRV_BRIGHT_UNITS
;
688 prev
->update
|= PREV_BRIGHTNESS
;
693 * preview_config_brightness - Configures the brightness.
694 * @params: Brightness value (u8 pointer, U8Q0 format).
697 preview_config_brightness(struct isp_prev_device
*prev
, const void *params
)
699 struct isp_device
*isp
= to_isp_device(prev
);
701 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CNT_BRT
,
702 0xff << ISPPRV_CNT_BRT_BRT_SHIFT
,
703 *(u8
*)params
<< ISPPRV_CNT_BRT_BRT_SHIFT
);
707 * preview_config_yc_range - Configures the max and min Y and C values.
708 * @yclimit: Structure containing the range of Y and C values.
711 preview_config_yc_range(struct isp_prev_device
*prev
, const void *yclimit
)
713 struct isp_device
*isp
= to_isp_device(prev
);
714 const struct omap3isp_prev_yclimit
*yc
= yclimit
;
717 yc
->maxC
<< ISPPRV_SETUP_YC_MAXC_SHIFT
|
718 yc
->maxY
<< ISPPRV_SETUP_YC_MAXY_SHIFT
|
719 yc
->minC
<< ISPPRV_SETUP_YC_MINC_SHIFT
|
720 yc
->minY
<< ISPPRV_SETUP_YC_MINY_SHIFT
,
721 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SETUP_YC
);
724 /* preview parameters update structure */
725 struct preview_update
{
728 void (*config
)(struct isp_prev_device
*, const void *);
729 void (*enable
)(struct isp_prev_device
*, u8
);
732 static struct preview_update update_attrs
[] = {
733 {OMAP3ISP_PREV_LUMAENH
, PREV_LUMA_ENHANCE
,
734 preview_config_luma_enhancement
,
735 preview_enable_luma_enhancement
},
736 {OMAP3ISP_PREV_INVALAW
, PREV_INVERSE_ALAW
,
738 preview_enable_invalaw
},
739 {OMAP3ISP_PREV_HRZ_MED
, PREV_HORZ_MEDIAN_FILTER
,
741 preview_enable_hmed
},
742 {OMAP3ISP_PREV_CFA
, PREV_CFA
,
745 {OMAP3ISP_PREV_CHROMA_SUPP
, PREV_CHROMA_SUPPRESS
,
746 preview_config_chroma_suppression
,
747 preview_enable_chroma_suppression
},
748 {OMAP3ISP_PREV_WB
, PREV_WB
,
749 preview_config_whitebalance
,
751 {OMAP3ISP_PREV_BLKADJ
, PREV_BLKADJ
,
752 preview_config_blkadj
,
754 {OMAP3ISP_PREV_RGB2RGB
, PREV_RGB2RGB
,
755 preview_config_rgb_blending
,
757 {OMAP3ISP_PREV_COLOR_CONV
, PREV_COLOR_CONV
,
758 preview_config_rgb_to_ycbcr
,
760 {OMAP3ISP_PREV_YC_LIMIT
, PREV_YCLIMITS
,
761 preview_config_yc_range
,
763 {OMAP3ISP_PREV_DEFECT_COR
, PREV_DEFECT_COR
,
765 preview_enable_dcor
},
766 {OMAP3ISP_PREV_GAMMABYPASS
, PREV_GAMMA_BYPASS
,
768 preview_enable_gammabypass
},
769 {OMAP3ISP_PREV_DRK_FRM_CAPTURE
, PREV_DARK_FRAME_CAPTURE
,
771 preview_enable_drkframe_capture
},
772 {OMAP3ISP_PREV_DRK_FRM_SUBTRACT
, PREV_DARK_FRAME_SUBTRACT
,
774 preview_enable_drkframe
},
775 {OMAP3ISP_PREV_LENS_SHADING
, PREV_LENS_SHADING
,
776 preview_config_drkf_shadcomp
,
777 preview_enable_drkframe
},
778 {OMAP3ISP_PREV_NF
, PREV_NOISE_FILTER
,
779 preview_config_noisefilter
,
780 preview_enable_noisefilter
},
781 {OMAP3ISP_PREV_GAMMA
, PREV_GAMMA
,
782 preview_config_gammacorrn
,
785 preview_config_contrast
,
787 {-1, PREV_BRIGHTNESS
,
788 preview_config_brightness
,
793 * __preview_get_ptrs - helper function which return pointers to members
794 * of params and config structures.
795 * @params - pointer to preview_params structure.
796 * @param - return pointer to appropriate structure field.
797 * @configs - pointer to update config structure.
798 * @config - return pointer to appropriate structure field.
799 * @bit - for which feature to return pointers.
800 * Return size of corresponding prev_params member
803 __preview_get_ptrs(struct prev_params
*params
, void **param
,
804 struct omap3isp_prev_update_config
*configs
,
805 void __user
**config
, u32 bit
)
807 #define CHKARG(cfgs, cfg, field) \
809 *(cfg) = (cfgs)->field; \
813 case PREV_HORZ_MEDIAN_FILTER
:
814 *param
= ¶ms
->hmed
;
815 CHKARG(configs
, config
, hmed
)
816 return sizeof(params
->hmed
);
817 case PREV_NOISE_FILTER
:
818 *param
= ¶ms
->nf
;
819 CHKARG(configs
, config
, nf
)
820 return sizeof(params
->nf
);
823 *param
= ¶ms
->cfa
;
824 CHKARG(configs
, config
, cfa
)
825 return sizeof(params
->cfa
);
826 case PREV_LUMA_ENHANCE
:
827 *param
= ¶ms
->luma
;
828 CHKARG(configs
, config
, luma
)
829 return sizeof(params
->luma
);
830 case PREV_CHROMA_SUPPRESS
:
831 *param
= ¶ms
->csup
;
832 CHKARG(configs
, config
, csup
)
833 return sizeof(params
->csup
);
834 case PREV_DEFECT_COR
:
835 *param
= ¶ms
->dcor
;
836 CHKARG(configs
, config
, dcor
)
837 return sizeof(params
->dcor
);
839 *param
= ¶ms
->blk_adj
;
840 CHKARG(configs
, config
, blkadj
)
841 return sizeof(params
->blk_adj
);
843 *param
= ¶ms
->yclimit
;
844 CHKARG(configs
, config
, yclimit
)
845 return sizeof(params
->yclimit
);
847 *param
= ¶ms
->rgb2rgb
;
848 CHKARG(configs
, config
, rgb2rgb
)
849 return sizeof(params
->rgb2rgb
);
850 case PREV_COLOR_CONV
:
851 *param
= ¶ms
->rgb2ycbcr
;
852 CHKARG(configs
, config
, csc
)
853 return sizeof(params
->rgb2ycbcr
);
855 *param
= ¶ms
->wbal
;
856 CHKARG(configs
, config
, wbal
)
857 return sizeof(params
->wbal
);
859 *param
= ¶ms
->gamma
;
860 CHKARG(configs
, config
, gamma
)
861 return sizeof(params
->gamma
);
863 *param
= ¶ms
->contrast
;
865 case PREV_BRIGHTNESS
:
866 *param
= ¶ms
->brightness
;
877 * preview_config - Copy and update local structure with userspace preview
879 * @prev: ISP preview engine
880 * @cfg: Configuration
882 * Return zero if success or -EFAULT if the configuration can't be copied from
885 static int preview_config(struct isp_prev_device
*prev
,
886 struct omap3isp_prev_update_config
*cfg
)
888 struct prev_params
*params
;
889 struct preview_update
*attr
;
890 int i
, bit
, rval
= 0;
892 params
= &prev
->params
;
894 if (prev
->state
!= ISP_PIPELINE_STREAM_STOPPED
) {
897 spin_lock_irqsave(&prev
->lock
, flags
);
898 prev
->shadow_update
= 1;
899 spin_unlock_irqrestore(&prev
->lock
, flags
);
902 for (i
= 0; i
< ARRAY_SIZE(update_attrs
); i
++) {
903 attr
= &update_attrs
[i
];
906 if (!(cfg
->update
& attr
->cfg_bit
))
909 bit
= cfg
->flag
& attr
->cfg_bit
;
911 void *to
= NULL
, __user
*from
= NULL
;
912 unsigned long sz
= 0;
914 sz
= __preview_get_ptrs(params
, &to
, cfg
, &from
,
916 if (to
&& from
&& sz
) {
917 if (copy_from_user(to
, from
, sz
)) {
922 params
->features
|= attr
->feature_bit
;
924 params
->features
&= ~attr
->feature_bit
;
927 prev
->update
|= attr
->feature_bit
;
930 prev
->shadow_update
= 0;
935 * preview_setup_hw - Setup preview registers and/or internal memory
936 * @prev: pointer to preview private structure
937 * Note: can be called from interrupt context
940 static void preview_setup_hw(struct isp_prev_device
*prev
)
942 struct prev_params
*params
= &prev
->params
;
943 struct preview_update
*attr
;
947 for (i
= 0; i
< ARRAY_SIZE(update_attrs
); i
++) {
948 attr
= &update_attrs
[i
];
950 if (!(prev
->update
& attr
->feature_bit
))
952 bit
= params
->features
& attr
->feature_bit
;
955 __preview_get_ptrs(params
, ¶m_ptr
, NULL
,
957 attr
->config(prev
, param_ptr
);
960 attr
->enable(prev
, 1);
963 attr
->enable(prev
, 0);
965 prev
->update
&= ~attr
->feature_bit
;
970 * preview_config_ycpos - Configure byte layout of YUV image.
971 * @mode: Indicates the required byte layout.
974 preview_config_ycpos(struct isp_prev_device
*prev
,
975 enum v4l2_mbus_pixelcode pixelcode
)
977 struct isp_device
*isp
= to_isp_device(prev
);
978 enum preview_ycpos_mode mode
;
981 case V4L2_MBUS_FMT_YUYV8_1X16
:
984 case V4L2_MBUS_FMT_UYVY8_1X16
:
991 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
992 ISPPRV_PCR_YCPOS_CrYCbY
,
993 mode
<< ISPPRV_PCR_YCPOS_SHIFT
);
997 * preview_config_averager - Enable / disable / configure averager
998 * @average: Average value to be configured.
1000 static void preview_config_averager(struct isp_prev_device
*prev
, u8 average
)
1002 struct isp_device
*isp
= to_isp_device(prev
);
1005 if (prev
->params
.cfa
.format
== OMAP3ISP_CFAFMT_BAYER
)
1006 reg
= ISPPRV_AVE_EVENDIST_2
<< ISPPRV_AVE_EVENDIST_SHIFT
|
1007 ISPPRV_AVE_ODDDIST_2
<< ISPPRV_AVE_ODDDIST_SHIFT
|
1009 else if (prev
->params
.cfa
.format
== OMAP3ISP_CFAFMT_RGBFOVEON
)
1010 reg
= ISPPRV_AVE_EVENDIST_3
<< ISPPRV_AVE_EVENDIST_SHIFT
|
1011 ISPPRV_AVE_ODDDIST_3
<< ISPPRV_AVE_ODDDIST_SHIFT
|
1013 isp_reg_writel(isp
, reg
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_AVE
);
1017 * preview_config_input_size - Configure the input frame size
1019 * The preview engine crops several rows and columns internally depending on
1020 * which processing blocks are enabled. The driver assumes all those blocks are
1021 * enabled when reporting source pad formats to userspace. If this assumption is
1022 * not true, rows and columns must be manually cropped at the preview engine
1023 * input to avoid overflows at the end of lines and frames.
1025 * See the explanation at the PREV_MARGIN_* definitions for more details.
1027 static void preview_config_input_size(struct isp_prev_device
*prev
)
1029 struct isp_device
*isp
= to_isp_device(prev
);
1030 struct prev_params
*params
= &prev
->params
;
1031 unsigned int sph
= prev
->crop
.left
;
1032 unsigned int eph
= prev
->crop
.left
+ prev
->crop
.width
- 1;
1033 unsigned int slv
= prev
->crop
.top
;
1034 unsigned int elv
= prev
->crop
.top
+ prev
->crop
.height
- 1;
1036 if (params
->features
& PREV_CFA
) {
1042 if (params
->features
& (PREV_DEFECT_COR
| PREV_NOISE_FILTER
)) {
1048 if (params
->features
& PREV_HORZ_MEDIAN_FILTER
) {
1052 if (params
->features
& (PREV_CHROMA_SUPPRESS
| PREV_LUMA_ENHANCE
))
1055 isp_reg_writel(isp
, (sph
<< ISPPRV_HORZ_INFO_SPH_SHIFT
) | eph
,
1056 OMAP3_ISP_IOMEM_PREV
, ISPPRV_HORZ_INFO
);
1057 isp_reg_writel(isp
, (slv
<< ISPPRV_VERT_INFO_SLV_SHIFT
) | elv
,
1058 OMAP3_ISP_IOMEM_PREV
, ISPPRV_VERT_INFO
);
1062 * preview_config_inlineoffset - Configures the Read address line offset.
1063 * @prev: Preview module
1064 * @offset: Line offset
1066 * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
1067 * However, a hardware bug requires the memory start address to be aligned on a
1068 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
1072 preview_config_inlineoffset(struct isp_prev_device
*prev
, u32 offset
)
1074 struct isp_device
*isp
= to_isp_device(prev
);
1076 isp_reg_writel(isp
, offset
& 0xffff, OMAP3_ISP_IOMEM_PREV
,
1077 ISPPRV_RADR_OFFSET
);
1081 * preview_set_inaddr - Sets memory address of input frame.
1082 * @addr: 32bit memory address aligned on 32byte boundary.
1084 * Configures the memory address from which the input frame is to be read.
1086 static void preview_set_inaddr(struct isp_prev_device
*prev
, u32 addr
)
1088 struct isp_device
*isp
= to_isp_device(prev
);
1090 isp_reg_writel(isp
, addr
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RSDR_ADDR
);
1094 * preview_config_outlineoffset - Configures the Write address line offset.
1095 * @offset: Line Offset for the preview output.
1097 * The offset must be a multiple of 32 bytes.
1099 static void preview_config_outlineoffset(struct isp_prev_device
*prev
,
1102 struct isp_device
*isp
= to_isp_device(prev
);
1104 isp_reg_writel(isp
, offset
& 0xffff, OMAP3_ISP_IOMEM_PREV
,
1105 ISPPRV_WADD_OFFSET
);
1109 * preview_set_outaddr - Sets the memory address to store output frame
1110 * @addr: 32bit memory address aligned on 32byte boundary.
1112 * Configures the memory address to which the output frame is written.
1114 static void preview_set_outaddr(struct isp_prev_device
*prev
, u32 addr
)
1116 struct isp_device
*isp
= to_isp_device(prev
);
1118 isp_reg_writel(isp
, addr
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WSDR_ADDR
);
1121 static void preview_adjust_bandwidth(struct isp_prev_device
*prev
)
1123 struct isp_pipeline
*pipe
= to_isp_pipeline(&prev
->subdev
.entity
);
1124 struct isp_device
*isp
= to_isp_device(prev
);
1125 const struct v4l2_mbus_framefmt
*ifmt
= &prev
->formats
[PREV_PAD_SINK
];
1126 unsigned long l3_ick
= pipe
->l3_ick
;
1127 struct v4l2_fract
*timeperframe
;
1128 unsigned int cycles_per_frame
;
1129 unsigned int requests_per_frame
;
1130 unsigned int cycles_per_request
;
1131 unsigned int minimum
;
1132 unsigned int maximum
;
1135 if (prev
->input
!= PREVIEW_INPUT_MEMORY
) {
1136 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_SBL
, ISPSBL_SDR_REQ_EXP
,
1137 ISPSBL_SDR_REQ_PRV_EXP_MASK
);
1141 /* Compute the minimum number of cycles per request, based on the
1142 * pipeline maximum data rate. This is an absolute lower bound if we
1143 * don't want SBL overflows, so round the value up.
1145 cycles_per_request
= div_u64((u64
)l3_ick
/ 2 * 256 + pipe
->max_rate
- 1,
1147 minimum
= DIV_ROUND_UP(cycles_per_request
, 32);
1149 /* Compute the maximum number of cycles per request, based on the
1150 * requested frame rate. This is a soft upper bound to achieve a frame
1151 * rate equal or higher than the requested value, so round the value
1154 timeperframe
= &pipe
->max_timeperframe
;
1156 requests_per_frame
= DIV_ROUND_UP(ifmt
->width
* 2, 256) * ifmt
->height
;
1157 cycles_per_frame
= div_u64((u64
)l3_ick
* timeperframe
->numerator
,
1158 timeperframe
->denominator
);
1159 cycles_per_request
= cycles_per_frame
/ requests_per_frame
;
1161 maximum
= cycles_per_request
/ 32;
1163 value
= max(minimum
, maximum
);
1165 dev_dbg(isp
->dev
, "%s: cycles per request = %u\n", __func__
, value
);
1166 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_SBL
, ISPSBL_SDR_REQ_EXP
,
1167 ISPSBL_SDR_REQ_PRV_EXP_MASK
,
1168 value
<< ISPSBL_SDR_REQ_PRV_EXP_SHIFT
);
1172 * omap3isp_preview_busy - Gets busy state of preview module.
1174 int omap3isp_preview_busy(struct isp_prev_device
*prev
)
1176 struct isp_device
*isp
= to_isp_device(prev
);
1178 return isp_reg_readl(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
)
1183 * omap3isp_preview_restore_context - Restores the values of preview registers
1185 void omap3isp_preview_restore_context(struct isp_device
*isp
)
1187 isp
->isp_prev
.update
= PREV_FEATURES_END
- 1;
1188 preview_setup_hw(&isp
->isp_prev
);
1192 * preview_print_status - Dump preview module registers to the kernel log
1194 #define PREV_PRINT_REGISTER(isp, name)\
1195 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1196 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1198 static void preview_print_status(struct isp_prev_device
*prev
)
1200 struct isp_device
*isp
= to_isp_device(prev
);
1202 dev_dbg(isp
->dev
, "-------------Preview Register dump----------\n");
1204 PREV_PRINT_REGISTER(isp
, PCR
);
1205 PREV_PRINT_REGISTER(isp
, HORZ_INFO
);
1206 PREV_PRINT_REGISTER(isp
, VERT_INFO
);
1207 PREV_PRINT_REGISTER(isp
, RSDR_ADDR
);
1208 PREV_PRINT_REGISTER(isp
, RADR_OFFSET
);
1209 PREV_PRINT_REGISTER(isp
, DSDR_ADDR
);
1210 PREV_PRINT_REGISTER(isp
, DRKF_OFFSET
);
1211 PREV_PRINT_REGISTER(isp
, WSDR_ADDR
);
1212 PREV_PRINT_REGISTER(isp
, WADD_OFFSET
);
1213 PREV_PRINT_REGISTER(isp
, AVE
);
1214 PREV_PRINT_REGISTER(isp
, HMED
);
1215 PREV_PRINT_REGISTER(isp
, NF
);
1216 PREV_PRINT_REGISTER(isp
, WB_DGAIN
);
1217 PREV_PRINT_REGISTER(isp
, WBGAIN
);
1218 PREV_PRINT_REGISTER(isp
, WBSEL
);
1219 PREV_PRINT_REGISTER(isp
, CFA
);
1220 PREV_PRINT_REGISTER(isp
, BLKADJOFF
);
1221 PREV_PRINT_REGISTER(isp
, RGB_MAT1
);
1222 PREV_PRINT_REGISTER(isp
, RGB_MAT2
);
1223 PREV_PRINT_REGISTER(isp
, RGB_MAT3
);
1224 PREV_PRINT_REGISTER(isp
, RGB_MAT4
);
1225 PREV_PRINT_REGISTER(isp
, RGB_MAT5
);
1226 PREV_PRINT_REGISTER(isp
, RGB_OFF1
);
1227 PREV_PRINT_REGISTER(isp
, RGB_OFF2
);
1228 PREV_PRINT_REGISTER(isp
, CSC0
);
1229 PREV_PRINT_REGISTER(isp
, CSC1
);
1230 PREV_PRINT_REGISTER(isp
, CSC2
);
1231 PREV_PRINT_REGISTER(isp
, CSC_OFFSET
);
1232 PREV_PRINT_REGISTER(isp
, CNT_BRT
);
1233 PREV_PRINT_REGISTER(isp
, CSUP
);
1234 PREV_PRINT_REGISTER(isp
, SETUP_YC
);
1235 PREV_PRINT_REGISTER(isp
, SET_TBL_ADDR
);
1236 PREV_PRINT_REGISTER(isp
, CDC_THR0
);
1237 PREV_PRINT_REGISTER(isp
, CDC_THR1
);
1238 PREV_PRINT_REGISTER(isp
, CDC_THR2
);
1239 PREV_PRINT_REGISTER(isp
, CDC_THR3
);
1241 dev_dbg(isp
->dev
, "--------------------------------------------\n");
1245 * preview_init_params - init image processing parameters.
1246 * @prev: pointer to previewer private structure
1249 static void preview_init_params(struct isp_prev_device
*prev
)
1251 struct prev_params
*params
= &prev
->params
;
1255 params
->contrast
= ISPPRV_CONTRAST_DEF
* ISPPRV_CONTRAST_UNITS
;
1256 params
->brightness
= ISPPRV_BRIGHT_DEF
* ISPPRV_BRIGHT_UNITS
;
1257 params
->cfa
.format
= OMAP3ISP_CFAFMT_BAYER
;
1258 memcpy(params
->cfa
.table
, cfa_coef_table
,
1259 sizeof(params
->cfa
.table
));
1260 params
->cfa
.gradthrs_horz
= FLR_CFA_GRADTHRS_HORZ
;
1261 params
->cfa
.gradthrs_vert
= FLR_CFA_GRADTHRS_VERT
;
1262 params
->csup
.gain
= FLR_CSUP_GAIN
;
1263 params
->csup
.thres
= FLR_CSUP_THRES
;
1264 params
->csup
.hypf_en
= 0;
1265 memcpy(params
->luma
.table
, luma_enhance_table
,
1266 sizeof(params
->luma
.table
));
1267 params
->nf
.spread
= FLR_NF_STRGTH
;
1268 memcpy(params
->nf
.table
, noise_filter_table
, sizeof(params
->nf
.table
));
1269 params
->dcor
.couplet_mode_en
= 1;
1270 for (i
= 0; i
< OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS
; i
++)
1271 params
->dcor
.detect_correct
[i
] = DEF_DETECT_CORRECT_VAL
;
1272 memcpy(params
->gamma
.blue
, gamma_table
, sizeof(params
->gamma
.blue
));
1273 memcpy(params
->gamma
.green
, gamma_table
, sizeof(params
->gamma
.green
));
1274 memcpy(params
->gamma
.red
, gamma_table
, sizeof(params
->gamma
.red
));
1275 params
->wbal
.dgain
= FLR_WBAL_DGAIN
;
1276 params
->wbal
.coef0
= FLR_WBAL_COEF
;
1277 params
->wbal
.coef1
= FLR_WBAL_COEF
;
1278 params
->wbal
.coef2
= FLR_WBAL_COEF
;
1279 params
->wbal
.coef3
= FLR_WBAL_COEF
;
1280 params
->blk_adj
.red
= FLR_BLKADJ_RED
;
1281 params
->blk_adj
.green
= FLR_BLKADJ_GREEN
;
1282 params
->blk_adj
.blue
= FLR_BLKADJ_BLUE
;
1283 params
->rgb2rgb
= flr_rgb2rgb
;
1284 params
->rgb2ycbcr
= flr_prev_csc
;
1285 params
->yclimit
.minC
= ISPPRV_YC_MIN
;
1286 params
->yclimit
.maxC
= ISPPRV_YC_MAX
;
1287 params
->yclimit
.minY
= ISPPRV_YC_MIN
;
1288 params
->yclimit
.maxY
= ISPPRV_YC_MAX
;
1290 params
->features
= PREV_CFA
| PREV_DEFECT_COR
| PREV_NOISE_FILTER
1291 | PREV_GAMMA
| PREV_BLKADJ
| PREV_YCLIMITS
1292 | PREV_RGB2RGB
| PREV_COLOR_CONV
| PREV_WB
1293 | PREV_BRIGHTNESS
| PREV_CONTRAST
;
1295 prev
->update
= PREV_FEATURES_END
- 1;
1299 * preview_max_out_width - Handle previewer hardware ouput limitations
1300 * @isp_revision : ISP revision
1301 * returns maximum width output for current isp revision
1303 static unsigned int preview_max_out_width(struct isp_prev_device
*prev
)
1305 struct isp_device
*isp
= to_isp_device(prev
);
1307 switch (isp
->revision
) {
1308 case ISP_REVISION_1_0
:
1309 return PREV_MAX_OUT_WIDTH_REV_1
;
1311 case ISP_REVISION_2_0
:
1313 return PREV_MAX_OUT_WIDTH_REV_2
;
1315 case ISP_REVISION_15_0
:
1316 return PREV_MAX_OUT_WIDTH_REV_15
;
1320 static void preview_configure(struct isp_prev_device
*prev
)
1322 struct isp_device
*isp
= to_isp_device(prev
);
1323 struct v4l2_mbus_framefmt
*format
;
1325 preview_setup_hw(prev
);
1327 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1328 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1329 ISPPRV_PCR_SDRPORT
);
1331 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1332 ISPPRV_PCR_SDRPORT
);
1334 if (prev
->output
& PREVIEW_OUTPUT_RESIZER
)
1335 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1336 ISPPRV_PCR_RSZPORT
);
1338 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1339 ISPPRV_PCR_RSZPORT
);
1342 format
= &prev
->formats
[PREV_PAD_SINK
];
1344 preview_adjust_bandwidth(prev
);
1346 preview_config_input_size(prev
);
1348 if (prev
->input
== PREVIEW_INPUT_CCDC
)
1349 preview_config_inlineoffset(prev
, 0);
1351 preview_config_inlineoffset(prev
,
1352 ALIGN(format
->width
, 0x20) * 2);
1354 /* PREV_PAD_SOURCE */
1355 format
= &prev
->formats
[PREV_PAD_SOURCE
];
1357 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1358 preview_config_outlineoffset(prev
,
1359 ALIGN(format
->width
, 0x10) * 2);
1361 preview_config_averager(prev
, 0);
1362 preview_config_ycpos(prev
, format
->code
);
1365 /* -----------------------------------------------------------------------------
1366 * Interrupt handling
1369 static void preview_enable_oneshot(struct isp_prev_device
*prev
)
1371 struct isp_device
*isp
= to_isp_device(prev
);
1373 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
1374 * bit is set. As the preview engine is used in single-shot mode, we
1375 * need to set PCR.SOURCE before enabling the preview engine.
1377 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
1378 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1381 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1382 ISPPRV_PCR_EN
| ISPPRV_PCR_ONESHOT
);
1385 void omap3isp_preview_isr_frame_sync(struct isp_prev_device
*prev
)
1388 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1389 * condition, the module was paused and now we have a buffer queued
1390 * on the output again. Restart the pipeline if running in continuous
1393 if (prev
->state
== ISP_PIPELINE_STREAM_CONTINUOUS
&&
1394 prev
->video_out
.dmaqueue_flags
& ISP_VIDEO_DMAQUEUE_QUEUED
) {
1395 preview_enable_oneshot(prev
);
1396 isp_video_dmaqueue_flags_clr(&prev
->video_out
);
1400 static void preview_isr_buffer(struct isp_prev_device
*prev
)
1402 struct isp_pipeline
*pipe
= to_isp_pipeline(&prev
->subdev
.entity
);
1403 struct isp_buffer
*buffer
;
1406 if (prev
->input
== PREVIEW_INPUT_MEMORY
) {
1407 buffer
= omap3isp_video_buffer_next(&prev
->video_in
);
1409 preview_set_inaddr(prev
, buffer
->isp_addr
);
1410 pipe
->state
|= ISP_PIPELINE_IDLE_INPUT
;
1413 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
) {
1414 buffer
= omap3isp_video_buffer_next(&prev
->video_out
);
1415 if (buffer
!= NULL
) {
1416 preview_set_outaddr(prev
, buffer
->isp_addr
);
1419 pipe
->state
|= ISP_PIPELINE_IDLE_OUTPUT
;
1422 switch (prev
->state
) {
1423 case ISP_PIPELINE_STREAM_SINGLESHOT
:
1424 if (isp_pipeline_ready(pipe
))
1425 omap3isp_pipeline_set_stream(pipe
,
1426 ISP_PIPELINE_STREAM_SINGLESHOT
);
1429 case ISP_PIPELINE_STREAM_CONTINUOUS
:
1430 /* If an underrun occurs, the video queue operation handler will
1431 * restart the preview engine. Otherwise restart it immediately.
1434 preview_enable_oneshot(prev
);
1437 case ISP_PIPELINE_STREAM_STOPPED
:
1444 * omap3isp_preview_isr - ISP preview engine interrupt handler
1446 * Manage the preview engine video buffers and configure shadowed registers.
1448 void omap3isp_preview_isr(struct isp_prev_device
*prev
)
1450 unsigned long flags
;
1452 if (omap3isp_module_sync_is_stopping(&prev
->wait
, &prev
->stopping
))
1455 spin_lock_irqsave(&prev
->lock
, flags
);
1456 if (prev
->shadow_update
)
1459 preview_setup_hw(prev
);
1460 preview_config_input_size(prev
);
1463 spin_unlock_irqrestore(&prev
->lock
, flags
);
1465 if (prev
->input
== PREVIEW_INPUT_MEMORY
||
1466 prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1467 preview_isr_buffer(prev
);
1468 else if (prev
->state
== ISP_PIPELINE_STREAM_CONTINUOUS
)
1469 preview_enable_oneshot(prev
);
1472 /* -----------------------------------------------------------------------------
1473 * ISP video operations
1476 static int preview_video_queue(struct isp_video
*video
,
1477 struct isp_buffer
*buffer
)
1479 struct isp_prev_device
*prev
= &video
->isp
->isp_prev
;
1481 if (video
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
)
1482 preview_set_inaddr(prev
, buffer
->isp_addr
);
1484 if (video
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1485 preview_set_outaddr(prev
, buffer
->isp_addr
);
1490 static const struct isp_video_operations preview_video_ops
= {
1491 .queue
= preview_video_queue
,
1494 /* -----------------------------------------------------------------------------
1495 * V4L2 subdev operations
1499 * preview_s_ctrl - Handle set control subdev method
1500 * @ctrl: pointer to v4l2 control structure
1502 static int preview_s_ctrl(struct v4l2_ctrl
*ctrl
)
1504 struct isp_prev_device
*prev
=
1505 container_of(ctrl
->handler
, struct isp_prev_device
, ctrls
);
1508 case V4L2_CID_BRIGHTNESS
:
1509 preview_update_brightness(prev
, ctrl
->val
);
1511 case V4L2_CID_CONTRAST
:
1512 preview_update_contrast(prev
, ctrl
->val
);
1519 static const struct v4l2_ctrl_ops preview_ctrl_ops
= {
1520 .s_ctrl
= preview_s_ctrl
,
1524 * preview_ioctl - Handle preview module private ioctl's
1525 * @prev: pointer to preview context structure
1526 * @cmd: configuration command
1527 * @arg: configuration argument
1528 * return -EINVAL or zero on success
1530 static long preview_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
1532 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1535 case VIDIOC_OMAP3ISP_PRV_CFG
:
1536 return preview_config(prev
, arg
);
1539 return -ENOIOCTLCMD
;
1544 * preview_set_stream - Enable/Disable streaming on preview subdev
1545 * @sd : pointer to v4l2 subdev structure
1546 * @enable: 1 == Enable, 0 == Disable
1547 * return -EINVAL or zero on success
1549 static int preview_set_stream(struct v4l2_subdev
*sd
, int enable
)
1551 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1552 struct isp_video
*video_out
= &prev
->video_out
;
1553 struct isp_device
*isp
= to_isp_device(prev
);
1554 struct device
*dev
= to_device(prev
);
1555 unsigned long flags
;
1557 if (prev
->state
== ISP_PIPELINE_STREAM_STOPPED
) {
1558 if (enable
== ISP_PIPELINE_STREAM_STOPPED
)
1561 omap3isp_subclk_enable(isp
, OMAP3_ISP_SUBCLK_PREVIEW
);
1562 preview_configure(prev
);
1563 atomic_set(&prev
->stopping
, 0);
1564 preview_print_status(prev
);
1568 case ISP_PIPELINE_STREAM_CONTINUOUS
:
1569 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1570 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1572 if (video_out
->dmaqueue_flags
& ISP_VIDEO_DMAQUEUE_QUEUED
||
1573 !(prev
->output
& PREVIEW_OUTPUT_MEMORY
))
1574 preview_enable_oneshot(prev
);
1576 isp_video_dmaqueue_flags_clr(video_out
);
1579 case ISP_PIPELINE_STREAM_SINGLESHOT
:
1580 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
1581 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_READ
);
1582 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1583 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1585 preview_enable_oneshot(prev
);
1588 case ISP_PIPELINE_STREAM_STOPPED
:
1589 if (omap3isp_module_sync_idle(&sd
->entity
, &prev
->wait
,
1591 dev_dbg(dev
, "%s: stop timeout.\n", sd
->name
);
1592 spin_lock_irqsave(&prev
->lock
, flags
);
1593 omap3isp_sbl_disable(isp
, OMAP3_ISP_SBL_PREVIEW_READ
);
1594 omap3isp_sbl_disable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1595 omap3isp_subclk_disable(isp
, OMAP3_ISP_SUBCLK_PREVIEW
);
1596 spin_unlock_irqrestore(&prev
->lock
, flags
);
1597 isp_video_dmaqueue_flags_clr(video_out
);
1601 prev
->state
= enable
;
1605 static struct v4l2_mbus_framefmt
*
1606 __preview_get_format(struct isp_prev_device
*prev
, struct v4l2_subdev_fh
*fh
,
1607 unsigned int pad
, enum v4l2_subdev_format_whence which
)
1609 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
1610 return v4l2_subdev_get_try_format(fh
, pad
);
1612 return &prev
->formats
[pad
];
1615 static struct v4l2_rect
*
1616 __preview_get_crop(struct isp_prev_device
*prev
, struct v4l2_subdev_fh
*fh
,
1617 enum v4l2_subdev_format_whence which
)
1619 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
1620 return v4l2_subdev_get_try_crop(fh
, PREV_PAD_SINK
);
1625 /* previewer format descriptions */
1626 static const unsigned int preview_input_fmts
[] = {
1627 V4L2_MBUS_FMT_SGRBG10_1X10
,
1628 V4L2_MBUS_FMT_SRGGB10_1X10
,
1629 V4L2_MBUS_FMT_SBGGR10_1X10
,
1630 V4L2_MBUS_FMT_SGBRG10_1X10
,
1633 static const unsigned int preview_output_fmts
[] = {
1634 V4L2_MBUS_FMT_UYVY8_1X16
,
1635 V4L2_MBUS_FMT_YUYV8_1X16
,
1639 * preview_try_format - Validate a format
1640 * @prev: ISP preview engine
1641 * @fh: V4L2 subdev file handle
1643 * @fmt: format to be validated
1644 * @which: try/active format selector
1646 * Validate and adjust the given format for the given pad based on the preview
1647 * engine limits and the format and crop rectangles on other pads.
1649 static void preview_try_format(struct isp_prev_device
*prev
,
1650 struct v4l2_subdev_fh
*fh
, unsigned int pad
,
1651 struct v4l2_mbus_framefmt
*fmt
,
1652 enum v4l2_subdev_format_whence which
)
1654 enum v4l2_mbus_pixelcode pixelcode
;
1655 struct v4l2_rect
*crop
;
1660 /* When reading data from the CCDC, the input size has already
1661 * been mangled by the CCDC output pad so it can be accepted
1664 * When reading data from memory, clamp the requested width and
1665 * height. The TRM doesn't specify a minimum input height, make
1666 * sure we got enough lines to enable the noise filter and color
1667 * filter array interpolation.
1669 if (prev
->input
== PREVIEW_INPUT_MEMORY
) {
1670 fmt
->width
= clamp_t(u32
, fmt
->width
, PREV_MIN_IN_WIDTH
,
1671 preview_max_out_width(prev
));
1672 fmt
->height
= clamp_t(u32
, fmt
->height
,
1674 PREV_MAX_IN_HEIGHT
);
1677 fmt
->colorspace
= V4L2_COLORSPACE_SRGB
;
1679 for (i
= 0; i
< ARRAY_SIZE(preview_input_fmts
); i
++) {
1680 if (fmt
->code
== preview_input_fmts
[i
])
1684 /* If not found, use SGRBG10 as default */
1685 if (i
>= ARRAY_SIZE(preview_input_fmts
))
1686 fmt
->code
= V4L2_MBUS_FMT_SGRBG10_1X10
;
1689 case PREV_PAD_SOURCE
:
1690 pixelcode
= fmt
->code
;
1691 *fmt
= *__preview_get_format(prev
, fh
, PREV_PAD_SINK
, which
);
1693 switch (pixelcode
) {
1694 case V4L2_MBUS_FMT_YUYV8_1X16
:
1695 case V4L2_MBUS_FMT_UYVY8_1X16
:
1696 fmt
->code
= pixelcode
;
1700 fmt
->code
= V4L2_MBUS_FMT_YUYV8_1X16
;
1704 /* The preview module output size is configurable through the
1705 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
1706 * is not supported yet, hardcode the output size to the crop
1709 crop
= __preview_get_crop(prev
, fh
, which
);
1710 fmt
->width
= crop
->width
;
1711 fmt
->height
= crop
->height
;
1713 fmt
->colorspace
= V4L2_COLORSPACE_JPEG
;
1717 fmt
->field
= V4L2_FIELD_NONE
;
1721 * preview_try_crop - Validate a crop rectangle
1722 * @prev: ISP preview engine
1723 * @sink: format on the sink pad
1724 * @crop: crop rectangle to be validated
1726 * The preview engine crops lines and columns for its internal operation,
1727 * depending on which filters are enabled. Enforce minimum crop margins to
1728 * handle that transparently for userspace.
1730 * See the explanation at the PREV_MARGIN_* definitions for more details.
1732 static void preview_try_crop(struct isp_prev_device
*prev
,
1733 const struct v4l2_mbus_framefmt
*sink
,
1734 struct v4l2_rect
*crop
)
1736 unsigned int left
= PREV_MARGIN_LEFT
;
1737 unsigned int right
= sink
->width
- PREV_MARGIN_RIGHT
;
1738 unsigned int top
= PREV_MARGIN_TOP
;
1739 unsigned int bottom
= sink
->height
- PREV_MARGIN_BOTTOM
;
1741 /* When processing data on-the-fly from the CCDC, at least 2 pixels must
1742 * be cropped from the left and right sides of the image. As we don't
1743 * know which filters will be enabled, increase the left and right
1746 if (prev
->input
== PREVIEW_INPUT_CCDC
) {
1751 /* Restrict left/top to even values to keep the Bayer pattern. */
1755 crop
->left
= clamp_t(u32
, crop
->left
, left
, right
- PREV_MIN_OUT_WIDTH
);
1756 crop
->top
= clamp_t(u32
, crop
->top
, top
, bottom
- PREV_MIN_OUT_HEIGHT
);
1757 crop
->width
= clamp_t(u32
, crop
->width
, PREV_MIN_OUT_WIDTH
,
1758 right
- crop
->left
);
1759 crop
->height
= clamp_t(u32
, crop
->height
, PREV_MIN_OUT_HEIGHT
,
1760 bottom
- crop
->top
);
1764 * preview_enum_mbus_code - Handle pixel format enumeration
1765 * @sd : pointer to v4l2 subdev structure
1766 * @fh : V4L2 subdev file handle
1767 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1768 * return -EINVAL or zero on success
1770 static int preview_enum_mbus_code(struct v4l2_subdev
*sd
,
1771 struct v4l2_subdev_fh
*fh
,
1772 struct v4l2_subdev_mbus_code_enum
*code
)
1774 switch (code
->pad
) {
1776 if (code
->index
>= ARRAY_SIZE(preview_input_fmts
))
1779 code
->code
= preview_input_fmts
[code
->index
];
1781 case PREV_PAD_SOURCE
:
1782 if (code
->index
>= ARRAY_SIZE(preview_output_fmts
))
1785 code
->code
= preview_output_fmts
[code
->index
];
1794 static int preview_enum_frame_size(struct v4l2_subdev
*sd
,
1795 struct v4l2_subdev_fh
*fh
,
1796 struct v4l2_subdev_frame_size_enum
*fse
)
1798 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1799 struct v4l2_mbus_framefmt format
;
1801 if (fse
->index
!= 0)
1804 format
.code
= fse
->code
;
1807 preview_try_format(prev
, fh
, fse
->pad
, &format
, V4L2_SUBDEV_FORMAT_TRY
);
1808 fse
->min_width
= format
.width
;
1809 fse
->min_height
= format
.height
;
1811 if (format
.code
!= fse
->code
)
1814 format
.code
= fse
->code
;
1817 preview_try_format(prev
, fh
, fse
->pad
, &format
, V4L2_SUBDEV_FORMAT_TRY
);
1818 fse
->max_width
= format
.width
;
1819 fse
->max_height
= format
.height
;
1825 * preview_get_crop - Retrieve the crop rectangle on a pad
1826 * @sd: ISP preview V4L2 subdevice
1827 * @fh: V4L2 subdev file handle
1828 * @crop: crop rectangle
1830 * Return 0 on success or a negative error code otherwise.
1832 static int preview_get_crop(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1833 struct v4l2_subdev_crop
*crop
)
1835 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1837 /* Cropping is only supported on the sink pad. */
1838 if (crop
->pad
!= PREV_PAD_SINK
)
1841 crop
->rect
= *__preview_get_crop(prev
, fh
, crop
->which
);
1846 * preview_set_crop - Retrieve the crop rectangle on a pad
1847 * @sd: ISP preview V4L2 subdevice
1848 * @fh: V4L2 subdev file handle
1849 * @crop: crop rectangle
1851 * Return 0 on success or a negative error code otherwise.
1853 static int preview_set_crop(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1854 struct v4l2_subdev_crop
*crop
)
1856 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1857 struct v4l2_mbus_framefmt
*format
;
1859 /* Cropping is only supported on the sink pad. */
1860 if (crop
->pad
!= PREV_PAD_SINK
)
1863 /* The crop rectangle can't be changed while streaming. */
1864 if (prev
->state
!= ISP_PIPELINE_STREAM_STOPPED
)
1867 format
= __preview_get_format(prev
, fh
, PREV_PAD_SINK
, crop
->which
);
1868 preview_try_crop(prev
, format
, &crop
->rect
);
1869 *__preview_get_crop(prev
, fh
, crop
->which
) = crop
->rect
;
1871 /* Update the source format. */
1872 format
= __preview_get_format(prev
, fh
, PREV_PAD_SOURCE
, crop
->which
);
1873 preview_try_format(prev
, fh
, PREV_PAD_SOURCE
, format
, crop
->which
);
1879 * preview_get_format - Handle get format by pads subdev method
1880 * @sd : pointer to v4l2 subdev structure
1881 * @fh : V4L2 subdev file handle
1882 * @fmt: pointer to v4l2 subdev format structure
1883 * return -EINVAL or zero on success
1885 static int preview_get_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1886 struct v4l2_subdev_format
*fmt
)
1888 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1889 struct v4l2_mbus_framefmt
*format
;
1891 format
= __preview_get_format(prev
, fh
, fmt
->pad
, fmt
->which
);
1895 fmt
->format
= *format
;
1900 * preview_set_format - Handle set format by pads subdev method
1901 * @sd : pointer to v4l2 subdev structure
1902 * @fh : V4L2 subdev file handle
1903 * @fmt: pointer to v4l2 subdev format structure
1904 * return -EINVAL or zero on success
1906 static int preview_set_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1907 struct v4l2_subdev_format
*fmt
)
1909 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1910 struct v4l2_mbus_framefmt
*format
;
1911 struct v4l2_rect
*crop
;
1913 format
= __preview_get_format(prev
, fh
, fmt
->pad
, fmt
->which
);
1917 preview_try_format(prev
, fh
, fmt
->pad
, &fmt
->format
, fmt
->which
);
1918 *format
= fmt
->format
;
1920 /* Propagate the format from sink to source */
1921 if (fmt
->pad
== PREV_PAD_SINK
) {
1922 /* Reset the crop rectangle. */
1923 crop
= __preview_get_crop(prev
, fh
, fmt
->which
);
1926 crop
->width
= fmt
->format
.width
;
1927 crop
->height
= fmt
->format
.height
;
1929 preview_try_crop(prev
, &fmt
->format
, crop
);
1931 /* Update the source format. */
1932 format
= __preview_get_format(prev
, fh
, PREV_PAD_SOURCE
,
1934 preview_try_format(prev
, fh
, PREV_PAD_SOURCE
, format
,
1942 * preview_init_formats - Initialize formats on all pads
1943 * @sd: ISP preview V4L2 subdevice
1944 * @fh: V4L2 subdev file handle
1946 * Initialize all pad formats with default values. If fh is not NULL, try
1947 * formats are initialized on the file handle. Otherwise active formats are
1948 * initialized on the device.
1950 static int preview_init_formats(struct v4l2_subdev
*sd
,
1951 struct v4l2_subdev_fh
*fh
)
1953 struct v4l2_subdev_format format
;
1955 memset(&format
, 0, sizeof(format
));
1956 format
.pad
= PREV_PAD_SINK
;
1957 format
.which
= fh
? V4L2_SUBDEV_FORMAT_TRY
: V4L2_SUBDEV_FORMAT_ACTIVE
;
1958 format
.format
.code
= V4L2_MBUS_FMT_SGRBG10_1X10
;
1959 format
.format
.width
= 4096;
1960 format
.format
.height
= 4096;
1961 preview_set_format(sd
, fh
, &format
);
1966 /* subdev core operations */
1967 static const struct v4l2_subdev_core_ops preview_v4l2_core_ops
= {
1968 .ioctl
= preview_ioctl
,
1971 /* subdev video operations */
1972 static const struct v4l2_subdev_video_ops preview_v4l2_video_ops
= {
1973 .s_stream
= preview_set_stream
,
1976 /* subdev pad operations */
1977 static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops
= {
1978 .enum_mbus_code
= preview_enum_mbus_code
,
1979 .enum_frame_size
= preview_enum_frame_size
,
1980 .get_fmt
= preview_get_format
,
1981 .set_fmt
= preview_set_format
,
1982 .get_crop
= preview_get_crop
,
1983 .set_crop
= preview_set_crop
,
1986 /* subdev operations */
1987 static const struct v4l2_subdev_ops preview_v4l2_ops
= {
1988 .core
= &preview_v4l2_core_ops
,
1989 .video
= &preview_v4l2_video_ops
,
1990 .pad
= &preview_v4l2_pad_ops
,
1993 /* subdev internal operations */
1994 static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops
= {
1995 .open
= preview_init_formats
,
1998 /* -----------------------------------------------------------------------------
1999 * Media entity operations
2003 * preview_link_setup - Setup previewer connections.
2004 * @entity : Pointer to media entity structure
2005 * @local : Pointer to local pad array
2006 * @remote : Pointer to remote pad array
2007 * @flags : Link flags
2008 * return -EINVAL or zero on success
2010 static int preview_link_setup(struct media_entity
*entity
,
2011 const struct media_pad
*local
,
2012 const struct media_pad
*remote
, u32 flags
)
2014 struct v4l2_subdev
*sd
= media_entity_to_v4l2_subdev(entity
);
2015 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
2017 switch (local
->index
| media_entity_type(remote
->entity
)) {
2018 case PREV_PAD_SINK
| MEDIA_ENT_T_DEVNODE
:
2019 /* read from memory */
2020 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2021 if (prev
->input
== PREVIEW_INPUT_CCDC
)
2023 prev
->input
= PREVIEW_INPUT_MEMORY
;
2025 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
2026 prev
->input
= PREVIEW_INPUT_NONE
;
2030 case PREV_PAD_SINK
| MEDIA_ENT_T_V4L2_SUBDEV
:
2031 /* read from ccdc */
2032 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2033 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
2035 prev
->input
= PREVIEW_INPUT_CCDC
;
2037 if (prev
->input
== PREVIEW_INPUT_CCDC
)
2038 prev
->input
= PREVIEW_INPUT_NONE
;
2043 * The ISP core doesn't support pipelines with multiple video outputs.
2044 * Revisit this when it will be implemented, and return -EBUSY for now.
2047 case PREV_PAD_SOURCE
| MEDIA_ENT_T_DEVNODE
:
2048 /* write to memory */
2049 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2050 if (prev
->output
& ~PREVIEW_OUTPUT_MEMORY
)
2052 prev
->output
|= PREVIEW_OUTPUT_MEMORY
;
2054 prev
->output
&= ~PREVIEW_OUTPUT_MEMORY
;
2058 case PREV_PAD_SOURCE
| MEDIA_ENT_T_V4L2_SUBDEV
:
2059 /* write to resizer */
2060 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2061 if (prev
->output
& ~PREVIEW_OUTPUT_RESIZER
)
2063 prev
->output
|= PREVIEW_OUTPUT_RESIZER
;
2065 prev
->output
&= ~PREVIEW_OUTPUT_RESIZER
;
2076 /* media operations */
2077 static const struct media_entity_operations preview_media_ops
= {
2078 .link_setup
= preview_link_setup
,
2081 void omap3isp_preview_unregister_entities(struct isp_prev_device
*prev
)
2083 v4l2_device_unregister_subdev(&prev
->subdev
);
2084 omap3isp_video_unregister(&prev
->video_in
);
2085 omap3isp_video_unregister(&prev
->video_out
);
2088 int omap3isp_preview_register_entities(struct isp_prev_device
*prev
,
2089 struct v4l2_device
*vdev
)
2093 /* Register the subdev and video nodes. */
2094 ret
= v4l2_device_register_subdev(vdev
, &prev
->subdev
);
2098 ret
= omap3isp_video_register(&prev
->video_in
, vdev
);
2102 ret
= omap3isp_video_register(&prev
->video_out
, vdev
);
2109 omap3isp_preview_unregister_entities(prev
);
2113 /* -----------------------------------------------------------------------------
2114 * ISP previewer initialisation and cleanup
2118 * preview_init_entities - Initialize subdev and media entity.
2119 * @prev : Pointer to preview structure
2120 * return -ENOMEM or zero on success
2122 static int preview_init_entities(struct isp_prev_device
*prev
)
2124 struct v4l2_subdev
*sd
= &prev
->subdev
;
2125 struct media_pad
*pads
= prev
->pads
;
2126 struct media_entity
*me
= &sd
->entity
;
2129 prev
->input
= PREVIEW_INPUT_NONE
;
2131 v4l2_subdev_init(sd
, &preview_v4l2_ops
);
2132 sd
->internal_ops
= &preview_v4l2_internal_ops
;
2133 strlcpy(sd
->name
, "OMAP3 ISP preview", sizeof(sd
->name
));
2134 sd
->grp_id
= 1 << 16; /* group ID for isp subdevs */
2135 v4l2_set_subdevdata(sd
, prev
);
2136 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
2138 v4l2_ctrl_handler_init(&prev
->ctrls
, 2);
2139 v4l2_ctrl_new_std(&prev
->ctrls
, &preview_ctrl_ops
, V4L2_CID_BRIGHTNESS
,
2140 ISPPRV_BRIGHT_LOW
, ISPPRV_BRIGHT_HIGH
,
2141 ISPPRV_BRIGHT_STEP
, ISPPRV_BRIGHT_DEF
);
2142 v4l2_ctrl_new_std(&prev
->ctrls
, &preview_ctrl_ops
, V4L2_CID_CONTRAST
,
2143 ISPPRV_CONTRAST_LOW
, ISPPRV_CONTRAST_HIGH
,
2144 ISPPRV_CONTRAST_STEP
, ISPPRV_CONTRAST_DEF
);
2145 v4l2_ctrl_handler_setup(&prev
->ctrls
);
2146 sd
->ctrl_handler
= &prev
->ctrls
;
2148 pads
[PREV_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
2149 pads
[PREV_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
2151 me
->ops
= &preview_media_ops
;
2152 ret
= media_entity_init(me
, PREV_PADS_NUM
, pads
, 0);
2156 preview_init_formats(sd
, NULL
);
2158 /* According to the OMAP34xx TRM, video buffers need to be aligned on a
2159 * 32 bytes boundary. However, an undocumented hardware bug requires a
2160 * 64 bytes boundary at the preview engine input.
2162 prev
->video_in
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
2163 prev
->video_in
.ops
= &preview_video_ops
;
2164 prev
->video_in
.isp
= to_isp_device(prev
);
2165 prev
->video_in
.capture_mem
= PAGE_ALIGN(4096 * 4096) * 2 * 3;
2166 prev
->video_in
.bpl_alignment
= 64;
2167 prev
->video_out
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2168 prev
->video_out
.ops
= &preview_video_ops
;
2169 prev
->video_out
.isp
= to_isp_device(prev
);
2170 prev
->video_out
.capture_mem
= PAGE_ALIGN(4096 * 4096) * 2 * 3;
2171 prev
->video_out
.bpl_alignment
= 32;
2173 ret
= omap3isp_video_init(&prev
->video_in
, "preview");
2175 goto error_video_in
;
2177 ret
= omap3isp_video_init(&prev
->video_out
, "preview");
2179 goto error_video_out
;
2181 /* Connect the video nodes to the previewer subdev. */
2182 ret
= media_entity_create_link(&prev
->video_in
.video
.entity
, 0,
2183 &prev
->subdev
.entity
, PREV_PAD_SINK
, 0);
2187 ret
= media_entity_create_link(&prev
->subdev
.entity
, PREV_PAD_SOURCE
,
2188 &prev
->video_out
.video
.entity
, 0, 0);
2195 omap3isp_video_cleanup(&prev
->video_out
);
2197 omap3isp_video_cleanup(&prev
->video_in
);
2199 media_entity_cleanup(&prev
->subdev
.entity
);
2204 * isp_preview_init - Previewer initialization.
2205 * @dev : Pointer to ISP device
2206 * return -ENOMEM or zero on success
2208 int omap3isp_preview_init(struct isp_device
*isp
)
2210 struct isp_prev_device
*prev
= &isp
->isp_prev
;
2212 spin_lock_init(&prev
->lock
);
2213 init_waitqueue_head(&prev
->wait
);
2214 preview_init_params(prev
);
2216 return preview_init_entities(prev
);
2219 void omap3isp_preview_cleanup(struct isp_device
*isp
)
2221 struct isp_prev_device
*prev
= &isp
->isp_prev
;
2223 v4l2_ctrl_handler_free(&prev
->ctrls
);
2224 omap3isp_video_cleanup(&prev
->video_in
);
2225 omap3isp_video_cleanup(&prev
->video_out
);
2226 media_entity_cleanup(&prev
->subdev
.entity
);