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 filters that can be configured
86 * during streaming are enabled when computing sink crop and source format
89 * If a filter is disabled, additional cropping is automatically added at the
90 * preview engine input by the driver to avoid overflow at line and frame end.
91 * This is completely transparent for applications.
93 * Median filter 4 pixels
95 * Faulty pixels correction 4 pixels, 4 lines
96 * Color suppression 2 pixels
98 * -------------------------------------------------------------
99 * Maximum total 10 pixels, 4 lines
101 * The color suppression and luma enhancement filters are applied after bayer to
102 * YUV conversion. They thus can crop one pixel on the left and one pixel on the
103 * right side of the image without changing the color pattern. When both those
104 * filters are disabled, the driver must crop the two pixels on the same side of
105 * the image to avoid changing the bayer pattern. The left margin is thus set to
106 * 6 pixels and the right margin to 4 pixels.
109 #define PREV_MARGIN_LEFT 6
110 #define PREV_MARGIN_RIGHT 4
111 #define PREV_MARGIN_TOP 2
112 #define PREV_MARGIN_BOTTOM 2
114 #define PREV_MIN_IN_WIDTH 64
115 #define PREV_MIN_IN_HEIGHT 8
116 #define PREV_MAX_IN_HEIGHT 16384
118 #define PREV_MIN_OUT_WIDTH 0
119 #define PREV_MIN_OUT_HEIGHT 0
120 #define PREV_MAX_OUT_WIDTH_REV_1 1280
121 #define PREV_MAX_OUT_WIDTH_REV_2 3300
122 #define PREV_MAX_OUT_WIDTH_REV_15 4096
125 * Coeficient Tables for the submodules in Preview.
126 * Array is initialised with the values from.the tables text file.
130 * CFA Filter Coefficient Table
133 static u32 cfa_coef_table
[4][OMAP3ISP_PREV_CFA_BLK_SIZE
] = {
134 #include "cfa_coef_table.h"
138 * Default Gamma Correction Table - All components
140 static u32 gamma_table
[] = {
141 #include "gamma_table.h"
145 * Noise Filter Threshold table
147 static u32 noise_filter_table
[] = {
148 #include "noise_filter_table.h"
152 * Luminance Enhancement Table
154 static u32 luma_enhance_table
[] = {
155 #include "luma_enhance_table.h"
159 * preview_config_luma_enhancement - Configure the Luminance Enhancement table
162 preview_config_luma_enhancement(struct isp_prev_device
*prev
,
163 const struct prev_params
*params
)
165 struct isp_device
*isp
= to_isp_device(prev
);
166 const struct omap3isp_prev_luma
*yt
= ¶ms
->luma
;
169 isp_reg_writel(isp
, ISPPRV_YENH_TABLE_ADDR
,
170 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
171 for (i
= 0; i
< OMAP3ISP_PREV_YENH_TBL_SIZE
; i
++) {
172 isp_reg_writel(isp
, yt
->table
[i
],
173 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_DATA
);
178 * preview_enable_luma_enhancement - Enable/disable Luminance Enhancement
181 preview_enable_luma_enhancement(struct isp_prev_device
*prev
, bool enable
)
183 struct isp_device
*isp
= to_isp_device(prev
);
186 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
189 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
194 * preview_enable_invalaw - Enable/disable Inverse A-Law decompression
196 static void preview_enable_invalaw(struct isp_prev_device
*prev
, bool enable
)
198 struct isp_device
*isp
= to_isp_device(prev
);
201 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
204 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
209 * preview_config_hmed - Configure the Horizontal Median Filter
211 static void preview_config_hmed(struct isp_prev_device
*prev
,
212 const struct prev_params
*params
)
214 struct isp_device
*isp
= to_isp_device(prev
);
215 const struct omap3isp_prev_hmed
*hmed
= ¶ms
->hmed
;
217 isp_reg_writel(isp
, (hmed
->odddist
== 1 ? 0 : ISPPRV_HMED_ODDDIST
) |
218 (hmed
->evendist
== 1 ? 0 : ISPPRV_HMED_EVENDIST
) |
219 (hmed
->thres
<< ISPPRV_HMED_THRESHOLD_SHIFT
),
220 OMAP3_ISP_IOMEM_PREV
, ISPPRV_HMED
);
224 * preview_enable_hmed - Enable/disable the Horizontal Median Filter
226 static void preview_enable_hmed(struct isp_prev_device
*prev
, bool enable
)
228 struct isp_device
*isp
= to_isp_device(prev
);
231 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
234 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
239 * preview_config_cfa - Configure CFA Interpolation for Bayer formats
241 * The CFA table is organised in four blocks, one per Bayer component. The
242 * hardware expects blocks to follow the Bayer order of the input data, while
243 * the driver stores the table in GRBG order in memory. The blocks need to be
244 * reordered to support non-GRBG Bayer patterns.
246 static void preview_config_cfa(struct isp_prev_device
*prev
,
247 const struct prev_params
*params
)
249 static const unsigned int cfa_coef_order
[4][4] = {
250 { 0, 1, 2, 3 }, /* GRBG */
251 { 1, 0, 3, 2 }, /* RGGB */
252 { 2, 3, 0, 1 }, /* BGGR */
253 { 3, 2, 1, 0 }, /* GBRG */
255 const unsigned int *order
= cfa_coef_order
[prev
->params
.cfa_order
];
256 const struct omap3isp_prev_cfa
*cfa
= ¶ms
->cfa
;
257 struct isp_device
*isp
= to_isp_device(prev
);
262 (cfa
->gradthrs_vert
<< ISPPRV_CFA_GRADTH_VER_SHIFT
) |
263 (cfa
->gradthrs_horz
<< ISPPRV_CFA_GRADTH_HOR_SHIFT
),
264 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CFA
);
266 isp_reg_writel(isp
, ISPPRV_CFA_TABLE_ADDR
,
267 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
269 for (i
= 0; i
< 4; ++i
) {
270 const __u32
*block
= cfa
->table
[order
[i
]];
272 for (j
= 0; j
< OMAP3ISP_PREV_CFA_BLK_SIZE
; ++j
)
273 isp_reg_writel(isp
, block
[j
], OMAP3_ISP_IOMEM_PREV
,
274 ISPPRV_SET_TBL_DATA
);
279 * preview_config_chroma_suppression - Configure Chroma Suppression
282 preview_config_chroma_suppression(struct isp_prev_device
*prev
,
283 const struct prev_params
*params
)
285 struct isp_device
*isp
= to_isp_device(prev
);
286 const struct omap3isp_prev_csup
*cs
= ¶ms
->csup
;
289 cs
->gain
| (cs
->thres
<< ISPPRV_CSUP_THRES_SHIFT
) |
290 (cs
->hypf_en
<< ISPPRV_CSUP_HPYF_SHIFT
),
291 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSUP
);
295 * preview_enable_chroma_suppression - Enable/disable Chrominance Suppression
298 preview_enable_chroma_suppression(struct isp_prev_device
*prev
, bool enable
)
300 struct isp_device
*isp
= to_isp_device(prev
);
303 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
306 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
311 * preview_config_whitebalance - Configure White Balance parameters
313 * Coefficient matrix always with default values.
316 preview_config_whitebalance(struct isp_prev_device
*prev
,
317 const struct prev_params
*params
)
319 struct isp_device
*isp
= to_isp_device(prev
);
320 const struct omap3isp_prev_wbal
*wbal
= ¶ms
->wbal
;
323 isp_reg_writel(isp
, wbal
->dgain
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WB_DGAIN
);
325 val
= wbal
->coef0
<< ISPPRV_WBGAIN_COEF0_SHIFT
;
326 val
|= wbal
->coef1
<< ISPPRV_WBGAIN_COEF1_SHIFT
;
327 val
|= wbal
->coef2
<< ISPPRV_WBGAIN_COEF2_SHIFT
;
328 val
|= wbal
->coef3
<< ISPPRV_WBGAIN_COEF3_SHIFT
;
329 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WBGAIN
);
332 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N0_0_SHIFT
|
333 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N0_1_SHIFT
|
334 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N0_2_SHIFT
|
335 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N0_3_SHIFT
|
336 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N1_0_SHIFT
|
337 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N1_1_SHIFT
|
338 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N1_2_SHIFT
|
339 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N1_3_SHIFT
|
340 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N2_0_SHIFT
|
341 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N2_1_SHIFT
|
342 ISPPRV_WBSEL_COEF0
<< ISPPRV_WBSEL_N2_2_SHIFT
|
343 ISPPRV_WBSEL_COEF1
<< ISPPRV_WBSEL_N2_3_SHIFT
|
344 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N3_0_SHIFT
|
345 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N3_1_SHIFT
|
346 ISPPRV_WBSEL_COEF2
<< ISPPRV_WBSEL_N3_2_SHIFT
|
347 ISPPRV_WBSEL_COEF3
<< ISPPRV_WBSEL_N3_3_SHIFT
,
348 OMAP3_ISP_IOMEM_PREV
, ISPPRV_WBSEL
);
352 * preview_config_blkadj - Configure Black Adjustment
355 preview_config_blkadj(struct isp_prev_device
*prev
,
356 const struct prev_params
*params
)
358 struct isp_device
*isp
= to_isp_device(prev
);
359 const struct omap3isp_prev_blkadj
*blkadj
= ¶ms
->blkadj
;
361 isp_reg_writel(isp
, (blkadj
->blue
<< ISPPRV_BLKADJOFF_B_SHIFT
) |
362 (blkadj
->green
<< ISPPRV_BLKADJOFF_G_SHIFT
) |
363 (blkadj
->red
<< ISPPRV_BLKADJOFF_R_SHIFT
),
364 OMAP3_ISP_IOMEM_PREV
, ISPPRV_BLKADJOFF
);
368 * preview_config_rgb_blending - Configure RGB-RGB Blending
371 preview_config_rgb_blending(struct isp_prev_device
*prev
,
372 const struct prev_params
*params
)
374 struct isp_device
*isp
= to_isp_device(prev
);
375 const struct omap3isp_prev_rgbtorgb
*rgbrgb
= ¶ms
->rgb2rgb
;
378 val
= (rgbrgb
->matrix
[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT
;
379 val
|= (rgbrgb
->matrix
[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT
;
380 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT1
);
382 val
= (rgbrgb
->matrix
[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT
;
383 val
|= (rgbrgb
->matrix
[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT
;
384 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT2
);
386 val
= (rgbrgb
->matrix
[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT
;
387 val
|= (rgbrgb
->matrix
[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT
;
388 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT3
);
390 val
= (rgbrgb
->matrix
[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT
;
391 val
|= (rgbrgb
->matrix
[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT
;
392 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT4
);
394 val
= (rgbrgb
->matrix
[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT
;
395 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_MAT5
);
397 val
= (rgbrgb
->offset
[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT
;
398 val
|= (rgbrgb
->offset
[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT
;
399 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_OFF1
);
401 val
= (rgbrgb
->offset
[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT
;
402 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RGB_OFF2
);
406 * preview_config_csc - Configure Color Space Conversion (RGB to YCbYCr)
409 preview_config_csc(struct isp_prev_device
*prev
,
410 const struct prev_params
*params
)
412 struct isp_device
*isp
= to_isp_device(prev
);
413 const struct omap3isp_prev_csc
*csc
= ¶ms
->csc
;
416 val
= (csc
->matrix
[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT
;
417 val
|= (csc
->matrix
[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT
;
418 val
|= (csc
->matrix
[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT
;
419 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC0
);
421 val
= (csc
->matrix
[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT
;
422 val
|= (csc
->matrix
[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT
;
423 val
|= (csc
->matrix
[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT
;
424 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC1
);
426 val
= (csc
->matrix
[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT
;
427 val
|= (csc
->matrix
[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT
;
428 val
|= (csc
->matrix
[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT
;
429 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC2
);
431 val
= (csc
->offset
[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT
;
432 val
|= (csc
->offset
[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT
;
433 val
|= (csc
->offset
[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT
;
434 isp_reg_writel(isp
, val
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CSC_OFFSET
);
438 * preview_config_yc_range - Configure the max and min Y and C values
441 preview_config_yc_range(struct isp_prev_device
*prev
,
442 const struct prev_params
*params
)
444 struct isp_device
*isp
= to_isp_device(prev
);
445 const struct omap3isp_prev_yclimit
*yc
= ¶ms
->yclimit
;
448 yc
->maxC
<< ISPPRV_SETUP_YC_MAXC_SHIFT
|
449 yc
->maxY
<< ISPPRV_SETUP_YC_MAXY_SHIFT
|
450 yc
->minC
<< ISPPRV_SETUP_YC_MINC_SHIFT
|
451 yc
->minY
<< ISPPRV_SETUP_YC_MINY_SHIFT
,
452 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SETUP_YC
);
456 * preview_config_dcor - Configure Couplet Defect Correction
459 preview_config_dcor(struct isp_prev_device
*prev
,
460 const struct prev_params
*params
)
462 struct isp_device
*isp
= to_isp_device(prev
);
463 const struct omap3isp_prev_dcor
*dcor
= ¶ms
->dcor
;
465 isp_reg_writel(isp
, dcor
->detect_correct
[0],
466 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR0
);
467 isp_reg_writel(isp
, dcor
->detect_correct
[1],
468 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR1
);
469 isp_reg_writel(isp
, dcor
->detect_correct
[2],
470 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR2
);
471 isp_reg_writel(isp
, dcor
->detect_correct
[3],
472 OMAP3_ISP_IOMEM_PREV
, ISPPRV_CDC_THR3
);
473 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
475 dcor
->couplet_mode_en
? ISPPRV_PCR_DCCOUP
: 0);
479 * preview_enable_dcor - Enable/disable Couplet Defect Correction
481 static void preview_enable_dcor(struct isp_prev_device
*prev
, bool enable
)
483 struct isp_device
*isp
= to_isp_device(prev
);
486 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
489 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
494 * preview_enable_drkframe_capture - Enable/disable Dark Frame Capture
497 preview_enable_drkframe_capture(struct isp_prev_device
*prev
, bool enable
)
499 struct isp_device
*isp
= to_isp_device(prev
);
502 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
505 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
510 * preview_enable_drkframe - Enable/disable Dark Frame Subtraction
512 static void preview_enable_drkframe(struct isp_prev_device
*prev
, bool enable
)
514 struct isp_device
*isp
= to_isp_device(prev
);
517 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
520 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
525 * preview_config_noisefilter - Configure the Noise Filter
528 preview_config_noisefilter(struct isp_prev_device
*prev
,
529 const struct prev_params
*params
)
531 struct isp_device
*isp
= to_isp_device(prev
);
532 const struct omap3isp_prev_nf
*nf
= ¶ms
->nf
;
535 isp_reg_writel(isp
, nf
->spread
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_NF
);
536 isp_reg_writel(isp
, ISPPRV_NF_TABLE_ADDR
,
537 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
538 for (i
= 0; i
< OMAP3ISP_PREV_NF_TBL_SIZE
; i
++) {
539 isp_reg_writel(isp
, nf
->table
[i
],
540 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_DATA
);
545 * preview_enable_noisefilter - Enable/disable the Noise Filter
548 preview_enable_noisefilter(struct isp_prev_device
*prev
, bool enable
)
550 struct isp_device
*isp
= to_isp_device(prev
);
553 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
556 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
561 * preview_config_gammacorrn - Configure the Gamma Correction tables
564 preview_config_gammacorrn(struct isp_prev_device
*prev
,
565 const struct prev_params
*params
)
567 struct isp_device
*isp
= to_isp_device(prev
);
568 const struct omap3isp_prev_gtables
*gt
= ¶ms
->gamma
;
571 isp_reg_writel(isp
, ISPPRV_REDGAMMA_TABLE_ADDR
,
572 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
573 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
574 isp_reg_writel(isp
, gt
->red
[i
], OMAP3_ISP_IOMEM_PREV
,
575 ISPPRV_SET_TBL_DATA
);
577 isp_reg_writel(isp
, ISPPRV_GREENGAMMA_TABLE_ADDR
,
578 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
579 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
580 isp_reg_writel(isp
, gt
->green
[i
], OMAP3_ISP_IOMEM_PREV
,
581 ISPPRV_SET_TBL_DATA
);
583 isp_reg_writel(isp
, ISPPRV_BLUEGAMMA_TABLE_ADDR
,
584 OMAP3_ISP_IOMEM_PREV
, ISPPRV_SET_TBL_ADDR
);
585 for (i
= 0; i
< OMAP3ISP_PREV_GAMMA_TBL_SIZE
; i
++)
586 isp_reg_writel(isp
, gt
->blue
[i
], OMAP3_ISP_IOMEM_PREV
,
587 ISPPRV_SET_TBL_DATA
);
591 * preview_enable_gammacorrn - Enable/disable Gamma Correction
593 * When gamma correction is disabled, the module is bypassed and its output is
594 * the 8 MSB of the 10-bit input .
597 preview_enable_gammacorrn(struct isp_prev_device
*prev
, bool enable
)
599 struct isp_device
*isp
= to_isp_device(prev
);
602 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
603 ISPPRV_PCR_GAMMA_BYPASS
);
605 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
606 ISPPRV_PCR_GAMMA_BYPASS
);
610 * preview_config_contrast - Configure the Contrast
612 * Value should be programmed before enabling the module.
615 preview_config_contrast(struct isp_prev_device
*prev
,
616 const struct prev_params
*params
)
618 struct isp_device
*isp
= to_isp_device(prev
);
620 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CNT_BRT
,
621 0xff << ISPPRV_CNT_BRT_CNT_SHIFT
,
622 params
->contrast
<< ISPPRV_CNT_BRT_CNT_SHIFT
);
626 * preview_config_brightness - Configure the Brightness
629 preview_config_brightness(struct isp_prev_device
*prev
,
630 const struct prev_params
*params
)
632 struct isp_device
*isp
= to_isp_device(prev
);
634 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_CNT_BRT
,
635 0xff << ISPPRV_CNT_BRT_BRT_SHIFT
,
636 params
->brightness
<< ISPPRV_CNT_BRT_BRT_SHIFT
);
640 * preview_update_contrast - Updates the contrast.
641 * @contrast: Pointer to hold the current programmed contrast value.
643 * Value should be programmed before enabling the module.
646 preview_update_contrast(struct isp_prev_device
*prev
, u8 contrast
)
648 struct prev_params
*params
;
651 spin_lock_irqsave(&prev
->params
.lock
, flags
);
652 params
= (prev
->params
.active
& OMAP3ISP_PREV_CONTRAST
)
653 ? &prev
->params
.params
[0] : &prev
->params
.params
[1];
655 if (params
->contrast
!= (contrast
* ISPPRV_CONTRAST_UNITS
)) {
656 params
->contrast
= contrast
* ISPPRV_CONTRAST_UNITS
;
657 params
->update
|= OMAP3ISP_PREV_CONTRAST
;
659 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
663 * preview_update_brightness - Updates the brightness in preview module.
664 * @brightness: Pointer to hold the current programmed brightness value.
668 preview_update_brightness(struct isp_prev_device
*prev
, u8 brightness
)
670 struct prev_params
*params
;
673 spin_lock_irqsave(&prev
->params
.lock
, flags
);
674 params
= (prev
->params
.active
& OMAP3ISP_PREV_BRIGHTNESS
)
675 ? &prev
->params
.params
[0] : &prev
->params
.params
[1];
677 if (params
->brightness
!= (brightness
* ISPPRV_BRIGHT_UNITS
)) {
678 params
->brightness
= brightness
* ISPPRV_BRIGHT_UNITS
;
679 params
->update
|= OMAP3ISP_PREV_BRIGHTNESS
;
681 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
685 preview_params_lock(struct isp_prev_device
*prev
, u32 update
, bool shadow
)
687 u32 active
= prev
->params
.active
;
690 /* Mark all shadow parameters we are going to touch as busy. */
691 prev
->params
.params
[0].busy
|= ~active
& update
;
692 prev
->params
.params
[1].busy
|= active
& update
;
694 /* Mark all active parameters we are going to touch as busy. */
695 update
= (prev
->params
.params
[0].update
& active
)
696 | (prev
->params
.params
[1].update
& ~active
);
698 prev
->params
.params
[0].busy
|= active
& update
;
699 prev
->params
.params
[1].busy
|= ~active
& update
;
706 preview_params_unlock(struct isp_prev_device
*prev
, u32 update
, bool shadow
)
708 u32 active
= prev
->params
.active
;
711 /* Set the update flag for shadow parameters that have been
712 * updated and clear the busy flag for all shadow parameters.
714 prev
->params
.params
[0].update
|= (~active
& update
);
715 prev
->params
.params
[1].update
|= (active
& update
);
716 prev
->params
.params
[0].busy
&= active
;
717 prev
->params
.params
[1].busy
&= ~active
;
719 /* Clear the update flag for active parameters that have been
720 * applied and the busy flag for all active parameters.
722 prev
->params
.params
[0].update
&= ~(active
& update
);
723 prev
->params
.params
[1].update
&= ~(~active
& update
);
724 prev
->params
.params
[0].busy
&= ~active
;
725 prev
->params
.params
[1].busy
&= active
;
729 static void preview_params_switch(struct isp_prev_device
*prev
)
733 /* Switch active parameters with updated shadow parameters when the
734 * shadow parameter has been updated and neither the active not the
735 * shadow parameter is busy.
737 to_switch
= (prev
->params
.params
[0].update
& ~prev
->params
.active
)
738 | (prev
->params
.params
[1].update
& prev
->params
.active
);
739 to_switch
&= ~(prev
->params
.params
[0].busy
|
740 prev
->params
.params
[1].busy
);
744 prev
->params
.active
^= to_switch
;
746 /* Remove the update flag for the shadow copy of parameters we have
749 prev
->params
.params
[0].update
&= ~(~prev
->params
.active
& to_switch
);
750 prev
->params
.params
[1].update
&= ~(prev
->params
.active
& to_switch
);
753 /* preview parameters update structure */
754 struct preview_update
{
755 void (*config
)(struct isp_prev_device
*, const struct prev_params
*);
756 void (*enable
)(struct isp_prev_device
*, bool);
757 unsigned int param_offset
;
758 unsigned int param_size
;
759 unsigned int config_offset
;
763 /* Keep the array indexed by the OMAP3ISP_PREV_* bit number. */
764 static const struct preview_update update_attrs
[] = {
765 /* OMAP3ISP_PREV_LUMAENH */ {
766 preview_config_luma_enhancement
,
767 preview_enable_luma_enhancement
,
768 offsetof(struct prev_params
, luma
),
769 FIELD_SIZEOF(struct prev_params
, luma
),
770 offsetof(struct omap3isp_prev_update_config
, luma
),
771 }, /* OMAP3ISP_PREV_INVALAW */ {
773 preview_enable_invalaw
,
774 }, /* OMAP3ISP_PREV_HRZ_MED */ {
777 offsetof(struct prev_params
, hmed
),
778 FIELD_SIZEOF(struct prev_params
, hmed
),
779 offsetof(struct omap3isp_prev_update_config
, hmed
),
780 }, /* OMAP3ISP_PREV_CFA */ {
783 offsetof(struct prev_params
, cfa
),
784 FIELD_SIZEOF(struct prev_params
, cfa
),
785 offsetof(struct omap3isp_prev_update_config
, cfa
),
786 }, /* OMAP3ISP_PREV_CHROMA_SUPP */ {
787 preview_config_chroma_suppression
,
788 preview_enable_chroma_suppression
,
789 offsetof(struct prev_params
, csup
),
790 FIELD_SIZEOF(struct prev_params
, csup
),
791 offsetof(struct omap3isp_prev_update_config
, csup
),
792 }, /* OMAP3ISP_PREV_WB */ {
793 preview_config_whitebalance
,
795 offsetof(struct prev_params
, wbal
),
796 FIELD_SIZEOF(struct prev_params
, wbal
),
797 offsetof(struct omap3isp_prev_update_config
, wbal
),
798 }, /* OMAP3ISP_PREV_BLKADJ */ {
799 preview_config_blkadj
,
801 offsetof(struct prev_params
, blkadj
),
802 FIELD_SIZEOF(struct prev_params
, blkadj
),
803 offsetof(struct omap3isp_prev_update_config
, blkadj
),
804 }, /* OMAP3ISP_PREV_RGB2RGB */ {
805 preview_config_rgb_blending
,
807 offsetof(struct prev_params
, rgb2rgb
),
808 FIELD_SIZEOF(struct prev_params
, rgb2rgb
),
809 offsetof(struct omap3isp_prev_update_config
, rgb2rgb
),
810 }, /* OMAP3ISP_PREV_COLOR_CONV */ {
813 offsetof(struct prev_params
, csc
),
814 FIELD_SIZEOF(struct prev_params
, csc
),
815 offsetof(struct omap3isp_prev_update_config
, csc
),
816 }, /* OMAP3ISP_PREV_YC_LIMIT */ {
817 preview_config_yc_range
,
819 offsetof(struct prev_params
, yclimit
),
820 FIELD_SIZEOF(struct prev_params
, yclimit
),
821 offsetof(struct omap3isp_prev_update_config
, yclimit
),
822 }, /* OMAP3ISP_PREV_DEFECT_COR */ {
825 offsetof(struct prev_params
, dcor
),
826 FIELD_SIZEOF(struct prev_params
, dcor
),
827 offsetof(struct omap3isp_prev_update_config
, dcor
),
828 }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ {
831 }, /* OMAP3ISP_PREV_DRK_FRM_CAPTURE */ {
833 preview_enable_drkframe_capture
,
834 }, /* OMAP3ISP_PREV_DRK_FRM_SUBTRACT */ {
836 preview_enable_drkframe
,
837 }, /* OMAP3ISP_PREV_LENS_SHADING */ {
839 preview_enable_drkframe
,
840 }, /* OMAP3ISP_PREV_NF */ {
841 preview_config_noisefilter
,
842 preview_enable_noisefilter
,
843 offsetof(struct prev_params
, nf
),
844 FIELD_SIZEOF(struct prev_params
, nf
),
845 offsetof(struct omap3isp_prev_update_config
, nf
),
846 }, /* OMAP3ISP_PREV_GAMMA */ {
847 preview_config_gammacorrn
,
848 preview_enable_gammacorrn
,
849 offsetof(struct prev_params
, gamma
),
850 FIELD_SIZEOF(struct prev_params
, gamma
),
851 offsetof(struct omap3isp_prev_update_config
, gamma
),
852 }, /* OMAP3ISP_PREV_CONTRAST */ {
853 preview_config_contrast
,
856 }, /* OMAP3ISP_PREV_BRIGHTNESS */ {
857 preview_config_brightness
,
864 * preview_config - Copy and update local structure with userspace preview
866 * @prev: ISP preview engine
867 * @cfg: Configuration
869 * Return zero if success or -EFAULT if the configuration can't be copied from
872 static int preview_config(struct isp_prev_device
*prev
,
873 struct omap3isp_prev_update_config
*cfg
)
881 if (cfg
->update
== 0)
884 /* Mark the shadow parameters we're going to update as busy. */
885 spin_lock_irqsave(&prev
->params
.lock
, flags
);
886 preview_params_lock(prev
, cfg
->update
, true);
887 active
= prev
->params
.active
;
888 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
892 for (i
= 0; i
< ARRAY_SIZE(update_attrs
); i
++) {
893 const struct preview_update
*attr
= &update_attrs
[i
];
894 struct prev_params
*params
;
895 unsigned int bit
= 1 << i
;
897 if (attr
->skip
|| !(cfg
->update
& bit
))
900 params
= &prev
->params
.params
[!!(active
& bit
)];
902 if (cfg
->flag
& bit
) {
903 void __user
*from
= *(void * __user
*)
904 ((void *)cfg
+ attr
->config_offset
);
905 void *to
= (void *)params
+ attr
->param_offset
;
906 size_t size
= attr
->param_size
;
908 if (to
&& from
&& size
) {
909 if (copy_from_user(to
, from
, size
)) {
914 params
->features
|= bit
;
916 params
->features
&= ~bit
;
922 spin_lock_irqsave(&prev
->params
.lock
, flags
);
923 preview_params_unlock(prev
, update
, true);
924 preview_params_switch(prev
);
925 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
931 * preview_setup_hw - Setup preview registers and/or internal memory
932 * @prev: pointer to preview private structure
933 * @update: Bitmask of parameters to setup
934 * @active: Bitmask of parameters active in set 0
935 * Note: can be called from interrupt context
938 static void preview_setup_hw(struct isp_prev_device
*prev
, u32 update
,
947 features
= (prev
->params
.params
[0].features
& active
)
948 | (prev
->params
.params
[1].features
& ~active
);
950 for (i
= 0; i
< ARRAY_SIZE(update_attrs
); i
++) {
951 const struct preview_update
*attr
= &update_attrs
[i
];
952 struct prev_params
*params
;
953 unsigned int bit
= 1 << i
;
958 params
= &prev
->params
.params
[!(active
& bit
)];
960 if (params
->features
& bit
) {
962 attr
->config(prev
, params
);
964 attr
->enable(prev
, true);
967 attr
->enable(prev
, false);
973 * preview_config_ycpos - Configure byte layout of YUV image.
974 * @mode: Indicates the required byte layout.
977 preview_config_ycpos(struct isp_prev_device
*prev
,
978 enum v4l2_mbus_pixelcode pixelcode
)
980 struct isp_device
*isp
= to_isp_device(prev
);
981 enum preview_ycpos_mode mode
;
984 case V4L2_MBUS_FMT_YUYV8_1X16
:
987 case V4L2_MBUS_FMT_UYVY8_1X16
:
994 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
995 ISPPRV_PCR_YCPOS_CrYCbY
,
996 mode
<< ISPPRV_PCR_YCPOS_SHIFT
);
1000 * preview_config_averager - Enable / disable / configure averager
1001 * @average: Average value to be configured.
1003 static void preview_config_averager(struct isp_prev_device
*prev
, u8 average
)
1005 struct isp_device
*isp
= to_isp_device(prev
);
1007 isp_reg_writel(isp
, ISPPRV_AVE_EVENDIST_2
<< ISPPRV_AVE_EVENDIST_SHIFT
|
1008 ISPPRV_AVE_ODDDIST_2
<< ISPPRV_AVE_ODDDIST_SHIFT
|
1009 average
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_AVE
);
1014 * preview_config_input_format - Configure the input format
1015 * @prev: The preview engine
1016 * @info: Sink pad format information
1018 * Enable and configure CFA interpolation for Bayer formats and disable it for
1019 * greyscale formats.
1021 * The CFA table is organised in four blocks, one per Bayer component. The
1022 * hardware expects blocks to follow the Bayer order of the input data, while
1023 * the driver stores the table in GRBG order in memory. The blocks need to be
1024 * reordered to support non-GRBG Bayer patterns.
1026 static void preview_config_input_format(struct isp_prev_device
*prev
,
1027 const struct isp_format_info
*info
)
1029 struct isp_device
*isp
= to_isp_device(prev
);
1030 struct prev_params
*params
;
1032 if (info
->width
== 8)
1033 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1036 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1039 switch (info
->flavor
) {
1040 case V4L2_MBUS_FMT_SGRBG8_1X8
:
1041 prev
->params
.cfa_order
= 0;
1043 case V4L2_MBUS_FMT_SRGGB8_1X8
:
1044 prev
->params
.cfa_order
= 1;
1046 case V4L2_MBUS_FMT_SBGGR8_1X8
:
1047 prev
->params
.cfa_order
= 2;
1049 case V4L2_MBUS_FMT_SGBRG8_1X8
:
1050 prev
->params
.cfa_order
= 3;
1053 /* Disable CFA for non-Bayer formats. */
1054 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1059 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
, ISPPRV_PCR_CFAEN
);
1060 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1061 ISPPRV_PCR_CFAFMT_MASK
, ISPPRV_PCR_CFAFMT_BAYER
);
1063 params
= (prev
->params
.active
& OMAP3ISP_PREV_CFA
)
1064 ? &prev
->params
.params
[0] : &prev
->params
.params
[1];
1066 preview_config_cfa(prev
, params
);
1070 * preview_config_input_size - Configure the input frame size
1072 * The preview engine crops several rows and columns internally depending on
1073 * which processing blocks are enabled. The driver assumes all those blocks are
1074 * enabled when reporting source pad formats to userspace. If this assumption is
1075 * not true, rows and columns must be manually cropped at the preview engine
1076 * input to avoid overflows at the end of lines and frames.
1078 * See the explanation at the PREV_MARGIN_* definitions for more details.
1080 static void preview_config_input_size(struct isp_prev_device
*prev
, u32 active
)
1082 const struct v4l2_mbus_framefmt
*format
= &prev
->formats
[PREV_PAD_SINK
];
1083 struct isp_device
*isp
= to_isp_device(prev
);
1084 unsigned int sph
= prev
->crop
.left
;
1085 unsigned int eph
= prev
->crop
.left
+ prev
->crop
.width
- 1;
1086 unsigned int slv
= prev
->crop
.top
;
1087 unsigned int elv
= prev
->crop
.top
+ prev
->crop
.height
- 1;
1090 if (format
->code
!= V4L2_MBUS_FMT_Y8_1X8
&&
1091 format
->code
!= V4L2_MBUS_FMT_Y10_1X10
) {
1098 features
= (prev
->params
.params
[0].features
& active
)
1099 | (prev
->params
.params
[1].features
& ~active
);
1101 if (features
& (OMAP3ISP_PREV_DEFECT_COR
| OMAP3ISP_PREV_NF
)) {
1107 if (features
& OMAP3ISP_PREV_HRZ_MED
) {
1111 if (features
& (OMAP3ISP_PREV_CHROMA_SUPP
| OMAP3ISP_PREV_LUMAENH
))
1114 isp_reg_writel(isp
, (sph
<< ISPPRV_HORZ_INFO_SPH_SHIFT
) | eph
,
1115 OMAP3_ISP_IOMEM_PREV
, ISPPRV_HORZ_INFO
);
1116 isp_reg_writel(isp
, (slv
<< ISPPRV_VERT_INFO_SLV_SHIFT
) | elv
,
1117 OMAP3_ISP_IOMEM_PREV
, ISPPRV_VERT_INFO
);
1121 * preview_config_inlineoffset - Configures the Read address line offset.
1122 * @prev: Preview module
1123 * @offset: Line offset
1125 * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
1126 * However, a hardware bug requires the memory start address to be aligned on a
1127 * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
1131 preview_config_inlineoffset(struct isp_prev_device
*prev
, u32 offset
)
1133 struct isp_device
*isp
= to_isp_device(prev
);
1135 isp_reg_writel(isp
, offset
& 0xffff, OMAP3_ISP_IOMEM_PREV
,
1136 ISPPRV_RADR_OFFSET
);
1140 * preview_set_inaddr - Sets memory address of input frame.
1141 * @addr: 32bit memory address aligned on 32byte boundary.
1143 * Configures the memory address from which the input frame is to be read.
1145 static void preview_set_inaddr(struct isp_prev_device
*prev
, u32 addr
)
1147 struct isp_device
*isp
= to_isp_device(prev
);
1149 isp_reg_writel(isp
, addr
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_RSDR_ADDR
);
1153 * preview_config_outlineoffset - Configures the Write address line offset.
1154 * @offset: Line Offset for the preview output.
1156 * The offset must be a multiple of 32 bytes.
1158 static void preview_config_outlineoffset(struct isp_prev_device
*prev
,
1161 struct isp_device
*isp
= to_isp_device(prev
);
1163 isp_reg_writel(isp
, offset
& 0xffff, OMAP3_ISP_IOMEM_PREV
,
1164 ISPPRV_WADD_OFFSET
);
1168 * preview_set_outaddr - Sets the memory address to store output frame
1169 * @addr: 32bit memory address aligned on 32byte boundary.
1171 * Configures the memory address to which the output frame is written.
1173 static void preview_set_outaddr(struct isp_prev_device
*prev
, u32 addr
)
1175 struct isp_device
*isp
= to_isp_device(prev
);
1177 isp_reg_writel(isp
, addr
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_WSDR_ADDR
);
1180 static void preview_adjust_bandwidth(struct isp_prev_device
*prev
)
1182 struct isp_pipeline
*pipe
= to_isp_pipeline(&prev
->subdev
.entity
);
1183 struct isp_device
*isp
= to_isp_device(prev
);
1184 const struct v4l2_mbus_framefmt
*ifmt
= &prev
->formats
[PREV_PAD_SINK
];
1185 unsigned long l3_ick
= pipe
->l3_ick
;
1186 struct v4l2_fract
*timeperframe
;
1187 unsigned int cycles_per_frame
;
1188 unsigned int requests_per_frame
;
1189 unsigned int cycles_per_request
;
1190 unsigned int minimum
;
1191 unsigned int maximum
;
1194 if (prev
->input
!= PREVIEW_INPUT_MEMORY
) {
1195 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_SBL
, ISPSBL_SDR_REQ_EXP
,
1196 ISPSBL_SDR_REQ_PRV_EXP_MASK
);
1200 /* Compute the minimum number of cycles per request, based on the
1201 * pipeline maximum data rate. This is an absolute lower bound if we
1202 * don't want SBL overflows, so round the value up.
1204 cycles_per_request
= div_u64((u64
)l3_ick
/ 2 * 256 + pipe
->max_rate
- 1,
1206 minimum
= DIV_ROUND_UP(cycles_per_request
, 32);
1208 /* Compute the maximum number of cycles per request, based on the
1209 * requested frame rate. This is a soft upper bound to achieve a frame
1210 * rate equal or higher than the requested value, so round the value
1213 timeperframe
= &pipe
->max_timeperframe
;
1215 requests_per_frame
= DIV_ROUND_UP(ifmt
->width
* 2, 256) * ifmt
->height
;
1216 cycles_per_frame
= div_u64((u64
)l3_ick
* timeperframe
->numerator
,
1217 timeperframe
->denominator
);
1218 cycles_per_request
= cycles_per_frame
/ requests_per_frame
;
1220 maximum
= cycles_per_request
/ 32;
1222 value
= max(minimum
, maximum
);
1224 dev_dbg(isp
->dev
, "%s: cycles per request = %u\n", __func__
, value
);
1225 isp_reg_clr_set(isp
, OMAP3_ISP_IOMEM_SBL
, ISPSBL_SDR_REQ_EXP
,
1226 ISPSBL_SDR_REQ_PRV_EXP_MASK
,
1227 value
<< ISPSBL_SDR_REQ_PRV_EXP_SHIFT
);
1231 * omap3isp_preview_busy - Gets busy state of preview module.
1233 int omap3isp_preview_busy(struct isp_prev_device
*prev
)
1235 struct isp_device
*isp
= to_isp_device(prev
);
1237 return isp_reg_readl(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
)
1242 * omap3isp_preview_restore_context - Restores the values of preview registers
1244 void omap3isp_preview_restore_context(struct isp_device
*isp
)
1246 struct isp_prev_device
*prev
= &isp
->isp_prev
;
1247 const u32 update
= OMAP3ISP_PREV_FEATURES_END
- 1;
1249 prev
->params
.params
[0].update
= prev
->params
.active
& update
;
1250 prev
->params
.params
[1].update
= ~prev
->params
.active
& update
;
1252 preview_setup_hw(prev
, update
, prev
->params
.active
);
1254 prev
->params
.params
[0].update
= 0;
1255 prev
->params
.params
[1].update
= 0;
1259 * preview_print_status - Dump preview module registers to the kernel log
1261 #define PREV_PRINT_REGISTER(isp, name)\
1262 dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
1263 isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
1265 static void preview_print_status(struct isp_prev_device
*prev
)
1267 struct isp_device
*isp
= to_isp_device(prev
);
1269 dev_dbg(isp
->dev
, "-------------Preview Register dump----------\n");
1271 PREV_PRINT_REGISTER(isp
, PCR
);
1272 PREV_PRINT_REGISTER(isp
, HORZ_INFO
);
1273 PREV_PRINT_REGISTER(isp
, VERT_INFO
);
1274 PREV_PRINT_REGISTER(isp
, RSDR_ADDR
);
1275 PREV_PRINT_REGISTER(isp
, RADR_OFFSET
);
1276 PREV_PRINT_REGISTER(isp
, DSDR_ADDR
);
1277 PREV_PRINT_REGISTER(isp
, DRKF_OFFSET
);
1278 PREV_PRINT_REGISTER(isp
, WSDR_ADDR
);
1279 PREV_PRINT_REGISTER(isp
, WADD_OFFSET
);
1280 PREV_PRINT_REGISTER(isp
, AVE
);
1281 PREV_PRINT_REGISTER(isp
, HMED
);
1282 PREV_PRINT_REGISTER(isp
, NF
);
1283 PREV_PRINT_REGISTER(isp
, WB_DGAIN
);
1284 PREV_PRINT_REGISTER(isp
, WBGAIN
);
1285 PREV_PRINT_REGISTER(isp
, WBSEL
);
1286 PREV_PRINT_REGISTER(isp
, CFA
);
1287 PREV_PRINT_REGISTER(isp
, BLKADJOFF
);
1288 PREV_PRINT_REGISTER(isp
, RGB_MAT1
);
1289 PREV_PRINT_REGISTER(isp
, RGB_MAT2
);
1290 PREV_PRINT_REGISTER(isp
, RGB_MAT3
);
1291 PREV_PRINT_REGISTER(isp
, RGB_MAT4
);
1292 PREV_PRINT_REGISTER(isp
, RGB_MAT5
);
1293 PREV_PRINT_REGISTER(isp
, RGB_OFF1
);
1294 PREV_PRINT_REGISTER(isp
, RGB_OFF2
);
1295 PREV_PRINT_REGISTER(isp
, CSC0
);
1296 PREV_PRINT_REGISTER(isp
, CSC1
);
1297 PREV_PRINT_REGISTER(isp
, CSC2
);
1298 PREV_PRINT_REGISTER(isp
, CSC_OFFSET
);
1299 PREV_PRINT_REGISTER(isp
, CNT_BRT
);
1300 PREV_PRINT_REGISTER(isp
, CSUP
);
1301 PREV_PRINT_REGISTER(isp
, SETUP_YC
);
1302 PREV_PRINT_REGISTER(isp
, SET_TBL_ADDR
);
1303 PREV_PRINT_REGISTER(isp
, CDC_THR0
);
1304 PREV_PRINT_REGISTER(isp
, CDC_THR1
);
1305 PREV_PRINT_REGISTER(isp
, CDC_THR2
);
1306 PREV_PRINT_REGISTER(isp
, CDC_THR3
);
1308 dev_dbg(isp
->dev
, "--------------------------------------------\n");
1312 * preview_init_params - init image processing parameters.
1313 * @prev: pointer to previewer private structure
1315 static void preview_init_params(struct isp_prev_device
*prev
)
1317 struct prev_params
*params
;
1320 spin_lock_init(&prev
->params
.lock
);
1322 prev
->params
.active
= ~0;
1323 prev
->params
.params
[0].busy
= 0;
1324 prev
->params
.params
[0].update
= OMAP3ISP_PREV_FEATURES_END
- 1;
1325 prev
->params
.params
[1].busy
= 0;
1326 prev
->params
.params
[1].update
= 0;
1328 params
= &prev
->params
.params
[0];
1331 params
->contrast
= ISPPRV_CONTRAST_DEF
* ISPPRV_CONTRAST_UNITS
;
1332 params
->brightness
= ISPPRV_BRIGHT_DEF
* ISPPRV_BRIGHT_UNITS
;
1333 params
->cfa
.format
= OMAP3ISP_CFAFMT_BAYER
;
1334 memcpy(params
->cfa
.table
, cfa_coef_table
,
1335 sizeof(params
->cfa
.table
));
1336 params
->cfa
.gradthrs_horz
= FLR_CFA_GRADTHRS_HORZ
;
1337 params
->cfa
.gradthrs_vert
= FLR_CFA_GRADTHRS_VERT
;
1338 params
->csup
.gain
= FLR_CSUP_GAIN
;
1339 params
->csup
.thres
= FLR_CSUP_THRES
;
1340 params
->csup
.hypf_en
= 0;
1341 memcpy(params
->luma
.table
, luma_enhance_table
,
1342 sizeof(params
->luma
.table
));
1343 params
->nf
.spread
= FLR_NF_STRGTH
;
1344 memcpy(params
->nf
.table
, noise_filter_table
, sizeof(params
->nf
.table
));
1345 params
->dcor
.couplet_mode_en
= 1;
1346 for (i
= 0; i
< OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS
; i
++)
1347 params
->dcor
.detect_correct
[i
] = DEF_DETECT_CORRECT_VAL
;
1348 memcpy(params
->gamma
.blue
, gamma_table
, sizeof(params
->gamma
.blue
));
1349 memcpy(params
->gamma
.green
, gamma_table
, sizeof(params
->gamma
.green
));
1350 memcpy(params
->gamma
.red
, gamma_table
, sizeof(params
->gamma
.red
));
1351 params
->wbal
.dgain
= FLR_WBAL_DGAIN
;
1352 params
->wbal
.coef0
= FLR_WBAL_COEF
;
1353 params
->wbal
.coef1
= FLR_WBAL_COEF
;
1354 params
->wbal
.coef2
= FLR_WBAL_COEF
;
1355 params
->wbal
.coef3
= FLR_WBAL_COEF
;
1356 params
->blkadj
.red
= FLR_BLKADJ_RED
;
1357 params
->blkadj
.green
= FLR_BLKADJ_GREEN
;
1358 params
->blkadj
.blue
= FLR_BLKADJ_BLUE
;
1359 params
->rgb2rgb
= flr_rgb2rgb
;
1360 params
->csc
= flr_prev_csc
;
1361 params
->yclimit
.minC
= ISPPRV_YC_MIN
;
1362 params
->yclimit
.maxC
= ISPPRV_YC_MAX
;
1363 params
->yclimit
.minY
= ISPPRV_YC_MIN
;
1364 params
->yclimit
.maxY
= ISPPRV_YC_MAX
;
1366 params
->features
= OMAP3ISP_PREV_CFA
| OMAP3ISP_PREV_DEFECT_COR
1367 | OMAP3ISP_PREV_NF
| OMAP3ISP_PREV_GAMMA
1368 | OMAP3ISP_PREV_BLKADJ
| OMAP3ISP_PREV_YC_LIMIT
1369 | OMAP3ISP_PREV_RGB2RGB
| OMAP3ISP_PREV_COLOR_CONV
1370 | OMAP3ISP_PREV_WB
| OMAP3ISP_PREV_BRIGHTNESS
1371 | OMAP3ISP_PREV_CONTRAST
;
1375 * preview_max_out_width - Handle previewer hardware ouput limitations
1376 * @isp_revision : ISP revision
1377 * returns maximum width output for current isp revision
1379 static unsigned int preview_max_out_width(struct isp_prev_device
*prev
)
1381 struct isp_device
*isp
= to_isp_device(prev
);
1383 switch (isp
->revision
) {
1384 case ISP_REVISION_1_0
:
1385 return PREV_MAX_OUT_WIDTH_REV_1
;
1387 case ISP_REVISION_2_0
:
1389 return PREV_MAX_OUT_WIDTH_REV_2
;
1391 case ISP_REVISION_15_0
:
1392 return PREV_MAX_OUT_WIDTH_REV_15
;
1396 static void preview_configure(struct isp_prev_device
*prev
)
1398 struct isp_device
*isp
= to_isp_device(prev
);
1399 const struct isp_format_info
*info
;
1400 struct v4l2_mbus_framefmt
*format
;
1401 unsigned long flags
;
1405 spin_lock_irqsave(&prev
->params
.lock
, flags
);
1406 /* Mark all active parameters we are going to touch as busy. */
1407 update
= preview_params_lock(prev
, 0, false);
1408 active
= prev
->params
.active
;
1409 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
1412 format
= &prev
->formats
[PREV_PAD_SINK
];
1413 info
= omap3isp_video_format_info(format
->code
);
1415 preview_adjust_bandwidth(prev
);
1417 preview_config_input_format(prev
, info
);
1418 preview_config_input_size(prev
, active
);
1420 if (prev
->input
== PREVIEW_INPUT_CCDC
)
1421 preview_config_inlineoffset(prev
, 0);
1423 preview_config_inlineoffset(prev
, ALIGN(format
->width
, 0x20) *
1426 preview_setup_hw(prev
, update
, active
);
1428 /* PREV_PAD_SOURCE */
1429 format
= &prev
->formats
[PREV_PAD_SOURCE
];
1431 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1432 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1433 ISPPRV_PCR_SDRPORT
);
1435 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1436 ISPPRV_PCR_SDRPORT
);
1438 if (prev
->output
& PREVIEW_OUTPUT_RESIZER
)
1439 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1440 ISPPRV_PCR_RSZPORT
);
1442 isp_reg_clr(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1443 ISPPRV_PCR_RSZPORT
);
1445 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1446 preview_config_outlineoffset(prev
,
1447 ALIGN(format
->width
, 0x10) * 2);
1449 preview_config_averager(prev
, 0);
1450 preview_config_ycpos(prev
, format
->code
);
1452 spin_lock_irqsave(&prev
->params
.lock
, flags
);
1453 preview_params_unlock(prev
, update
, false);
1454 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
1457 /* -----------------------------------------------------------------------------
1458 * Interrupt handling
1461 static void preview_enable_oneshot(struct isp_prev_device
*prev
)
1463 struct isp_device
*isp
= to_isp_device(prev
);
1465 /* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
1466 * bit is set. As the preview engine is used in single-shot mode, we
1467 * need to set PCR.SOURCE before enabling the preview engine.
1469 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
1470 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1473 isp_reg_set(isp
, OMAP3_ISP_IOMEM_PREV
, ISPPRV_PCR
,
1474 ISPPRV_PCR_EN
| ISPPRV_PCR_ONESHOT
);
1477 void omap3isp_preview_isr_frame_sync(struct isp_prev_device
*prev
)
1480 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
1481 * condition, the module was paused and now we have a buffer queued
1482 * on the output again. Restart the pipeline if running in continuous
1485 if (prev
->state
== ISP_PIPELINE_STREAM_CONTINUOUS
&&
1486 prev
->video_out
.dmaqueue_flags
& ISP_VIDEO_DMAQUEUE_QUEUED
) {
1487 preview_enable_oneshot(prev
);
1488 isp_video_dmaqueue_flags_clr(&prev
->video_out
);
1492 static void preview_isr_buffer(struct isp_prev_device
*prev
)
1494 struct isp_pipeline
*pipe
= to_isp_pipeline(&prev
->subdev
.entity
);
1495 struct isp_buffer
*buffer
;
1498 if (prev
->input
== PREVIEW_INPUT_MEMORY
) {
1499 buffer
= omap3isp_video_buffer_next(&prev
->video_in
);
1501 preview_set_inaddr(prev
, buffer
->isp_addr
);
1502 pipe
->state
|= ISP_PIPELINE_IDLE_INPUT
;
1505 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
) {
1506 buffer
= omap3isp_video_buffer_next(&prev
->video_out
);
1507 if (buffer
!= NULL
) {
1508 preview_set_outaddr(prev
, buffer
->isp_addr
);
1511 pipe
->state
|= ISP_PIPELINE_IDLE_OUTPUT
;
1514 switch (prev
->state
) {
1515 case ISP_PIPELINE_STREAM_SINGLESHOT
:
1516 if (isp_pipeline_ready(pipe
))
1517 omap3isp_pipeline_set_stream(pipe
,
1518 ISP_PIPELINE_STREAM_SINGLESHOT
);
1521 case ISP_PIPELINE_STREAM_CONTINUOUS
:
1522 /* If an underrun occurs, the video queue operation handler will
1523 * restart the preview engine. Otherwise restart it immediately.
1526 preview_enable_oneshot(prev
);
1529 case ISP_PIPELINE_STREAM_STOPPED
:
1536 * omap3isp_preview_isr - ISP preview engine interrupt handler
1538 * Manage the preview engine video buffers and configure shadowed registers.
1540 void omap3isp_preview_isr(struct isp_prev_device
*prev
)
1542 unsigned long flags
;
1546 if (omap3isp_module_sync_is_stopping(&prev
->wait
, &prev
->stopping
))
1549 spin_lock_irqsave(&prev
->params
.lock
, flags
);
1550 preview_params_switch(prev
);
1551 update
= preview_params_lock(prev
, 0, false);
1552 active
= prev
->params
.active
;
1553 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
1555 preview_setup_hw(prev
, update
, active
);
1556 preview_config_input_size(prev
, active
);
1558 if (prev
->input
== PREVIEW_INPUT_MEMORY
||
1559 prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1560 preview_isr_buffer(prev
);
1561 else if (prev
->state
== ISP_PIPELINE_STREAM_CONTINUOUS
)
1562 preview_enable_oneshot(prev
);
1564 spin_lock_irqsave(&prev
->params
.lock
, flags
);
1565 preview_params_unlock(prev
, update
, false);
1566 spin_unlock_irqrestore(&prev
->params
.lock
, flags
);
1569 /* -----------------------------------------------------------------------------
1570 * ISP video operations
1573 static int preview_video_queue(struct isp_video
*video
,
1574 struct isp_buffer
*buffer
)
1576 struct isp_prev_device
*prev
= &video
->isp
->isp_prev
;
1578 if (video
->type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
)
1579 preview_set_inaddr(prev
, buffer
->isp_addr
);
1581 if (video
->type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1582 preview_set_outaddr(prev
, buffer
->isp_addr
);
1587 static const struct isp_video_operations preview_video_ops
= {
1588 .queue
= preview_video_queue
,
1591 /* -----------------------------------------------------------------------------
1592 * V4L2 subdev operations
1596 * preview_s_ctrl - Handle set control subdev method
1597 * @ctrl: pointer to v4l2 control structure
1599 static int preview_s_ctrl(struct v4l2_ctrl
*ctrl
)
1601 struct isp_prev_device
*prev
=
1602 container_of(ctrl
->handler
, struct isp_prev_device
, ctrls
);
1605 case V4L2_CID_BRIGHTNESS
:
1606 preview_update_brightness(prev
, ctrl
->val
);
1608 case V4L2_CID_CONTRAST
:
1609 preview_update_contrast(prev
, ctrl
->val
);
1616 static const struct v4l2_ctrl_ops preview_ctrl_ops
= {
1617 .s_ctrl
= preview_s_ctrl
,
1621 * preview_ioctl - Handle preview module private ioctl's
1622 * @prev: pointer to preview context structure
1623 * @cmd: configuration command
1624 * @arg: configuration argument
1625 * return -EINVAL or zero on success
1627 static long preview_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
1629 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1632 case VIDIOC_OMAP3ISP_PRV_CFG
:
1633 return preview_config(prev
, arg
);
1636 return -ENOIOCTLCMD
;
1641 * preview_set_stream - Enable/Disable streaming on preview subdev
1642 * @sd : pointer to v4l2 subdev structure
1643 * @enable: 1 == Enable, 0 == Disable
1644 * return -EINVAL or zero on success
1646 static int preview_set_stream(struct v4l2_subdev
*sd
, int enable
)
1648 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1649 struct isp_video
*video_out
= &prev
->video_out
;
1650 struct isp_device
*isp
= to_isp_device(prev
);
1651 struct device
*dev
= to_device(prev
);
1653 if (prev
->state
== ISP_PIPELINE_STREAM_STOPPED
) {
1654 if (enable
== ISP_PIPELINE_STREAM_STOPPED
)
1657 omap3isp_subclk_enable(isp
, OMAP3_ISP_SUBCLK_PREVIEW
);
1658 preview_configure(prev
);
1659 atomic_set(&prev
->stopping
, 0);
1660 preview_print_status(prev
);
1664 case ISP_PIPELINE_STREAM_CONTINUOUS
:
1665 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1666 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1668 if (video_out
->dmaqueue_flags
& ISP_VIDEO_DMAQUEUE_QUEUED
||
1669 !(prev
->output
& PREVIEW_OUTPUT_MEMORY
))
1670 preview_enable_oneshot(prev
);
1672 isp_video_dmaqueue_flags_clr(video_out
);
1675 case ISP_PIPELINE_STREAM_SINGLESHOT
:
1676 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
1677 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_READ
);
1678 if (prev
->output
& PREVIEW_OUTPUT_MEMORY
)
1679 omap3isp_sbl_enable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1681 preview_enable_oneshot(prev
);
1684 case ISP_PIPELINE_STREAM_STOPPED
:
1685 if (omap3isp_module_sync_idle(&sd
->entity
, &prev
->wait
,
1687 dev_dbg(dev
, "%s: stop timeout.\n", sd
->name
);
1688 omap3isp_sbl_disable(isp
, OMAP3_ISP_SBL_PREVIEW_READ
);
1689 omap3isp_sbl_disable(isp
, OMAP3_ISP_SBL_PREVIEW_WRITE
);
1690 omap3isp_subclk_disable(isp
, OMAP3_ISP_SUBCLK_PREVIEW
);
1691 isp_video_dmaqueue_flags_clr(video_out
);
1695 prev
->state
= enable
;
1699 static struct v4l2_mbus_framefmt
*
1700 __preview_get_format(struct isp_prev_device
*prev
, struct v4l2_subdev_fh
*fh
,
1701 unsigned int pad
, enum v4l2_subdev_format_whence which
)
1703 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
1704 return v4l2_subdev_get_try_format(fh
, pad
);
1706 return &prev
->formats
[pad
];
1709 static struct v4l2_rect
*
1710 __preview_get_crop(struct isp_prev_device
*prev
, struct v4l2_subdev_fh
*fh
,
1711 enum v4l2_subdev_format_whence which
)
1713 if (which
== V4L2_SUBDEV_FORMAT_TRY
)
1714 return v4l2_subdev_get_try_crop(fh
, PREV_PAD_SINK
);
1719 /* previewer format descriptions */
1720 static const unsigned int preview_input_fmts
[] = {
1721 V4L2_MBUS_FMT_Y8_1X8
,
1722 V4L2_MBUS_FMT_SGRBG8_1X8
,
1723 V4L2_MBUS_FMT_SRGGB8_1X8
,
1724 V4L2_MBUS_FMT_SBGGR8_1X8
,
1725 V4L2_MBUS_FMT_SGBRG8_1X8
,
1726 V4L2_MBUS_FMT_Y10_1X10
,
1727 V4L2_MBUS_FMT_SGRBG10_1X10
,
1728 V4L2_MBUS_FMT_SRGGB10_1X10
,
1729 V4L2_MBUS_FMT_SBGGR10_1X10
,
1730 V4L2_MBUS_FMT_SGBRG10_1X10
,
1733 static const unsigned int preview_output_fmts
[] = {
1734 V4L2_MBUS_FMT_UYVY8_1X16
,
1735 V4L2_MBUS_FMT_YUYV8_1X16
,
1739 * preview_try_format - Validate a format
1740 * @prev: ISP preview engine
1741 * @fh: V4L2 subdev file handle
1743 * @fmt: format to be validated
1744 * @which: try/active format selector
1746 * Validate and adjust the given format for the given pad based on the preview
1747 * engine limits and the format and crop rectangles on other pads.
1749 static void preview_try_format(struct isp_prev_device
*prev
,
1750 struct v4l2_subdev_fh
*fh
, unsigned int pad
,
1751 struct v4l2_mbus_framefmt
*fmt
,
1752 enum v4l2_subdev_format_whence which
)
1754 enum v4l2_mbus_pixelcode pixelcode
;
1755 struct v4l2_rect
*crop
;
1760 /* When reading data from the CCDC, the input size has already
1761 * been mangled by the CCDC output pad so it can be accepted
1764 * When reading data from memory, clamp the requested width and
1765 * height. The TRM doesn't specify a minimum input height, make
1766 * sure we got enough lines to enable the noise filter and color
1767 * filter array interpolation.
1769 if (prev
->input
== PREVIEW_INPUT_MEMORY
) {
1770 fmt
->width
= clamp_t(u32
, fmt
->width
, PREV_MIN_IN_WIDTH
,
1771 preview_max_out_width(prev
));
1772 fmt
->height
= clamp_t(u32
, fmt
->height
,
1774 PREV_MAX_IN_HEIGHT
);
1777 fmt
->colorspace
= V4L2_COLORSPACE_SRGB
;
1779 for (i
= 0; i
< ARRAY_SIZE(preview_input_fmts
); i
++) {
1780 if (fmt
->code
== preview_input_fmts
[i
])
1784 /* If not found, use SGRBG10 as default */
1785 if (i
>= ARRAY_SIZE(preview_input_fmts
))
1786 fmt
->code
= V4L2_MBUS_FMT_SGRBG10_1X10
;
1789 case PREV_PAD_SOURCE
:
1790 pixelcode
= fmt
->code
;
1791 *fmt
= *__preview_get_format(prev
, fh
, PREV_PAD_SINK
, which
);
1793 switch (pixelcode
) {
1794 case V4L2_MBUS_FMT_YUYV8_1X16
:
1795 case V4L2_MBUS_FMT_UYVY8_1X16
:
1796 fmt
->code
= pixelcode
;
1800 fmt
->code
= V4L2_MBUS_FMT_YUYV8_1X16
;
1804 /* The preview module output size is configurable through the
1805 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). This
1806 * is not supported yet, hardcode the output size to the crop
1809 crop
= __preview_get_crop(prev
, fh
, which
);
1810 fmt
->width
= crop
->width
;
1811 fmt
->height
= crop
->height
;
1813 fmt
->colorspace
= V4L2_COLORSPACE_JPEG
;
1817 fmt
->field
= V4L2_FIELD_NONE
;
1821 * preview_try_crop - Validate a crop rectangle
1822 * @prev: ISP preview engine
1823 * @sink: format on the sink pad
1824 * @crop: crop rectangle to be validated
1826 * The preview engine crops lines and columns for its internal operation,
1827 * depending on which filters are enabled. Enforce minimum crop margins to
1828 * handle that transparently for userspace.
1830 * See the explanation at the PREV_MARGIN_* definitions for more details.
1832 static void preview_try_crop(struct isp_prev_device
*prev
,
1833 const struct v4l2_mbus_framefmt
*sink
,
1834 struct v4l2_rect
*crop
)
1836 unsigned int left
= PREV_MARGIN_LEFT
;
1837 unsigned int right
= sink
->width
- PREV_MARGIN_RIGHT
;
1838 unsigned int top
= PREV_MARGIN_TOP
;
1839 unsigned int bottom
= sink
->height
- PREV_MARGIN_BOTTOM
;
1841 /* When processing data on-the-fly from the CCDC, at least 2 pixels must
1842 * be cropped from the left and right sides of the image. As we don't
1843 * know which filters will be enabled, increase the left and right
1846 if (prev
->input
== PREVIEW_INPUT_CCDC
) {
1851 /* The CFA filter crops 4 lines and 4 columns in Bayer mode, and 2 lines
1852 * and no columns in other modes. Increase the margins based on the sink
1855 if (sink
->code
!= V4L2_MBUS_FMT_Y8_1X8
&&
1856 sink
->code
!= V4L2_MBUS_FMT_Y10_1X10
) {
1863 /* Restrict left/top to even values to keep the Bayer pattern. */
1867 crop
->left
= clamp_t(u32
, crop
->left
, left
, right
- PREV_MIN_OUT_WIDTH
);
1868 crop
->top
= clamp_t(u32
, crop
->top
, top
, bottom
- PREV_MIN_OUT_HEIGHT
);
1869 crop
->width
= clamp_t(u32
, crop
->width
, PREV_MIN_OUT_WIDTH
,
1870 right
- crop
->left
);
1871 crop
->height
= clamp_t(u32
, crop
->height
, PREV_MIN_OUT_HEIGHT
,
1872 bottom
- crop
->top
);
1876 * preview_enum_mbus_code - Handle pixel format enumeration
1877 * @sd : pointer to v4l2 subdev structure
1878 * @fh : V4L2 subdev file handle
1879 * @code : pointer to v4l2_subdev_mbus_code_enum structure
1880 * return -EINVAL or zero on success
1882 static int preview_enum_mbus_code(struct v4l2_subdev
*sd
,
1883 struct v4l2_subdev_fh
*fh
,
1884 struct v4l2_subdev_mbus_code_enum
*code
)
1886 switch (code
->pad
) {
1888 if (code
->index
>= ARRAY_SIZE(preview_input_fmts
))
1891 code
->code
= preview_input_fmts
[code
->index
];
1893 case PREV_PAD_SOURCE
:
1894 if (code
->index
>= ARRAY_SIZE(preview_output_fmts
))
1897 code
->code
= preview_output_fmts
[code
->index
];
1906 static int preview_enum_frame_size(struct v4l2_subdev
*sd
,
1907 struct v4l2_subdev_fh
*fh
,
1908 struct v4l2_subdev_frame_size_enum
*fse
)
1910 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1911 struct v4l2_mbus_framefmt format
;
1913 if (fse
->index
!= 0)
1916 format
.code
= fse
->code
;
1919 preview_try_format(prev
, fh
, fse
->pad
, &format
, V4L2_SUBDEV_FORMAT_TRY
);
1920 fse
->min_width
= format
.width
;
1921 fse
->min_height
= format
.height
;
1923 if (format
.code
!= fse
->code
)
1926 format
.code
= fse
->code
;
1929 preview_try_format(prev
, fh
, fse
->pad
, &format
, V4L2_SUBDEV_FORMAT_TRY
);
1930 fse
->max_width
= format
.width
;
1931 fse
->max_height
= format
.height
;
1937 * preview_get_selection - Retrieve a selection rectangle on a pad
1938 * @sd: ISP preview V4L2 subdevice
1939 * @fh: V4L2 subdev file handle
1940 * @sel: Selection rectangle
1942 * The only supported rectangles are the crop rectangles on the sink pad.
1944 * Return 0 on success or a negative error code otherwise.
1946 static int preview_get_selection(struct v4l2_subdev
*sd
,
1947 struct v4l2_subdev_fh
*fh
,
1948 struct v4l2_subdev_selection
*sel
)
1950 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1951 struct v4l2_mbus_framefmt
*format
;
1953 if (sel
->pad
!= PREV_PAD_SINK
)
1956 switch (sel
->target
) {
1957 case V4L2_SEL_TGT_CROP_BOUNDS
:
1960 sel
->r
.width
= INT_MAX
;
1961 sel
->r
.height
= INT_MAX
;
1963 format
= __preview_get_format(prev
, fh
, PREV_PAD_SINK
,
1965 preview_try_crop(prev
, format
, &sel
->r
);
1968 case V4L2_SEL_TGT_CROP
:
1969 sel
->r
= *__preview_get_crop(prev
, fh
, sel
->which
);
1980 * preview_set_selection - Set a selection rectangle on a pad
1981 * @sd: ISP preview V4L2 subdevice
1982 * @fh: V4L2 subdev file handle
1983 * @sel: Selection rectangle
1985 * The only supported rectangle is the actual crop rectangle on the sink pad.
1987 * Return 0 on success or a negative error code otherwise.
1989 static int preview_set_selection(struct v4l2_subdev
*sd
,
1990 struct v4l2_subdev_fh
*fh
,
1991 struct v4l2_subdev_selection
*sel
)
1993 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
1994 struct v4l2_mbus_framefmt
*format
;
1996 if (sel
->target
!= V4L2_SEL_TGT_CROP
||
1997 sel
->pad
!= PREV_PAD_SINK
)
2000 /* The crop rectangle can't be changed while streaming. */
2001 if (prev
->state
!= ISP_PIPELINE_STREAM_STOPPED
)
2004 /* Modifying the crop rectangle always changes the format on the source
2005 * pad. If the KEEP_CONFIG flag is set, just return the current crop
2008 if (sel
->flags
& V4L2_SEL_FLAG_KEEP_CONFIG
) {
2009 sel
->r
= *__preview_get_crop(prev
, fh
, sel
->which
);
2013 format
= __preview_get_format(prev
, fh
, PREV_PAD_SINK
, sel
->which
);
2014 preview_try_crop(prev
, format
, &sel
->r
);
2015 *__preview_get_crop(prev
, fh
, sel
->which
) = sel
->r
;
2017 /* Update the source format. */
2018 format
= __preview_get_format(prev
, fh
, PREV_PAD_SOURCE
, sel
->which
);
2019 preview_try_format(prev
, fh
, PREV_PAD_SOURCE
, format
, sel
->which
);
2025 * preview_get_format - Handle get format by pads subdev method
2026 * @sd : pointer to v4l2 subdev structure
2027 * @fh : V4L2 subdev file handle
2028 * @fmt: pointer to v4l2 subdev format structure
2029 * return -EINVAL or zero on success
2031 static int preview_get_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
2032 struct v4l2_subdev_format
*fmt
)
2034 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
2035 struct v4l2_mbus_framefmt
*format
;
2037 format
= __preview_get_format(prev
, fh
, fmt
->pad
, fmt
->which
);
2041 fmt
->format
= *format
;
2046 * preview_set_format - Handle set format by pads subdev method
2047 * @sd : pointer to v4l2 subdev structure
2048 * @fh : V4L2 subdev file handle
2049 * @fmt: pointer to v4l2 subdev format structure
2050 * return -EINVAL or zero on success
2052 static int preview_set_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
2053 struct v4l2_subdev_format
*fmt
)
2055 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
2056 struct v4l2_mbus_framefmt
*format
;
2057 struct v4l2_rect
*crop
;
2059 format
= __preview_get_format(prev
, fh
, fmt
->pad
, fmt
->which
);
2063 preview_try_format(prev
, fh
, fmt
->pad
, &fmt
->format
, fmt
->which
);
2064 *format
= fmt
->format
;
2066 /* Propagate the format from sink to source */
2067 if (fmt
->pad
== PREV_PAD_SINK
) {
2068 /* Reset the crop rectangle. */
2069 crop
= __preview_get_crop(prev
, fh
, fmt
->which
);
2072 crop
->width
= fmt
->format
.width
;
2073 crop
->height
= fmt
->format
.height
;
2075 preview_try_crop(prev
, &fmt
->format
, crop
);
2077 /* Update the source format. */
2078 format
= __preview_get_format(prev
, fh
, PREV_PAD_SOURCE
,
2080 preview_try_format(prev
, fh
, PREV_PAD_SOURCE
, format
,
2088 * preview_init_formats - Initialize formats on all pads
2089 * @sd: ISP preview V4L2 subdevice
2090 * @fh: V4L2 subdev file handle
2092 * Initialize all pad formats with default values. If fh is not NULL, try
2093 * formats are initialized on the file handle. Otherwise active formats are
2094 * initialized on the device.
2096 static int preview_init_formats(struct v4l2_subdev
*sd
,
2097 struct v4l2_subdev_fh
*fh
)
2099 struct v4l2_subdev_format format
;
2101 memset(&format
, 0, sizeof(format
));
2102 format
.pad
= PREV_PAD_SINK
;
2103 format
.which
= fh
? V4L2_SUBDEV_FORMAT_TRY
: V4L2_SUBDEV_FORMAT_ACTIVE
;
2104 format
.format
.code
= V4L2_MBUS_FMT_SGRBG10_1X10
;
2105 format
.format
.width
= 4096;
2106 format
.format
.height
= 4096;
2107 preview_set_format(sd
, fh
, &format
);
2112 /* subdev core operations */
2113 static const struct v4l2_subdev_core_ops preview_v4l2_core_ops
= {
2114 .ioctl
= preview_ioctl
,
2117 /* subdev video operations */
2118 static const struct v4l2_subdev_video_ops preview_v4l2_video_ops
= {
2119 .s_stream
= preview_set_stream
,
2122 /* subdev pad operations */
2123 static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops
= {
2124 .enum_mbus_code
= preview_enum_mbus_code
,
2125 .enum_frame_size
= preview_enum_frame_size
,
2126 .get_fmt
= preview_get_format
,
2127 .set_fmt
= preview_set_format
,
2128 .get_selection
= preview_get_selection
,
2129 .set_selection
= preview_set_selection
,
2132 /* subdev operations */
2133 static const struct v4l2_subdev_ops preview_v4l2_ops
= {
2134 .core
= &preview_v4l2_core_ops
,
2135 .video
= &preview_v4l2_video_ops
,
2136 .pad
= &preview_v4l2_pad_ops
,
2139 /* subdev internal operations */
2140 static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops
= {
2141 .open
= preview_init_formats
,
2144 /* -----------------------------------------------------------------------------
2145 * Media entity operations
2149 * preview_link_setup - Setup previewer connections.
2150 * @entity : Pointer to media entity structure
2151 * @local : Pointer to local pad array
2152 * @remote : Pointer to remote pad array
2153 * @flags : Link flags
2154 * return -EINVAL or zero on success
2156 static int preview_link_setup(struct media_entity
*entity
,
2157 const struct media_pad
*local
,
2158 const struct media_pad
*remote
, u32 flags
)
2160 struct v4l2_subdev
*sd
= media_entity_to_v4l2_subdev(entity
);
2161 struct isp_prev_device
*prev
= v4l2_get_subdevdata(sd
);
2163 switch (local
->index
| media_entity_type(remote
->entity
)) {
2164 case PREV_PAD_SINK
| MEDIA_ENT_T_DEVNODE
:
2165 /* read from memory */
2166 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2167 if (prev
->input
== PREVIEW_INPUT_CCDC
)
2169 prev
->input
= PREVIEW_INPUT_MEMORY
;
2171 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
2172 prev
->input
= PREVIEW_INPUT_NONE
;
2176 case PREV_PAD_SINK
| MEDIA_ENT_T_V4L2_SUBDEV
:
2177 /* read from ccdc */
2178 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2179 if (prev
->input
== PREVIEW_INPUT_MEMORY
)
2181 prev
->input
= PREVIEW_INPUT_CCDC
;
2183 if (prev
->input
== PREVIEW_INPUT_CCDC
)
2184 prev
->input
= PREVIEW_INPUT_NONE
;
2189 * The ISP core doesn't support pipelines with multiple video outputs.
2190 * Revisit this when it will be implemented, and return -EBUSY for now.
2193 case PREV_PAD_SOURCE
| MEDIA_ENT_T_DEVNODE
:
2194 /* write to memory */
2195 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2196 if (prev
->output
& ~PREVIEW_OUTPUT_MEMORY
)
2198 prev
->output
|= PREVIEW_OUTPUT_MEMORY
;
2200 prev
->output
&= ~PREVIEW_OUTPUT_MEMORY
;
2204 case PREV_PAD_SOURCE
| MEDIA_ENT_T_V4L2_SUBDEV
:
2205 /* write to resizer */
2206 if (flags
& MEDIA_LNK_FL_ENABLED
) {
2207 if (prev
->output
& ~PREVIEW_OUTPUT_RESIZER
)
2209 prev
->output
|= PREVIEW_OUTPUT_RESIZER
;
2211 prev
->output
&= ~PREVIEW_OUTPUT_RESIZER
;
2222 /* media operations */
2223 static const struct media_entity_operations preview_media_ops
= {
2224 .link_setup
= preview_link_setup
,
2225 .link_validate
= v4l2_subdev_link_validate
,
2228 void omap3isp_preview_unregister_entities(struct isp_prev_device
*prev
)
2230 v4l2_device_unregister_subdev(&prev
->subdev
);
2231 omap3isp_video_unregister(&prev
->video_in
);
2232 omap3isp_video_unregister(&prev
->video_out
);
2235 int omap3isp_preview_register_entities(struct isp_prev_device
*prev
,
2236 struct v4l2_device
*vdev
)
2240 /* Register the subdev and video nodes. */
2241 ret
= v4l2_device_register_subdev(vdev
, &prev
->subdev
);
2245 ret
= omap3isp_video_register(&prev
->video_in
, vdev
);
2249 ret
= omap3isp_video_register(&prev
->video_out
, vdev
);
2256 omap3isp_preview_unregister_entities(prev
);
2260 /* -----------------------------------------------------------------------------
2261 * ISP previewer initialisation and cleanup
2265 * preview_init_entities - Initialize subdev and media entity.
2266 * @prev : Pointer to preview structure
2267 * return -ENOMEM or zero on success
2269 static int preview_init_entities(struct isp_prev_device
*prev
)
2271 struct v4l2_subdev
*sd
= &prev
->subdev
;
2272 struct media_pad
*pads
= prev
->pads
;
2273 struct media_entity
*me
= &sd
->entity
;
2276 prev
->input
= PREVIEW_INPUT_NONE
;
2278 v4l2_subdev_init(sd
, &preview_v4l2_ops
);
2279 sd
->internal_ops
= &preview_v4l2_internal_ops
;
2280 strlcpy(sd
->name
, "OMAP3 ISP preview", sizeof(sd
->name
));
2281 sd
->grp_id
= 1 << 16; /* group ID for isp subdevs */
2282 v4l2_set_subdevdata(sd
, prev
);
2283 sd
->flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
2285 v4l2_ctrl_handler_init(&prev
->ctrls
, 2);
2286 v4l2_ctrl_new_std(&prev
->ctrls
, &preview_ctrl_ops
, V4L2_CID_BRIGHTNESS
,
2287 ISPPRV_BRIGHT_LOW
, ISPPRV_BRIGHT_HIGH
,
2288 ISPPRV_BRIGHT_STEP
, ISPPRV_BRIGHT_DEF
);
2289 v4l2_ctrl_new_std(&prev
->ctrls
, &preview_ctrl_ops
, V4L2_CID_CONTRAST
,
2290 ISPPRV_CONTRAST_LOW
, ISPPRV_CONTRAST_HIGH
,
2291 ISPPRV_CONTRAST_STEP
, ISPPRV_CONTRAST_DEF
);
2292 v4l2_ctrl_handler_setup(&prev
->ctrls
);
2293 sd
->ctrl_handler
= &prev
->ctrls
;
2295 pads
[PREV_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
2296 pads
[PREV_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
2298 me
->ops
= &preview_media_ops
;
2299 ret
= media_entity_init(me
, PREV_PADS_NUM
, pads
, 0);
2303 preview_init_formats(sd
, NULL
);
2305 /* According to the OMAP34xx TRM, video buffers need to be aligned on a
2306 * 32 bytes boundary. However, an undocumented hardware bug requires a
2307 * 64 bytes boundary at the preview engine input.
2309 prev
->video_in
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
2310 prev
->video_in
.ops
= &preview_video_ops
;
2311 prev
->video_in
.isp
= to_isp_device(prev
);
2312 prev
->video_in
.capture_mem
= PAGE_ALIGN(4096 * 4096) * 2 * 3;
2313 prev
->video_in
.bpl_alignment
= 64;
2314 prev
->video_out
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2315 prev
->video_out
.ops
= &preview_video_ops
;
2316 prev
->video_out
.isp
= to_isp_device(prev
);
2317 prev
->video_out
.capture_mem
= PAGE_ALIGN(4096 * 4096) * 2 * 3;
2318 prev
->video_out
.bpl_alignment
= 32;
2320 ret
= omap3isp_video_init(&prev
->video_in
, "preview");
2322 goto error_video_in
;
2324 ret
= omap3isp_video_init(&prev
->video_out
, "preview");
2326 goto error_video_out
;
2328 /* Connect the video nodes to the previewer subdev. */
2329 ret
= media_entity_create_link(&prev
->video_in
.video
.entity
, 0,
2330 &prev
->subdev
.entity
, PREV_PAD_SINK
, 0);
2334 ret
= media_entity_create_link(&prev
->subdev
.entity
, PREV_PAD_SOURCE
,
2335 &prev
->video_out
.video
.entity
, 0, 0);
2342 omap3isp_video_cleanup(&prev
->video_out
);
2344 omap3isp_video_cleanup(&prev
->video_in
);
2346 media_entity_cleanup(&prev
->subdev
.entity
);
2351 * omap3isp_preview_init - Previewer initialization.
2352 * @dev : Pointer to ISP device
2353 * return -ENOMEM or zero on success
2355 int omap3isp_preview_init(struct isp_device
*isp
)
2357 struct isp_prev_device
*prev
= &isp
->isp_prev
;
2359 init_waitqueue_head(&prev
->wait
);
2361 preview_init_params(prev
);
2363 return preview_init_entities(prev
);
2366 void omap3isp_preview_cleanup(struct isp_device
*isp
)
2368 struct isp_prev_device
*prev
= &isp
->isp_prev
;
2370 v4l2_ctrl_handler_free(&prev
->ctrls
);
2371 omap3isp_video_cleanup(&prev
->video_in
);
2372 omap3isp_video_cleanup(&prev
->video_out
);
2373 media_entity_cleanup(&prev
->subdev
.entity
);