2 * Copyright (C) 2012 Texas Instruments Inc
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
22 #include <linux/delay.h>
23 #include "dm365_isif.h"
24 #include "vpfe_mc_capture.h"
26 #define MAX_WIDTH 4096
27 #define MAX_HEIGHT 4096
29 static const unsigned int isif_fmts
[] = {
30 MEDIA_BUS_FMT_YUYV8_2X8
,
31 MEDIA_BUS_FMT_UYVY8_2X8
,
32 MEDIA_BUS_FMT_YUYV8_1X16
,
33 MEDIA_BUS_FMT_YUYV10_1X20
,
34 MEDIA_BUS_FMT_SGRBG12_1X12
,
35 MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8
,
36 MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8
,
39 #define ISIF_COLPTN_R_Ye 0x0
40 #define ISIF_COLPTN_Gr_Cy 0x1
41 #define ISIF_COLPTN_Gb_G 0x2
42 #define ISIF_COLPTN_B_Mg 0x3
44 #define ISIF_CCOLP_CP01_0 0
45 #define ISIF_CCOLP_CP03_2 2
46 #define ISIF_CCOLP_CP05_4 4
47 #define ISIF_CCOLP_CP07_6 6
48 #define ISIF_CCOLP_CP11_0 8
49 #define ISIF_CCOLP_CP13_2 10
50 #define ISIF_CCOLP_CP15_4 12
51 #define ISIF_CCOLP_CP17_6 14
53 static const u32 isif_sgrbg_pattern
=
54 ISIF_COLPTN_Gr_Cy
<< ISIF_CCOLP_CP01_0
|
55 ISIF_COLPTN_R_Ye
<< ISIF_CCOLP_CP03_2
|
56 ISIF_COLPTN_B_Mg
<< ISIF_CCOLP_CP05_4
|
57 ISIF_COLPTN_Gb_G
<< ISIF_CCOLP_CP07_6
|
58 ISIF_COLPTN_Gr_Cy
<< ISIF_CCOLP_CP11_0
|
59 ISIF_COLPTN_R_Ye
<< ISIF_CCOLP_CP13_2
|
60 ISIF_COLPTN_B_Mg
<< ISIF_CCOLP_CP15_4
|
61 ISIF_COLPTN_Gb_G
<< ISIF_CCOLP_CP17_6
;
63 static const u32 isif_srggb_pattern
=
64 ISIF_COLPTN_R_Ye
<< ISIF_CCOLP_CP01_0
|
65 ISIF_COLPTN_Gr_Cy
<< ISIF_CCOLP_CP03_2
|
66 ISIF_COLPTN_Gb_G
<< ISIF_CCOLP_CP05_4
|
67 ISIF_COLPTN_B_Mg
<< ISIF_CCOLP_CP07_6
|
68 ISIF_COLPTN_R_Ye
<< ISIF_CCOLP_CP11_0
|
69 ISIF_COLPTN_Gr_Cy
<< ISIF_CCOLP_CP13_2
|
70 ISIF_COLPTN_Gb_G
<< ISIF_CCOLP_CP15_4
|
71 ISIF_COLPTN_B_Mg
<< ISIF_CCOLP_CP17_6
;
73 static inline u32
isif_read(void __iomem
*base_addr
, u32 offset
)
75 return readl(base_addr
+ offset
);
78 static inline void isif_write(void __iomem
*base_addr
, u32 val
, u32 offset
)
80 writel(val
, base_addr
+ offset
);
83 static inline u32
isif_merge(void __iomem
*base_addr
, u32 mask
, u32 val
,
86 u32 new_val
= (isif_read(base_addr
, offset
) & ~mask
) | (val
& mask
);
88 isif_write(base_addr
, new_val
, offset
);
93 static void isif_enable_output_to_sdram(struct vpfe_isif_device
*isif
, int en
)
95 isif_merge(isif
->isif_cfg
.base_addr
, ISIF_SYNCEN_WEN_MASK
,
96 en
<< ISIF_SYNCEN_WEN_SHIFT
, SYNCEN
);
100 isif_regw_lin_tbl(struct vpfe_isif_device
*isif
, u32 val
, u32 offset
, int i
)
103 writel(val
, isif
->isif_cfg
.linear_tbl0_addr
+ offset
);
105 writel(val
, isif
->isif_cfg
.linear_tbl1_addr
+ offset
);
108 static void isif_disable_all_modules(struct vpfe_isif_device
*isif
)
111 isif_write(isif
->isif_cfg
.base_addr
, 0, CLAMPCFG
);
113 isif_write(isif
->isif_cfg
.base_addr
, 0, DFCCTL
);
115 isif_write(isif
->isif_cfg
.base_addr
, 0, CSCCTL
);
116 /* disable linearization */
117 isif_write(isif
->isif_cfg
.base_addr
, 0, LINCFG0
);
120 static void isif_enable(struct vpfe_isif_device
*isif
, int en
)
123 /* Before disable isif, disable all ISIF modules */
124 isif_disable_all_modules(isif
);
127 * wait for next VD. Assume lowest scan rate is 12 Hz. So
128 * 100 msec delay is good enough
131 isif_merge(isif
->isif_cfg
.base_addr
, ISIF_SYNCEN_VDHDEN_MASK
,
136 * ISIF helper functions
139 #define DM365_ISIF_MDFS_OFFSET 15
140 #define DM365_ISIF_MDFS_MASK 0x1
142 /* get field id in isif hardware */
143 enum v4l2_field
vpfe_isif_get_fid(struct vpfe_device
*vpfe_dev
)
145 struct vpfe_isif_device
*isif
= &vpfe_dev
->vpfe_isif
;
148 field_status
= isif_read(isif
->isif_cfg
.base_addr
, MODESET
);
149 field_status
= (field_status
>> DM365_ISIF_MDFS_OFFSET
) &
150 DM365_ISIF_MDFS_MASK
;
155 isif_set_pixel_format(struct vpfe_isif_device
*isif
, unsigned int pixfmt
)
157 if (isif
->formats
[ISIF_PAD_SINK
].code
== MEDIA_BUS_FMT_SGRBG12_1X12
) {
158 if (pixfmt
== V4L2_PIX_FMT_SBGGR16
)
159 isif
->isif_cfg
.data_pack
= ISIF_PACK_16BIT
;
160 else if ((pixfmt
== V4L2_PIX_FMT_SGRBG10DPCM8
) ||
161 (pixfmt
== V4L2_PIX_FMT_SGRBG10ALAW8
))
162 isif
->isif_cfg
.data_pack
= ISIF_PACK_8BIT
;
166 isif
->isif_cfg
.bayer
.pix_fmt
= ISIF_PIXFMT_RAW
;
167 isif
->isif_cfg
.bayer
.v4l2_pix_fmt
= pixfmt
;
169 if (pixfmt
== V4L2_PIX_FMT_YUYV
)
170 isif
->isif_cfg
.ycbcr
.pix_order
= ISIF_PIXORDER_YCBYCR
;
171 else if (pixfmt
== V4L2_PIX_FMT_UYVY
)
172 isif
->isif_cfg
.ycbcr
.pix_order
= ISIF_PIXORDER_CBYCRY
;
176 isif
->isif_cfg
.data_pack
= ISIF_PACK_8BIT
;
177 isif
->isif_cfg
.ycbcr
.v4l2_pix_fmt
= pixfmt
;
184 isif_set_frame_format(struct vpfe_isif_device
*isif
,
185 enum isif_frmfmt frm_fmt
)
187 if (isif
->formats
[ISIF_PAD_SINK
].code
== MEDIA_BUS_FMT_SGRBG12_1X12
)
188 isif
->isif_cfg
.bayer
.frm_fmt
= frm_fmt
;
190 isif
->isif_cfg
.ycbcr
.frm_fmt
= frm_fmt
;
195 static int isif_set_image_window(struct vpfe_isif_device
*isif
)
197 struct v4l2_rect
*win
= &isif
->crop
;
199 if (isif
->formats
[ISIF_PAD_SINK
].code
== MEDIA_BUS_FMT_SGRBG12_1X12
) {
200 isif
->isif_cfg
.bayer
.win
.top
= win
->top
;
201 isif
->isif_cfg
.bayer
.win
.left
= win
->left
;
202 isif
->isif_cfg
.bayer
.win
.width
= win
->width
;
203 isif
->isif_cfg
.bayer
.win
.height
= win
->height
;
206 isif
->isif_cfg
.ycbcr
.win
.top
= win
->top
;
207 isif
->isif_cfg
.ycbcr
.win
.left
= win
->left
;
208 isif
->isif_cfg
.ycbcr
.win
.width
= win
->width
;
209 isif
->isif_cfg
.ycbcr
.win
.height
= win
->height
;
215 isif_set_buftype(struct vpfe_isif_device
*isif
, enum isif_buftype buf_type
)
217 if (isif
->formats
[ISIF_PAD_SINK
].code
== MEDIA_BUS_FMT_SGRBG12_1X12
)
218 isif
->isif_cfg
.bayer
.buf_type
= buf_type
;
220 isif
->isif_cfg
.ycbcr
.buf_type
= buf_type
;
225 /* configure format in isif hardware */
227 isif_config_format(struct vpfe_device
*vpfe_dev
, unsigned int pad
)
229 struct vpfe_isif_device
*vpfe_isif
= &vpfe_dev
->vpfe_isif
;
230 enum isif_frmfmt frm_fmt
= ISIF_FRMFMT_INTERLACED
;
231 struct v4l2_pix_format format
;
234 v4l2_fill_pix_format(&format
, &vpfe_dev
->vpfe_isif
.formats
[pad
]);
235 mbus_to_pix(&vpfe_dev
->vpfe_isif
.formats
[pad
], &format
);
237 if (isif_set_pixel_format(vpfe_isif
, format
.pixelformat
) < 0) {
238 v4l2_err(&vpfe_dev
->v4l2_dev
,
239 "Failed to set pixel format in isif\n");
243 /* call for s_crop will override these values */
244 vpfe_isif
->crop
.left
= 0;
245 vpfe_isif
->crop
.top
= 0;
246 vpfe_isif
->crop
.width
= format
.width
;
247 vpfe_isif
->crop
.height
= format
.height
;
249 /* configure the image window */
250 isif_set_image_window(vpfe_isif
);
252 switch (vpfe_dev
->vpfe_isif
.formats
[pad
].field
) {
253 case V4L2_FIELD_INTERLACED
:
254 /* do nothing, since it is default */
255 ret
= isif_set_buftype(vpfe_isif
, ISIF_BUFTYPE_FLD_INTERLEAVED
);
258 case V4L2_FIELD_NONE
:
259 frm_fmt
= ISIF_FRMFMT_PROGRESSIVE
;
260 /* buffer type only applicable for interlaced scan */
263 case V4L2_FIELD_SEQ_TB
:
264 ret
= isif_set_buftype(vpfe_isif
, ISIF_BUFTYPE_FLD_SEPARATED
);
271 /* set the frame format */
273 ret
= isif_set_frame_format(vpfe_isif
, frm_fmt
);
279 * isif_try_format() - Try video format on a pad
280 * @isif: VPFE isif device
281 * @fh: V4L2 subdev file handle
282 * @fmt: pointer to v4l2 subdev format structure
285 isif_try_format(struct vpfe_isif_device
*isif
, struct v4l2_subdev_fh
*fh
,
286 struct v4l2_subdev_format
*fmt
)
288 unsigned int width
= fmt
->format
.width
;
289 unsigned int height
= fmt
->format
.height
;
292 for (i
= 0; i
< ARRAY_SIZE(isif_fmts
); i
++) {
293 if (fmt
->format
.code
== isif_fmts
[i
])
297 /* If not found, use YUYV8_2x8 as default */
298 if (i
>= ARRAY_SIZE(isif_fmts
))
299 fmt
->format
.code
= MEDIA_BUS_FMT_YUYV8_2X8
;
301 /* Clamp the size. */
302 fmt
->format
.width
= clamp_t(u32
, width
, 32, MAX_WIDTH
);
303 fmt
->format
.height
= clamp_t(u32
, height
, 32, MAX_HEIGHT
);
305 /* The data formatter truncates the number of horizontal output
306 * pixels to a multiple of 16. To avoid clipping data, allow
307 * callers to request an output size bigger than the input size
308 * up to the nearest multiple of 16.
310 if (fmt
->pad
== ISIF_PAD_SOURCE
)
311 fmt
->format
.width
&= ~15;
315 * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr
316 * @isif: Pointer to isif subdevice.
318 void vpfe_isif_buffer_isr(struct vpfe_isif_device
*isif
)
320 struct vpfe_device
*vpfe_dev
= to_vpfe_device(isif
);
321 struct vpfe_video_device
*video
= &isif
->video_out
;
322 enum v4l2_field field
;
328 field
= video
->fmt
.fmt
.pix
.field
;
330 if (field
== V4L2_FIELD_NONE
) {
331 /* handle progressive frame capture */
332 if (video
->cur_frm
!= video
->next_frm
)
333 vpfe_video_process_buffer_complete(video
);
337 /* interlaced or TB capture check which field we
340 fid
= vpfe_isif_get_fid(vpfe_dev
);
342 /* switch the software maintained field id */
343 video
->field_id
^= 1;
344 if (fid
== video
->field_id
) {
345 /* we are in-sync here,continue */
348 * One frame is just being captured. If the
349 * next frame is available, release the current
352 if (video
->cur_frm
!= video
->next_frm
)
353 vpfe_video_process_buffer_complete(video
);
355 * based on whether the two fields are stored
356 * interleavely or separately in memory,
357 * reconfigure the ISIF memory address
359 if (field
== V4L2_FIELD_SEQ_TB
)
360 vpfe_video_schedule_bottom_field(video
);
364 * if one field is just being captured configure
365 * the next frame get the next frame from the
366 * empty queue if no frame is available hold on
367 * to the current buffer
369 spin_lock(&video
->dma_queue_lock
);
370 if (!list_empty(&video
->dma_queue
) &&
371 video
->cur_frm
== video
->next_frm
)
372 vpfe_video_schedule_next_buffer(video
);
373 spin_unlock(&video
->dma_queue_lock
);
374 } else if (fid
== 0) {
376 * out of sync. Recover from any hardware out-of-sync.
377 * May loose one frame
379 video
->field_id
= fid
;
384 * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr
385 * @isif: Pointer to isif subdevice.
387 void vpfe_isif_vidint1_isr(struct vpfe_isif_device
*isif
)
389 struct vpfe_video_device
*video
= &isif
->video_out
;
394 spin_lock(&video
->dma_queue_lock
);
395 if (video
->fmt
.fmt
.pix
.field
== V4L2_FIELD_NONE
&&
396 !list_empty(&video
->dma_queue
) && video
->cur_frm
== video
->next_frm
)
397 vpfe_video_schedule_next_buffer(video
);
399 spin_unlock(&video
->dma_queue_lock
);
403 * VPFE video operations
406 static int isif_video_queue(struct vpfe_device
*vpfe_dev
, unsigned long addr
)
408 struct vpfe_isif_device
*isif
= &vpfe_dev
->vpfe_isif
;
410 isif_write(isif
->isif_cfg
.base_addr
, (addr
>> 21) &
411 ISIF_CADU_BITS
, CADU
);
412 isif_write(isif
->isif_cfg
.base_addr
, (addr
>> 5) &
413 ISIF_CADL_BITS
, CADL
);
418 static const struct vpfe_video_operations isif_video_ops
= {
419 .queue
= isif_video_queue
,
423 * V4L2 subdev operations
426 /* Parameter operations */
427 static int isif_get_params(struct v4l2_subdev
*sd
, void *params
)
429 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
431 /* only raw module parameters can be set through the IOCTL */
432 if (isif
->formats
[ISIF_PAD_SINK
].code
!= MEDIA_BUS_FMT_SGRBG12_1X12
)
434 memcpy(params
, &isif
->isif_cfg
.bayer
.config_params
,
435 sizeof(isif
->isif_cfg
.bayer
.config_params
));
439 static int isif_validate_df_csc_params(struct vpfe_isif_df_csc
*df_csc
)
441 struct vpfe_isif_color_space_conv
*csc
;
445 if (!df_csc
->df_or_csc
) {
446 /* csc configuration */
449 for (i
= 0; i
< VPFE_ISIF_CSC_NUM_COEFF
; i
++)
450 if (csc
->coeff
[i
].integer
>
451 ISIF_CSC_COEF_INTEG_MASK
||
452 csc
->coeff
[i
].decimal
>
453 ISIF_CSC_COEF_DECIMAL_MASK
) {
454 pr_err("Invalid CSC coefficients\n");
459 if (df_csc
->start_pix
> ISIF_DF_CSC_SPH_MASK
) {
460 pr_err("Invalid df_csc start pix value\n");
464 if (df_csc
->num_pixels
> ISIF_DF_NUMPIX
) {
465 pr_err("Invalid df_csc num pixels value\n");
469 if (df_csc
->start_line
> ISIF_DF_CSC_LNH_MASK
) {
470 pr_err("Invalid df_csc start_line value\n");
474 if (df_csc
->num_lines
> ISIF_DF_NUMLINES
) {
475 pr_err("Invalid df_csc num_lines value\n");
482 #define DM365_ISIF_MAX_VDFLSFT 4
483 #define DM365_ISIF_MAX_VDFSLV 4095
484 #define DM365_ISIF_MAX_DFCMEM0 0x1fff
485 #define DM365_ISIF_MAX_DFCMEM1 0x1fff
487 static int isif_validate_dfc_params(struct vpfe_isif_dfc
*dfc
)
495 if (dfc
->corr_whole_line
> 1) {
496 pr_err("Invalid corr_whole_line value\n");
500 if (dfc
->def_level_shift
> DM365_ISIF_MAX_VDFLSFT
) {
501 pr_err("Invalid def_level_shift value\n");
505 if (dfc
->def_sat_level
> DM365_ISIF_MAX_VDFSLV
) {
506 pr_err("Invalid def_sat_level value\n");
510 if (!dfc
->num_vdefects
||
511 dfc
->num_vdefects
> VPFE_ISIF_VDFC_TABLE_SIZE
) {
512 pr_err("Invalid num_vdefects value\n");
516 for (i
= 0; i
< VPFE_ISIF_VDFC_TABLE_SIZE
; i
++) {
517 if (dfc
->table
[i
].pos_vert
> DM365_ISIF_MAX_DFCMEM0
) {
518 pr_err("Invalid pos_vert value\n");
521 if (dfc
->table
[i
].pos_horz
> DM365_ISIF_MAX_DFCMEM1
) {
522 pr_err("Invalid pos_horz value\n");
530 #define DM365_ISIF_MAX_CLVRV 0xfff
531 #define DM365_ISIF_MAX_CLDC 0x1fff
532 #define DM365_ISIF_MAX_CLHSH 0x1fff
533 #define DM365_ISIF_MAX_CLHSV 0x1fff
534 #define DM365_ISIF_MAX_CLVSH 0x1fff
535 #define DM365_ISIF_MAX_CLVSV 0x1fff
536 #define DM365_ISIF_MAX_HEIGHT_BLACK_REGION 0x1fff
538 static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp
*bclamp
)
542 if (bclamp
->dc_offset
> DM365_ISIF_MAX_CLDC
) {
543 pr_err("Invalid bclamp dc_offset value\n");
548 if (bclamp
->horz
.clamp_pix_limit
> 1) {
549 pr_err("Invalid bclamp horz clamp_pix_limit value\n");
552 if (bclamp
->horz
.win_count_calc
< 1 ||
553 bclamp
->horz
.win_count_calc
> 32) {
554 pr_err("Invalid bclamp horz win_count_calc value\n");
557 if (bclamp
->horz
.win_start_h_calc
> DM365_ISIF_MAX_CLHSH
) {
558 pr_err("Invalid bclamp win_start_v_calc value\n");
562 if (bclamp
->horz
.win_start_v_calc
> DM365_ISIF_MAX_CLHSV
) {
563 pr_err("Invalid bclamp win_start_v_calc value\n");
566 if (bclamp
->vert
.reset_clamp_val
> DM365_ISIF_MAX_CLVRV
) {
567 pr_err("Invalid bclamp reset_clamp_val value\n");
570 if (bclamp
->vert
.ob_v_sz_calc
> DM365_ISIF_MAX_HEIGHT_BLACK_REGION
) {
571 pr_err("Invalid bclamp ob_v_sz_calc value\n");
574 if (bclamp
->vert
.ob_start_h
> DM365_ISIF_MAX_CLVSH
) {
575 pr_err("Invalid bclamp ob_start_h value\n");
578 if (bclamp
->vert
.ob_start_v
> DM365_ISIF_MAX_CLVSV
) {
579 pr_err("Invalid bclamp ob_start_h value\n");
586 isif_validate_raw_params(struct vpfe_isif_raw_config
*params
)
590 ret
= isif_validate_df_csc_params(¶ms
->df_csc
);
593 ret
= isif_validate_dfc_params(¶ms
->dfc
);
596 ret
= isif_validate_bclamp_params(¶ms
->bclamp
);
600 static int isif_set_params(struct v4l2_subdev
*sd
, void *params
)
602 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
603 struct vpfe_isif_raw_config isif_raw_params
;
606 /* only raw module parameters can be set through the IOCTL */
607 if (isif
->formats
[ISIF_PAD_SINK
].code
!= MEDIA_BUS_FMT_SGRBG12_1X12
)
610 memcpy(&isif_raw_params
, params
, sizeof(isif_raw_params
));
611 if (!isif_validate_raw_params(&isif_raw_params
)) {
612 memcpy(&isif
->isif_cfg
.bayer
.config_params
, &isif_raw_params
,
613 sizeof(isif_raw_params
));
619 * isif_ioctl() - isif module private ioctl's
620 * @sd: VPFE isif V4L2 subdevice
621 * @cmd: ioctl command
622 * @arg: ioctl argument
624 * Return 0 on success or a negative error code otherwise.
626 static long isif_ioctl(struct v4l2_subdev
*sd
, unsigned int cmd
, void *arg
)
631 case VIDIOC_VPFE_ISIF_S_RAW_PARAMS
:
632 ret
= isif_set_params(sd
, arg
);
635 case VIDIOC_VPFE_ISIF_G_RAW_PARAMS
:
636 ret
= isif_get_params(sd
, arg
);
645 static void isif_config_gain_offset(struct vpfe_isif_device
*isif
)
647 struct vpfe_isif_gain_offsets_adj
*gain_off_ptr
=
648 &isif
->isif_cfg
.bayer
.config_params
.gain_offset
;
649 void __iomem
*base
= isif
->isif_cfg
.base_addr
;
652 val
= ((gain_off_ptr
->gain_sdram_en
& 1) << GAIN_SDRAM_EN_SHIFT
) |
653 ((gain_off_ptr
->gain_ipipe_en
& 1) << GAIN_IPIPE_EN_SHIFT
) |
654 ((gain_off_ptr
->gain_h3a_en
& 1) << GAIN_H3A_EN_SHIFT
) |
655 ((gain_off_ptr
->offset_sdram_en
& 1) << OFST_SDRAM_EN_SHIFT
) |
656 ((gain_off_ptr
->offset_ipipe_en
& 1) << OFST_IPIPE_EN_SHIFT
) |
657 ((gain_off_ptr
->offset_h3a_en
& 1) << OFST_H3A_EN_SHIFT
);
658 isif_merge(base
, GAIN_OFFSET_EN_MASK
, val
, CGAMMAWD
);
660 isif_write(base
, isif
->isif_cfg
.isif_gain_params
.cr_gain
, CRGAIN
);
661 isif_write(base
, isif
->isif_cfg
.isif_gain_params
.cgr_gain
, CGRGAIN
);
662 isif_write(base
, isif
->isif_cfg
.isif_gain_params
.cgb_gain
, CGBGAIN
);
663 isif_write(base
, isif
->isif_cfg
.isif_gain_params
.cb_gain
, CBGAIN
);
664 isif_write(base
, isif
->isif_cfg
.isif_gain_params
.offset
& OFFSET_MASK
,
669 static void isif_config_bclamp(struct vpfe_isif_device
*isif
,
670 struct vpfe_isif_black_clamp
*bc
)
675 * DC Offset is always added to image data irrespective of bc enable
678 val
= bc
->dc_offset
& ISIF_BC_DCOFFSET_MASK
;
679 isif_write(isif
->isif_cfg
.base_addr
, val
, CLDCOFST
);
684 val
= (bc
->bc_mode_color
& ISIF_BC_MODE_COLOR_MASK
) <<
685 ISIF_BC_MODE_COLOR_SHIFT
;
687 /* Enable BC and horizontal clamp calculation paramaters */
688 val
= val
| 1 | ((bc
->horz
.mode
& ISIF_HORZ_BC_MODE_MASK
) <<
689 ISIF_HORZ_BC_MODE_SHIFT
);
691 isif_write(isif
->isif_cfg
.base_addr
, val
, CLAMPCFG
);
693 if (bc
->horz
.mode
!= VPFE_ISIF_HORZ_BC_DISABLE
) {
695 * Window count for calculation
696 * Base window selection
698 * Horizontal size of window
699 * vertical size of the window
700 * Horizontal start position of the window
701 * Vertical start position of the window
703 val
= (bc
->horz
.win_count_calc
& ISIF_HORZ_BC_WIN_COUNT_MASK
) |
704 ((bc
->horz
.base_win_sel_calc
& 1) <<
705 ISIF_HORZ_BC_WIN_SEL_SHIFT
) |
706 ((bc
->horz
.clamp_pix_limit
& 1) <<
707 ISIF_HORZ_BC_PIX_LIMIT_SHIFT
) |
708 ((bc
->horz
.win_h_sz_calc
&
709 ISIF_HORZ_BC_WIN_H_SIZE_MASK
) <<
710 ISIF_HORZ_BC_WIN_H_SIZE_SHIFT
) |
711 ((bc
->horz
.win_v_sz_calc
&
712 ISIF_HORZ_BC_WIN_V_SIZE_MASK
) <<
713 ISIF_HORZ_BC_WIN_V_SIZE_SHIFT
);
715 isif_write(isif
->isif_cfg
.base_addr
, val
, CLHWIN0
);
717 val
= bc
->horz
.win_start_h_calc
& ISIF_HORZ_BC_WIN_START_H_MASK
;
718 isif_write(isif
->isif_cfg
.base_addr
, val
, CLHWIN1
);
720 val
= bc
->horz
.win_start_v_calc
& ISIF_HORZ_BC_WIN_START_V_MASK
;
721 isif_write(isif
->isif_cfg
.base_addr
, val
, CLHWIN2
);
724 /* vertical clamp calculation paramaters */
726 val
= bc
->vert
.ob_h_sz_calc
& ISIF_VERT_BC_OB_H_SZ_MASK
;
728 /* Reset clamp value sel for previous line */
729 val
|= (bc
->vert
.reset_val_sel
& ISIF_VERT_BC_RST_VAL_SEL_MASK
) <<
730 ISIF_VERT_BC_RST_VAL_SEL_SHIFT
;
732 /* Line average coefficient */
733 val
|= bc
->vert
.line_ave_coef
<< ISIF_VERT_BC_LINE_AVE_COEF_SHIFT
;
734 isif_write(isif
->isif_cfg
.base_addr
, val
, CLVWIN0
);
736 /* Configured reset value */
737 if (bc
->vert
.reset_val_sel
== VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL
) {
738 val
= bc
->vert
.reset_clamp_val
& ISIF_VERT_BC_RST_VAL_MASK
;
739 isif_write(isif
->isif_cfg
.base_addr
, val
, CLVRV
);
742 /* Optical Black horizontal start position */
743 val
= bc
->vert
.ob_start_h
& ISIF_VERT_BC_OB_START_HORZ_MASK
;
744 isif_write(isif
->isif_cfg
.base_addr
, val
, CLVWIN1
);
746 /* Optical Black vertical start position */
747 val
= bc
->vert
.ob_start_v
& ISIF_VERT_BC_OB_START_VERT_MASK
;
748 isif_write(isif
->isif_cfg
.base_addr
, val
, CLVWIN2
);
750 val
= bc
->vert
.ob_v_sz_calc
& ISIF_VERT_BC_OB_VERT_SZ_MASK
;
751 isif_write(isif
->isif_cfg
.base_addr
, val
, CLVWIN3
);
753 /* Vertical start position for BC subtraction */
754 val
= bc
->vert_start_sub
& ISIF_BC_VERT_START_SUB_V_MASK
;
755 isif_write(isif
->isif_cfg
.base_addr
, val
, CLSV
);
758 /* This function will configure the window size to be capture in ISIF reg */
760 isif_setwin(struct vpfe_isif_device
*isif
, struct v4l2_rect
*image_win
,
761 enum isif_frmfmt frm_fmt
, int ppc
, int mode
)
770 * ppc - per pixel count. indicates how many pixels per cell
771 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
772 * raw capture this is 1
774 horz_start
= image_win
->left
<< (ppc
- 1);
775 horz_nr_pixels
= (image_win
->width
<< (ppc
- 1)) - 1;
777 /* Writing the horizontal info into the registers */
778 isif_write(isif
->isif_cfg
.base_addr
,
779 horz_start
& START_PX_HOR_MASK
, SPH
);
780 isif_write(isif
->isif_cfg
.base_addr
,
781 horz_nr_pixels
& NUM_PX_HOR_MASK
, LNH
);
782 vert_start
= image_win
->top
;
784 if (frm_fmt
== ISIF_FRMFMT_INTERLACED
) {
785 vert_nr_lines
= (image_win
->height
>> 1) - 1;
787 /* To account for VD since line 0 doesn't have any data */
790 /* To account for VD since line 0 doesn't have any data */
792 vert_nr_lines
= image_win
->height
- 1;
793 /* configure VDINT0 and VDINT1 */
794 mid_img
= vert_start
+ (image_win
->height
/ 2);
795 isif_write(isif
->isif_cfg
.base_addr
, mid_img
, VDINT1
);
799 isif_write(isif
->isif_cfg
.base_addr
, 0, VDINT0
);
801 isif_write(isif
->isif_cfg
.base_addr
, vert_nr_lines
, VDINT0
);
802 isif_write(isif
->isif_cfg
.base_addr
,
803 vert_start
& START_VER_ONE_MASK
, SLV0
);
804 isif_write(isif
->isif_cfg
.base_addr
,
805 vert_start
& START_VER_TWO_MASK
, SLV1
);
806 isif_write(isif
->isif_cfg
.base_addr
,
807 vert_nr_lines
& NUM_LINES_VER
, LNV
);
810 #define DM365_ISIF_DFCMWR_MEMORY_WRITE 1
811 #define DM365_ISIF_DFCMRD_MEMORY_READ 0x2
814 isif_config_dfc(struct vpfe_isif_device
*isif
, struct vpfe_isif_dfc
*vdfc
)
816 #define DFC_WRITE_WAIT_COUNT 1000
817 u32 count
= DFC_WRITE_WAIT_COUNT
;
824 /* Correction mode */
825 val
= (vdfc
->corr_mode
& ISIF_VDFC_CORR_MOD_MASK
) <<
826 ISIF_VDFC_CORR_MOD_SHIFT
;
828 /* Correct whole line or partial */
829 if (vdfc
->corr_whole_line
)
830 val
|= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT
;
832 /* level shift value */
833 val
|= (vdfc
->def_level_shift
& ISIF_VDFC_LEVEL_SHFT_MASK
) <<
834 ISIF_VDFC_LEVEL_SHFT_SHIFT
;
836 isif_write(isif
->isif_cfg
.base_addr
, val
, DFCCTL
);
838 /* Defect saturation level */
839 val
= vdfc
->def_sat_level
& ISIF_VDFC_SAT_LEVEL_MASK
;
840 isif_write(isif
->isif_cfg
.base_addr
, val
, VDFSATLV
);
842 isif_write(isif
->isif_cfg
.base_addr
, vdfc
->table
[0].pos_vert
&
843 ISIF_VDFC_POS_MASK
, DFCMEM0
);
844 isif_write(isif
->isif_cfg
.base_addr
, vdfc
->table
[0].pos_horz
&
845 ISIF_VDFC_POS_MASK
, DFCMEM1
);
846 if (vdfc
->corr_mode
== VPFE_ISIF_VDFC_NORMAL
||
847 vdfc
->corr_mode
== VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT
) {
848 isif_write(isif
->isif_cfg
.base_addr
,
849 vdfc
->table
[0].level_at_pos
, DFCMEM2
);
850 isif_write(isif
->isif_cfg
.base_addr
,
851 vdfc
->table
[0].level_up_pixels
, DFCMEM3
);
852 isif_write(isif
->isif_cfg
.base_addr
,
853 vdfc
->table
[0].level_low_pixels
, DFCMEM4
);
856 val
= isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
);
857 /* set DFCMARST and set DFCMWR */
858 val
|= 1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT
;
860 isif_write(isif
->isif_cfg
.base_addr
, val
, DFCMEMCTL
);
862 while (count
&& (isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
) & 0x01))
865 val
= isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
);
867 pr_debug("defect table write timeout !!\n");
871 for (i
= 1; i
< vdfc
->num_vdefects
; i
++) {
872 isif_write(isif
->isif_cfg
.base_addr
, vdfc
->table
[i
].pos_vert
&
873 ISIF_VDFC_POS_MASK
, DFCMEM0
);
875 isif_write(isif
->isif_cfg
.base_addr
, vdfc
->table
[i
].pos_horz
&
876 ISIF_VDFC_POS_MASK
, DFCMEM1
);
878 if (vdfc
->corr_mode
== VPFE_ISIF_VDFC_NORMAL
||
879 vdfc
->corr_mode
== VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT
) {
880 isif_write(isif
->isif_cfg
.base_addr
,
881 vdfc
->table
[i
].level_at_pos
, DFCMEM2
);
882 isif_write(isif
->isif_cfg
.base_addr
,
883 vdfc
->table
[i
].level_up_pixels
, DFCMEM3
);
884 isif_write(isif
->isif_cfg
.base_addr
,
885 vdfc
->table
[i
].level_low_pixels
, DFCMEM4
);
887 val
= isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
);
888 /* clear DFCMARST and set DFCMWR */
889 val
&= ~(1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT
);
891 isif_write(isif
->isif_cfg
.base_addr
, val
, DFCMEMCTL
);
893 count
= DFC_WRITE_WAIT_COUNT
;
894 while (count
&& (isif_read(isif
->isif_cfg
.base_addr
,
898 val
= isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
);
900 pr_debug("defect table write timeout !!\n");
904 if (vdfc
->num_vdefects
< VPFE_ISIF_VDFC_TABLE_SIZE
) {
905 /* Extra cycle needed */
906 isif_write(isif
->isif_cfg
.base_addr
, 0, DFCMEM0
);
907 isif_write(isif
->isif_cfg
.base_addr
,
908 DM365_ISIF_MAX_DFCMEM1
, DFCMEM1
);
909 isif_write(isif
->isif_cfg
.base_addr
,
910 DM365_ISIF_DFCMWR_MEMORY_WRITE
, DFCMEMCTL
);
913 isif_merge(isif
->isif_cfg
.base_addr
, (1 << ISIF_VDFC_EN_SHIFT
),
914 (1 << ISIF_VDFC_EN_SHIFT
), DFCCTL
);
916 isif_merge(isif
->isif_cfg
.base_addr
, (1 << ISIF_VDFC_EN_SHIFT
),
917 (0 << ISIF_VDFC_EN_SHIFT
), DFCCTL
);
919 isif_write(isif
->isif_cfg
.base_addr
, 0x6, DFCMEMCTL
);
920 for (i
= 0; i
< vdfc
->num_vdefects
; i
++) {
921 count
= DFC_WRITE_WAIT_COUNT
;
923 (isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
) & 0x2))
925 val
= isif_read(isif
->isif_cfg
.base_addr
, DFCMEMCTL
);
927 pr_debug("defect table write timeout !!\n");
930 isif_write(isif
->isif_cfg
.base_addr
,
931 DM365_ISIF_DFCMRD_MEMORY_READ
, DFCMEMCTL
);
936 isif_config_csc(struct vpfe_isif_device
*isif
, struct vpfe_isif_df_csc
*df_csc
)
942 if (!df_csc
->csc
.en
) {
943 isif_write(isif
->isif_cfg
.base_addr
, 0, CSCCTL
);
946 /* initialize all bits to 0 */
948 for (i
= 0; i
< VPFE_ISIF_CSC_NUM_COEFF
; i
++) {
951 val1
= ((df_csc
->csc
.coeff
[i
].integer
&
952 ISIF_CSC_COEF_INTEG_MASK
) <<
953 ISIF_CSC_COEF_INTEG_SHIFT
) |
954 ((df_csc
->csc
.coeff
[i
].decimal
&
955 ISIF_CSC_COEF_DECIMAL_MASK
));
959 val2
= ((df_csc
->csc
.coeff
[i
].integer
&
960 ISIF_CSC_COEF_INTEG_MASK
) <<
961 ISIF_CSC_COEF_INTEG_SHIFT
) |
962 ((df_csc
->csc
.coeff
[i
].decimal
&
963 ISIF_CSC_COEF_DECIMAL_MASK
));
964 val2
<<= ISIF_CSCM_MSB_SHIFT
;
966 isif_write(isif
->isif_cfg
.base_addr
, val2
,
967 (CSCM0
+ ((i
-1) << 1)));
970 /* program the active area */
971 isif_write(isif
->isif_cfg
.base_addr
, df_csc
->start_pix
&
972 ISIF_DF_CSC_SPH_MASK
, FMTSPH
);
974 * one extra pixel as required for CSC. Actually number of
975 * pixel - 1 should be configured in this register. So we
976 * need to subtract 1 before writing to FMTSPH, but we will
977 * not do this since csc requires one extra pixel
979 isif_write(isif
->isif_cfg
.base_addr
, df_csc
->num_pixels
&
980 ISIF_DF_CSC_SPH_MASK
, FMTLNH
);
981 isif_write(isif
->isif_cfg
.base_addr
, df_csc
->start_line
&
982 ISIF_DF_CSC_SPH_MASK
, FMTSLV
);
984 * one extra line as required for CSC. See reason documented for
987 isif_write(isif
->isif_cfg
.base_addr
, df_csc
->num_lines
&
988 ISIF_DF_CSC_SPH_MASK
, FMTLNV
);
990 isif_write(isif
->isif_cfg
.base_addr
, 1, CSCCTL
);
994 isif_config_linearization(struct vpfe_isif_device
*isif
,
995 struct vpfe_isif_linearize
*linearize
)
1000 if (!linearize
->en
) {
1001 isif_write(isif
->isif_cfg
.base_addr
, 0, LINCFG0
);
1004 /* shift value for correction */
1005 val
= (linearize
->corr_shft
& ISIF_LIN_CORRSFT_MASK
) <<
1006 ISIF_LIN_CORRSFT_SHIFT
;
1009 isif_write(isif
->isif_cfg
.base_addr
, val
, LINCFG0
);
1011 val
= (linearize
->scale_fact
.integer
& 1) <<
1012 ISIF_LIN_SCALE_FACT_INTEG_SHIFT
;
1013 val
|= linearize
->scale_fact
.decimal
& ISIF_LIN_SCALE_FACT_DECIMAL_MASK
;
1014 isif_write(isif
->isif_cfg
.base_addr
, val
, LINCFG1
);
1016 for (i
= 0; i
< VPFE_ISIF_LINEAR_TAB_SIZE
; i
++) {
1017 val
= linearize
->table
[i
] & ISIF_LIN_ENTRY_MASK
;
1019 isif_regw_lin_tbl(isif
, val
, ((i
>> 1) << 2), 1);
1021 isif_regw_lin_tbl(isif
, val
, ((i
>> 1) << 2), 0);
1026 isif_config_culling(struct vpfe_isif_device
*isif
, struct vpfe_isif_cul
*cul
)
1030 /* Horizontal pattern */
1031 val
= cul
->hcpat_even
<< CULL_PAT_EVEN_LINE_SHIFT
;
1032 val
|= cul
->hcpat_odd
;
1033 isif_write(isif
->isif_cfg
.base_addr
, val
, CULH
);
1034 /* vertical pattern */
1035 isif_write(isif
->isif_cfg
.base_addr
, cul
->vcpat
, CULV
);
1037 isif_merge(isif
->isif_cfg
.base_addr
, ISIF_LPF_MASK
<< ISIF_LPF_SHIFT
,
1038 cul
->en_lpf
<< ISIF_LPF_SHIFT
, MODESET
);
1041 static int isif_get_pix_fmt(u32 mbus_code
)
1043 switch (mbus_code
) {
1044 case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8
:
1045 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8
:
1046 case MEDIA_BUS_FMT_SGRBG12_1X12
:
1047 return ISIF_PIXFMT_RAW
;
1049 case MEDIA_BUS_FMT_YUYV8_2X8
:
1050 case MEDIA_BUS_FMT_UYVY8_2X8
:
1051 case MEDIA_BUS_FMT_YUYV10_2X10
:
1052 case MEDIA_BUS_FMT_Y8_1X8
:
1053 return ISIF_PIXFMT_YCBCR_8BIT
;
1055 case MEDIA_BUS_FMT_YUYV8_1X16
:
1056 case MEDIA_BUS_FMT_YUYV10_1X20
:
1057 return ISIF_PIXFMT_YCBCR_16BIT
;
1065 #define ISIF_INTERLACE_INVERSE_MODE 0x4b6d
1066 #define ISIF_INTERLACE_NON_INVERSE_MODE 0x0b6d
1067 #define ISIF_PROGRESSIVE_INVERSE_MODE 0x4000
1068 #define ISIF_PROGRESSIVE_NON_INVERSE_MODE 0x0000
1070 static int isif_config_raw(struct v4l2_subdev
*sd
, int mode
)
1072 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1073 struct isif_params_raw
*params
= &isif
->isif_cfg
.bayer
;
1074 struct vpfe_isif_raw_config
*module_params
=
1075 &isif
->isif_cfg
.bayer
.config_params
;
1076 struct v4l2_mbus_framefmt
*format
;
1080 format
= &isif
->formats
[ISIF_PAD_SINK
];
1082 /* In case of user has set BT656IF earlier, it should be reset
1083 * when configuring for raw input.
1085 isif_write(isif
->isif_cfg
.base_addr
, 0, REC656IF
);
1086 /* Configure CCDCFG register
1087 * Set CCD Not to swap input since input is RAW data
1088 * Set FID detection function to Latch at V-Sync
1089 * Set WENLOG - isif valid area
1092 * Packed to 8 or 16 bits
1094 val
= ISIF_YCINSWP_RAW
| ISIF_CCDCFG_FIDMD_LATCH_VSYNC
|
1095 ISIF_CCDCFG_WENLOG_AND
| ISIF_CCDCFG_TRGSEL_WEN
|
1096 ISIF_CCDCFG_EXTRG_DISABLE
| (isif
->isif_cfg
.data_pack
&
1097 ISIF_DATA_PACK_MASK
);
1098 isif_write(isif
->isif_cfg
.base_addr
, val
, CCDCFG
);
1100 pix_fmt
= isif_get_pix_fmt(format
->code
);
1102 pr_debug("Invalid pix_fmt(input mode)\n");
1106 * Configure the vertical sync polarity(MODESET.VDPOL)
1107 * Configure the horizontal sync polarity (MODESET.HDPOL)
1108 * Configure frame id polarity (MODESET.FLDPOL)
1109 * Configure data polarity
1110 * Configure External WEN Selection
1111 * Configure frame format(progressive or interlace)
1112 * Configure pixel format (Input mode)
1113 * Configure the data shift
1115 val
= ISIF_VDHDOUT_INPUT
| ((params
->vd_pol
& ISIF_VD_POL_MASK
) <<
1116 ISIF_VD_POL_SHIFT
) | ((params
->hd_pol
& ISIF_HD_POL_MASK
) <<
1117 ISIF_HD_POL_SHIFT
) | ((params
->fid_pol
& ISIF_FID_POL_MASK
) <<
1118 ISIF_FID_POL_SHIFT
) | ((ISIF_DATAPOL_NORMAL
&
1119 ISIF_DATAPOL_MASK
) << ISIF_DATAPOL_SHIFT
) | ((ISIF_EXWEN_DISABLE
&
1120 ISIF_EXWEN_MASK
) << ISIF_EXWEN_SHIFT
) | ((params
->frm_fmt
&
1121 ISIF_FRM_FMT_MASK
) << ISIF_FRM_FMT_SHIFT
) | ((pix_fmt
&
1122 ISIF_INPUT_MASK
) << ISIF_INPUT_SHIFT
);
1124 /* currently only MEDIA_BUS_FMT_SGRBG12_1X12 is
1125 * supported. shift appropriately depending on
1126 * different MBUS fmt's added
1128 if (format
->code
== MEDIA_BUS_FMT_SGRBG12_1X12
)
1129 val
|= ((VPFE_ISIF_NO_SHIFT
&
1130 ISIF_DATASFT_MASK
) << ISIF_DATASFT_SHIFT
);
1132 isif_write(isif
->isif_cfg
.base_addr
, val
, MODESET
);
1134 * Configure GAMMAWD register
1135 * CFA pattern setting
1137 val
= (params
->cfa_pat
& ISIF_GAMMAWD_CFA_MASK
) <<
1138 ISIF_GAMMAWD_CFA_SHIFT
;
1140 if (params
->v4l2_pix_fmt
== V4L2_PIX_FMT_SGRBG10ALAW8
)
1141 val
= val
| ISIF_ALAW_ENABLE
;
1143 val
= val
| ((params
->data_msb
& ISIF_ALAW_GAMA_WD_MASK
) <<
1144 ISIF_ALAW_GAMA_WD_SHIFT
);
1146 isif_write(isif
->isif_cfg
.base_addr
, val
, CGAMMAWD
);
1147 /* Configure DPCM compression settings */
1148 if (params
->v4l2_pix_fmt
== V4L2_PIX_FMT_SGRBG10DPCM8
) {
1149 val
= 1 << ISIF_DPCM_EN_SHIFT
;
1150 val
|= (params
->dpcm_predictor
&
1151 ISIF_DPCM_PREDICTOR_MASK
) << ISIF_DPCM_PREDICTOR_SHIFT
;
1153 isif_write(isif
->isif_cfg
.base_addr
, val
, MISC
);
1154 /* Configure Gain & Offset */
1155 isif_config_gain_offset(isif
);
1156 /* Configure Color pattern */
1157 if (format
->code
== MEDIA_BUS_FMT_SGRBG12_1X12
)
1158 val
= isif_sgrbg_pattern
;
1160 /* default set to rggb */
1161 val
= isif_srggb_pattern
;
1163 isif_write(isif
->isif_cfg
.base_addr
, val
, CCOLP
);
1165 /* Configure HSIZE register */
1166 val
= (params
->horz_flip_en
& ISIF_HSIZE_FLIP_MASK
) <<
1167 ISIF_HSIZE_FLIP_SHIFT
;
1169 /* calculate line offset in 32 bytes based on pack value */
1170 if (isif
->isif_cfg
.data_pack
== ISIF_PACK_8BIT
)
1171 val
|= ((params
->win
.width
+ 31) >> 5) & ISIF_LINEOFST_MASK
;
1172 else if (isif
->isif_cfg
.data_pack
== ISIF_PACK_12BIT
)
1173 val
|= ((((params
->win
.width
+ (params
->win
.width
>> 2)) +
1174 31) >> 5) & ISIF_LINEOFST_MASK
);
1176 val
|= (((params
->win
.width
* 2) + 31) >> 5) &
1178 isif_write(isif
->isif_cfg
.base_addr
, val
, HSIZE
);
1179 /* Configure SDOFST register */
1180 if (params
->frm_fmt
== ISIF_FRMFMT_INTERLACED
) {
1181 if (params
->image_invert_en
)
1182 /* For interlace inverse mode */
1183 isif_write(isif
->isif_cfg
.base_addr
,
1184 ISIF_INTERLACE_INVERSE_MODE
, SDOFST
);
1186 /* For interlace non inverse mode */
1187 isif_write(isif
->isif_cfg
.base_addr
,
1188 ISIF_INTERLACE_NON_INVERSE_MODE
, SDOFST
);
1189 } else if (params
->frm_fmt
== ISIF_FRMFMT_PROGRESSIVE
) {
1190 if (params
->image_invert_en
)
1191 isif_write(isif
->isif_cfg
.base_addr
,
1192 ISIF_PROGRESSIVE_INVERSE_MODE
, SDOFST
);
1194 /* For progessive non inverse mode */
1195 isif_write(isif
->isif_cfg
.base_addr
,
1196 ISIF_PROGRESSIVE_NON_INVERSE_MODE
, SDOFST
);
1198 /* Configure video window */
1199 isif_setwin(isif
, ¶ms
->win
, params
->frm_fmt
, 1, mode
);
1200 /* Configure Black Clamp */
1201 isif_config_bclamp(isif
, &module_params
->bclamp
);
1202 /* Configure Vertical Defection Pixel Correction */
1203 isif_config_dfc(isif
, &module_params
->dfc
);
1204 if (!module_params
->df_csc
.df_or_csc
)
1205 /* Configure Color Space Conversion */
1206 isif_config_csc(isif
, &module_params
->df_csc
);
1208 isif_config_linearization(isif
, &module_params
->linearize
);
1209 /* Configure Culling */
1210 isif_config_culling(isif
, &module_params
->culling
);
1211 /* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */
1212 val
= module_params
->horz_offset
& ISIF_DATA_H_OFFSET_MASK
;
1213 isif_write(isif
->isif_cfg
.base_addr
, val
, DATAHOFST
);
1215 val
= module_params
->vert_offset
& ISIF_DATA_V_OFFSET_MASK
;
1216 isif_write(isif
->isif_cfg
.base_addr
, val
, DATAVOFST
);
1221 #define DM365_ISIF_HSIZE_MASK 0xffffffe0
1222 #define DM365_ISIF_SDOFST_2_LINES 0x00000249
1224 /* This function will configure ISIF for YCbCr parameters. */
1225 static int isif_config_ycbcr(struct v4l2_subdev
*sd
, int mode
)
1227 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1228 struct isif_ycbcr_config
*params
= &isif
->isif_cfg
.ycbcr
;
1229 struct v4l2_mbus_framefmt
*format
;
1234 format
= &isif
->formats
[ISIF_PAD_SINK
];
1236 * first reset the ISIF
1237 * all registers have default values after reset
1238 * This is important since we assume default values to be set in
1239 * a lot of registers that we didn't touch
1241 /* start with all bits zero */
1242 ccdcfg
= modeset
= 0;
1243 pix_fmt
= isif_get_pix_fmt(format
->code
);
1245 pr_debug("Invalid pix_fmt(input mode)\n");
1248 /* configure pixel format or input mode */
1249 modeset
= modeset
| ((pix_fmt
& ISIF_INPUT_MASK
) <<
1250 ISIF_INPUT_SHIFT
) | ((params
->frm_fmt
& ISIF_FRM_FMT_MASK
) <<
1251 ISIF_FRM_FMT_SHIFT
) | (((params
->fid_pol
&
1252 ISIF_FID_POL_MASK
) << ISIF_FID_POL_SHIFT
)) |
1253 (((params
->hd_pol
& ISIF_HD_POL_MASK
) << ISIF_HD_POL_SHIFT
)) |
1254 (((params
->vd_pol
& ISIF_VD_POL_MASK
) << ISIF_VD_POL_SHIFT
));
1255 /* pack the data to 8-bit CCDCCFG */
1256 switch (format
->code
) {
1257 case MEDIA_BUS_FMT_YUYV8_2X8
:
1258 case MEDIA_BUS_FMT_UYVY8_2X8
:
1259 if (pix_fmt
!= ISIF_PIXFMT_YCBCR_8BIT
) {
1260 pr_debug("Invalid pix_fmt(input mode)\n");
1263 modeset
|= ((VPFE_PINPOL_NEGATIVE
& ISIF_VD_POL_MASK
) <<
1265 isif_write(isif
->isif_cfg
.base_addr
, 3, REC656IF
);
1266 ccdcfg
= ccdcfg
| ISIF_PACK_8BIT
| ISIF_YCINSWP_YCBCR
;
1269 case MEDIA_BUS_FMT_YUYV10_2X10
:
1270 if (pix_fmt
!= ISIF_PIXFMT_YCBCR_8BIT
) {
1271 pr_debug("Invalid pix_fmt(input mode)\n");
1274 /* setup BT.656, embedded sync */
1275 isif_write(isif
->isif_cfg
.base_addr
, 3, REC656IF
);
1276 /* enable 10 bit mode in ccdcfg */
1277 ccdcfg
= ccdcfg
| ISIF_PACK_8BIT
| ISIF_YCINSWP_YCBCR
|
1281 case MEDIA_BUS_FMT_YUYV10_1X20
:
1282 if (pix_fmt
!= ISIF_PIXFMT_YCBCR_16BIT
) {
1283 pr_debug("Invalid pix_fmt(input mode)\n");
1286 isif_write(isif
->isif_cfg
.base_addr
, 3, REC656IF
);
1289 case MEDIA_BUS_FMT_Y8_1X8
:
1290 ccdcfg
|= ISIF_PACK_8BIT
;
1291 ccdcfg
|= ISIF_YCINSWP_YCBCR
;
1292 if (pix_fmt
!= ISIF_PIXFMT_YCBCR_8BIT
) {
1293 pr_debug("Invalid pix_fmt(input mode)\n");
1298 case MEDIA_BUS_FMT_YUYV8_1X16
:
1299 if (pix_fmt
!= ISIF_PIXFMT_YCBCR_16BIT
) {
1300 pr_debug("Invalid pix_fmt(input mode)\n");
1306 /* should never come here */
1307 pr_debug("Invalid interface type\n");
1310 isif_write(isif
->isif_cfg
.base_addr
, modeset
, MODESET
);
1311 /* Set up pix order */
1312 ccdcfg
|= (params
->pix_order
& ISIF_PIX_ORDER_MASK
) <<
1313 ISIF_PIX_ORDER_SHIFT
;
1314 isif_write(isif
->isif_cfg
.base_addr
, ccdcfg
, CCDCFG
);
1315 /* configure video window */
1316 if (format
->code
== MEDIA_BUS_FMT_YUYV10_1X20
||
1317 format
->code
== MEDIA_BUS_FMT_YUYV8_1X16
)
1318 isif_setwin(isif
, ¶ms
->win
, params
->frm_fmt
, 1, mode
);
1320 isif_setwin(isif
, ¶ms
->win
, params
->frm_fmt
, 2, mode
);
1323 * configure the horizontal line offset
1324 * this is done by rounding up width to a multiple of 16 pixels
1325 * and multiply by two to account for y:cb:cr 4:2:2 data
1327 isif_write(isif
->isif_cfg
.base_addr
,
1328 ((((params
->win
.width
* 2) + 31) &
1329 DM365_ISIF_HSIZE_MASK
) >> 5), HSIZE
);
1331 /* configure the memory line offset */
1332 if (params
->frm_fmt
== ISIF_FRMFMT_INTERLACED
&&
1333 params
->buf_type
== ISIF_BUFTYPE_FLD_INTERLEAVED
)
1334 /* two fields are interleaved in memory */
1335 isif_write(isif
->isif_cfg
.base_addr
,
1336 DM365_ISIF_SDOFST_2_LINES
, SDOFST
);
1340 static int isif_configure(struct v4l2_subdev
*sd
, int mode
)
1342 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1343 struct v4l2_mbus_framefmt
*format
;
1345 format
= &isif
->formats
[ISIF_PAD_SINK
];
1347 switch (format
->code
) {
1348 case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8
:
1349 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8
:
1350 case MEDIA_BUS_FMT_SGRBG12_1X12
:
1351 return isif_config_raw(sd
, mode
);
1353 case MEDIA_BUS_FMT_YUYV8_2X8
:
1354 case MEDIA_BUS_FMT_UYVY8_2X8
:
1355 case MEDIA_BUS_FMT_YUYV10_2X10
:
1356 case MEDIA_BUS_FMT_Y8_1X8
:
1357 case MEDIA_BUS_FMT_YUYV8_1X16
:
1358 case MEDIA_BUS_FMT_YUYV10_1X20
:
1359 return isif_config_ycbcr(sd
, mode
);
1368 * isif_set_stream() - Enable/Disable streaming on the ISIF module
1369 * @sd: VPFE ISIF V4L2 subdevice
1370 * @enable: Enable/disable stream
1372 static int isif_set_stream(struct v4l2_subdev
*sd
, int enable
)
1374 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1378 ret
= isif_configure(sd
,
1379 (isif
->output
== ISIF_OUTPUT_MEMORY
) ? 0 : 1);
1382 if (isif
->output
== ISIF_OUTPUT_MEMORY
)
1383 isif_enable_output_to_sdram(isif
, 1);
1384 isif_enable(isif
, 1);
1386 isif_enable(isif
, 0);
1387 isif_enable_output_to_sdram(isif
, 0);
1394 * __isif_get_format() - helper function for getting isif format
1395 * @isif: pointer to isif private structure.
1397 * @fh: V4L2 subdev file handle.
1398 * @which: wanted subdev format.
1400 static struct v4l2_mbus_framefmt
*
1401 __isif_get_format(struct vpfe_isif_device
*isif
, struct v4l2_subdev_fh
*fh
,
1402 unsigned int pad
, enum v4l2_subdev_format_whence which
)
1404 if (which
== V4L2_SUBDEV_FORMAT_TRY
) {
1405 struct v4l2_subdev_format fmt
;
1410 return v4l2_subdev_get_try_format(fh
, pad
);
1412 return &isif
->formats
[pad
];
1416 * isif_set_format() - set format on pad
1417 * @sd : VPFE ISIF device
1418 * @fh : V4L2 subdev file handle
1419 * @fmt : pointer to v4l2 subdev format structure
1421 * Return 0 on success or -EINVAL if format or pad is invalid
1424 isif_set_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1425 struct v4l2_subdev_format
*fmt
)
1427 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1428 struct vpfe_device
*vpfe_dev
= to_vpfe_device(isif
);
1429 struct v4l2_mbus_framefmt
*format
;
1431 format
= __isif_get_format(isif
, fh
, fmt
->pad
, fmt
->which
);
1435 isif_try_format(isif
, fh
, fmt
);
1436 memcpy(format
, &fmt
->format
, sizeof(*format
));
1438 if (fmt
->which
== V4L2_SUBDEV_FORMAT_TRY
)
1441 if (fmt
->pad
== ISIF_PAD_SOURCE
)
1442 return isif_config_format(vpfe_dev
, fmt
->pad
);
1448 * isif_get_format() - Retrieve the video format on a pad
1449 * @sd: VPFE ISIF V4L2 subdevice
1450 * @fh: V4L2 subdev file handle
1451 * @fmt: pointer to v4l2 subdev format structure
1453 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1454 * to the format type.
1457 isif_get_format(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1458 struct v4l2_subdev_format
*fmt
)
1460 struct vpfe_isif_device
*vpfe_isif
= v4l2_get_subdevdata(sd
);
1461 struct v4l2_mbus_framefmt
*format
;
1463 format
= __isif_get_format(vpfe_isif
, fh
, fmt
->pad
, fmt
->which
);
1467 memcpy(&fmt
->format
, format
, sizeof(fmt
->format
));
1473 * isif_enum_frame_size() - enum frame sizes on pads
1474 * @sd: VPFE isif V4L2 subdevice
1475 * @fh: V4L2 subdev file handle
1476 * @code: pointer to v4l2_subdev_frame_size_enum structure
1479 isif_enum_frame_size(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1480 struct v4l2_subdev_frame_size_enum
*fse
)
1482 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1483 struct v4l2_subdev_format format
;
1485 if (fse
->index
!= 0)
1488 format
.pad
= fse
->pad
;
1489 format
.format
.code
= fse
->code
;
1490 format
.format
.width
= 1;
1491 format
.format
.height
= 1;
1492 format
.which
= V4L2_SUBDEV_FORMAT_TRY
;
1493 isif_try_format(isif
, fh
, &format
);
1494 fse
->min_width
= format
.format
.width
;
1495 fse
->min_height
= format
.format
.height
;
1497 if (format
.format
.code
!= fse
->code
)
1500 format
.pad
= fse
->pad
;
1501 format
.format
.code
= fse
->code
;
1502 format
.format
.width
= -1;
1503 format
.format
.height
= -1;
1504 format
.which
= V4L2_SUBDEV_FORMAT_TRY
;
1505 isif_try_format(isif
, fh
, &format
);
1506 fse
->max_width
= format
.format
.width
;
1507 fse
->max_height
= format
.format
.height
;
1513 * isif_enum_mbus_code() - enum mbus codes for pads
1514 * @sd: VPFE isif V4L2 subdevice
1515 * @fh: V4L2 subdev file handle
1516 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1519 isif_enum_mbus_code(struct v4l2_subdev
*sd
, struct v4l2_subdev_fh
*fh
,
1520 struct v4l2_subdev_mbus_code_enum
*code
)
1522 switch (code
->pad
) {
1524 case ISIF_PAD_SOURCE
:
1525 if (code
->index
>= ARRAY_SIZE(isif_fmts
))
1527 code
->code
= isif_fmts
[code
->index
];
1538 * isif_pad_set_selection() - set crop rectangle on pad
1539 * @sd: VPFE isif V4L2 subdevice
1540 * @fh: V4L2 subdev file handle
1541 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1543 * Return 0 on success, -EINVAL if pad is invalid
1546 isif_pad_set_selection(struct v4l2_subdev
*sd
,
1547 struct v4l2_subdev_fh
*fh
,
1548 struct v4l2_subdev_selection
*sel
)
1550 struct vpfe_isif_device
*vpfe_isif
= v4l2_get_subdevdata(sd
);
1551 struct v4l2_mbus_framefmt
*format
;
1553 /* check whether it's a valid pad and target */
1554 if (sel
->pad
!= ISIF_PAD_SINK
|| sel
->target
!= V4L2_SEL_TGT_CROP
)
1557 format
= __isif_get_format(vpfe_isif
, fh
, sel
->pad
, sel
->which
);
1561 /* check wether crop rect is within limits */
1562 if (sel
->r
.top
< 0 || sel
->r
.left
< 0 ||
1563 (sel
->r
.left
+ sel
->r
.width
>
1564 vpfe_isif
->formats
[ISIF_PAD_SINK
].width
) ||
1565 (sel
->r
.top
+ sel
->r
.height
>
1566 vpfe_isif
->formats
[ISIF_PAD_SINK
].height
)) {
1569 sel
->r
.width
= format
->width
;
1570 sel
->r
.height
= format
->height
;
1572 /* adjust the width to 16 pixel boundary */
1573 sel
->r
.width
= ((sel
->r
.width
+ 15) & ~0xf);
1574 vpfe_isif
->crop
= sel
->r
;
1575 if (sel
->which
== V4L2_SUBDEV_FORMAT_ACTIVE
) {
1576 isif_set_image_window(vpfe_isif
);
1578 struct v4l2_rect
*rect
;
1580 rect
= v4l2_subdev_get_try_crop(fh
, ISIF_PAD_SINK
);
1581 memcpy(rect
, &vpfe_isif
->crop
, sizeof(*rect
));
1587 * isif_pad_get_selection() - get crop rectangle on pad
1588 * @sd: VPFE isif V4L2 subdevice
1589 * @fh: V4L2 subdev file handle
1590 * @code: pointer to v4l2_subdev_mbus_code_enum structure
1592 * Return 0 on success, -EINVAL if pad is invalid
1595 isif_pad_get_selection(struct v4l2_subdev
*sd
,
1596 struct v4l2_subdev_fh
*fh
,
1597 struct v4l2_subdev_selection
*sel
)
1599 struct vpfe_isif_device
*vpfe_isif
= v4l2_get_subdevdata(sd
);
1601 /* check whether it's a valid pad and target */
1602 if (sel
->pad
!= ISIF_PAD_SINK
|| sel
->target
!= V4L2_SEL_TGT_CROP
)
1605 if (sel
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1606 struct v4l2_rect
*rect
;
1608 rect
= v4l2_subdev_get_try_crop(fh
, ISIF_PAD_SINK
);
1609 memcpy(&sel
->r
, rect
, sizeof(*rect
));
1611 sel
->r
= vpfe_isif
->crop
;
1618 * isif_init_formats() - Initialize formats on all pads
1619 * @sd: VPFE isif V4L2 subdevice
1620 * @fh: V4L2 subdev file handle
1622 * Initialize all pad formats with default values. If fh is not NULL, try
1623 * formats are initialized on the file handle. Otherwise active formats are
1624 * initialized on the device.
1627 isif_init_formats(struct v4l2_subdev
*sd
,
1628 struct v4l2_subdev_fh
*fh
)
1630 struct v4l2_subdev_format format
;
1631 struct v4l2_subdev_selection sel
;
1633 memset(&format
, 0, sizeof(format
));
1634 format
.pad
= ISIF_PAD_SINK
;
1635 format
.which
= fh
? V4L2_SUBDEV_FORMAT_TRY
: V4L2_SUBDEV_FORMAT_ACTIVE
;
1636 format
.format
.code
= MEDIA_BUS_FMT_SGRBG12_1X12
;
1637 format
.format
.width
= MAX_WIDTH
;
1638 format
.format
.height
= MAX_HEIGHT
;
1639 isif_set_format(sd
, fh
, &format
);
1641 memset(&format
, 0, sizeof(format
));
1642 format
.pad
= ISIF_PAD_SOURCE
;
1643 format
.which
= fh
? V4L2_SUBDEV_FORMAT_TRY
: V4L2_SUBDEV_FORMAT_ACTIVE
;
1644 format
.format
.code
= MEDIA_BUS_FMT_SGRBG12_1X12
;
1645 format
.format
.width
= MAX_WIDTH
;
1646 format
.format
.height
= MAX_HEIGHT
;
1647 isif_set_format(sd
, fh
, &format
);
1649 memset(&sel
, 0, sizeof(sel
));
1650 sel
.pad
= ISIF_PAD_SINK
;
1651 sel
.which
= fh
? V4L2_SUBDEV_FORMAT_TRY
: V4L2_SUBDEV_FORMAT_ACTIVE
;
1652 sel
.target
= V4L2_SEL_TGT_CROP
;
1653 sel
.r
.width
= MAX_WIDTH
;
1654 sel
.r
.height
= MAX_HEIGHT
;
1655 isif_pad_set_selection(sd
, fh
, &sel
);
1660 /* subdev core operations */
1661 static const struct v4l2_subdev_core_ops isif_v4l2_core_ops
= {
1662 .ioctl
= isif_ioctl
,
1665 /* subdev file operations */
1666 static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops
= {
1667 .open
= isif_init_formats
,
1670 /* subdev video operations */
1671 static const struct v4l2_subdev_video_ops isif_v4l2_video_ops
= {
1672 .s_stream
= isif_set_stream
,
1675 /* subdev pad operations */
1676 static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops
= {
1677 .enum_mbus_code
= isif_enum_mbus_code
,
1678 .enum_frame_size
= isif_enum_frame_size
,
1679 .get_fmt
= isif_get_format
,
1680 .set_fmt
= isif_set_format
,
1681 .set_selection
= isif_pad_set_selection
,
1682 .get_selection
= isif_pad_get_selection
,
1685 /* subdev operations */
1686 static const struct v4l2_subdev_ops isif_v4l2_ops
= {
1687 .core
= &isif_v4l2_core_ops
,
1688 .video
= &isif_v4l2_video_ops
,
1689 .pad
= &isif_v4l2_pad_ops
,
1693 * Media entity operations
1697 * isif_link_setup() - Setup isif connections
1698 * @entity: isif media entity
1699 * @local: Pad at the local end of the link
1700 * @remote: Pad at the remote end of the link
1701 * @flags: Link flags
1703 * return -EINVAL or zero on success
1706 isif_link_setup(struct media_entity
*entity
, const struct media_pad
*local
,
1707 const struct media_pad
*remote
, u32 flags
)
1709 struct v4l2_subdev
*sd
= media_entity_to_v4l2_subdev(entity
);
1710 struct vpfe_isif_device
*isif
= v4l2_get_subdevdata(sd
);
1712 switch (local
->index
| media_entity_type(remote
->entity
)) {
1713 case ISIF_PAD_SINK
| MEDIA_ENT_T_V4L2_SUBDEV
:
1714 /* read from decoder/sensor */
1715 if (!(flags
& MEDIA_LNK_FL_ENABLED
)) {
1716 isif
->input
= ISIF_INPUT_NONE
;
1719 if (isif
->input
!= ISIF_INPUT_NONE
)
1721 isif
->input
= ISIF_INPUT_PARALLEL
;
1724 case ISIF_PAD_SOURCE
| MEDIA_ENT_T_DEVNODE
:
1725 /* write to memory */
1726 if (flags
& MEDIA_LNK_FL_ENABLED
)
1727 isif
->output
= ISIF_OUTPUT_MEMORY
;
1729 isif
->output
= ISIF_OUTPUT_NONE
;
1732 case ISIF_PAD_SOURCE
| MEDIA_ENT_T_V4L2_SUBDEV
:
1733 if (flags
& MEDIA_LNK_FL_ENABLED
)
1734 isif
->output
= ISIF_OUTPUT_IPIPEIF
;
1736 isif
->output
= ISIF_OUTPUT_NONE
;
1745 static const struct media_entity_operations isif_media_ops
= {
1746 .link_setup
= isif_link_setup
,
1750 * vpfe_isif_unregister_entities() - isif unregister entity
1751 * @isif - pointer to isif subdevice structure.
1753 void vpfe_isif_unregister_entities(struct vpfe_isif_device
*isif
)
1755 vpfe_video_unregister(&isif
->video_out
);
1756 /* unregister subdev */
1757 v4l2_device_unregister_subdev(&isif
->subdev
);
1758 /* cleanup entity */
1759 media_entity_cleanup(&isif
->subdev
.entity
);
1762 static void isif_restore_defaults(struct vpfe_isif_device
*isif
)
1764 enum vpss_ccdc_source_sel source
= VPSS_CCDCIN
;
1767 memset(&isif
->isif_cfg
.bayer
.config_params
, 0,
1768 sizeof(struct vpfe_isif_raw_config
));
1770 isif
->isif_cfg
.bayer
.config_params
.linearize
.corr_shft
=
1772 isif
->isif_cfg
.bayer
.config_params
.linearize
.scale_fact
.integer
= 1;
1773 isif
->isif_cfg
.bayer
.config_params
.culling
.hcpat_odd
=
1774 ISIF_CULLING_HCAPT_ODD
;
1775 isif
->isif_cfg
.bayer
.config_params
.culling
.hcpat_even
=
1776 ISIF_CULLING_HCAPT_EVEN
;
1777 isif
->isif_cfg
.bayer
.config_params
.culling
.vcpat
= ISIF_CULLING_VCAPT
;
1778 /* Enable clock to ISIF, IPIPEIF and BL */
1779 vpss_enable_clock(VPSS_CCDC_CLOCK
, 1);
1780 vpss_enable_clock(VPSS_IPIPEIF_CLOCK
, 1);
1781 vpss_enable_clock(VPSS_BL_CLOCK
, 1);
1783 /* set all registers to default value */
1784 for (i
= 0; i
<= 0x1f8; i
+= 4)
1785 isif_write(isif
->isif_cfg
.base_addr
, 0, i
);
1786 /* no culling support */
1787 isif_write(isif
->isif_cfg
.base_addr
, 0xffff, CULH
);
1788 isif_write(isif
->isif_cfg
.base_addr
, 0xff, CULV
);
1790 /* Set default offset and gain */
1791 isif_config_gain_offset(isif
);
1792 vpss_select_ccdc_source(source
);
1796 * vpfe_isif_register_entities() - isif register entity
1797 * @isif - pointer to isif subdevice structure.
1798 * @vdev: pointer to v4l2 device structure.
1800 int vpfe_isif_register_entities(struct vpfe_isif_device
*isif
,
1801 struct v4l2_device
*vdev
)
1803 struct vpfe_device
*vpfe_dev
= to_vpfe_device(isif
);
1807 /* Register the subdev */
1808 ret
= v4l2_device_register_subdev(vdev
, &isif
->subdev
);
1812 isif_restore_defaults(isif
);
1813 ret
= vpfe_video_register(&isif
->video_out
, vdev
);
1815 pr_err("Failed to register isif video out device\n");
1816 goto out_video_register
;
1818 isif
->video_out
.vpfe_dev
= vpfe_dev
;
1820 /* connect isif to video node */
1821 ret
= media_entity_create_link(&isif
->subdev
.entity
, 1,
1822 &isif
->video_out
.video_dev
.entity
,
1825 goto out_create_link
;
1828 vpfe_video_unregister(&isif
->video_out
);
1830 v4l2_device_unregister_subdev(&isif
->subdev
);
1834 /* -------------------------------------------------------------------
1835 * V4L2 subdev control operations
1838 static int vpfe_isif_s_ctrl(struct v4l2_ctrl
*ctrl
)
1840 struct vpfe_isif_device
*isif
=
1841 container_of(ctrl
->handler
, struct vpfe_isif_device
, ctrls
);
1842 struct isif_oper_config
*config
= &isif
->isif_cfg
;
1845 case VPFE_CID_DPCM_PREDICTOR
:
1846 config
->bayer
.dpcm_predictor
= ctrl
->val
;
1849 case VPFE_ISIF_CID_CRGAIN
:
1850 config
->isif_gain_params
.cr_gain
= ctrl
->val
;
1853 case VPFE_ISIF_CID_CGRGAIN
:
1854 config
->isif_gain_params
.cgr_gain
= ctrl
->val
;
1857 case VPFE_ISIF_CID_CGBGAIN
:
1858 config
->isif_gain_params
.cgb_gain
= ctrl
->val
;
1861 case VPFE_ISIF_CID_CBGAIN
:
1862 config
->isif_gain_params
.cb_gain
= ctrl
->val
;
1865 case VPFE_ISIF_CID_GAIN_OFFSET
:
1866 config
->isif_gain_params
.offset
= ctrl
->val
;
1875 static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops
= {
1876 .s_ctrl
= vpfe_isif_s_ctrl
,
1879 static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred
= {
1880 .ops
= &vpfe_isif_ctrl_ops
,
1881 .id
= VPFE_CID_DPCM_PREDICTOR
,
1882 .name
= "DPCM Predictor",
1883 .type
= V4L2_CTRL_TYPE_INTEGER
,
1890 static const struct v4l2_ctrl_config vpfe_isif_crgain
= {
1891 .ops
= &vpfe_isif_ctrl_ops
,
1892 .id
= VPFE_ISIF_CID_CRGAIN
,
1894 .type
= V4L2_CTRL_TYPE_INTEGER
,
1896 .max
= (1 << 12) - 1,
1901 static const struct v4l2_ctrl_config vpfe_isif_cgrgain
= {
1902 .ops
= &vpfe_isif_ctrl_ops
,
1903 .id
= VPFE_ISIF_CID_CGRGAIN
,
1905 .type
= V4L2_CTRL_TYPE_INTEGER
,
1907 .max
= (1 << 12) - 1,
1912 static const struct v4l2_ctrl_config vpfe_isif_cgbgain
= {
1913 .ops
= &vpfe_isif_ctrl_ops
,
1914 .id
= VPFE_ISIF_CID_CGBGAIN
,
1916 .type
= V4L2_CTRL_TYPE_INTEGER
,
1918 .max
= (1 << 12) - 1,
1923 static const struct v4l2_ctrl_config vpfe_isif_cbgain
= {
1924 .ops
= &vpfe_isif_ctrl_ops
,
1925 .id
= VPFE_ISIF_CID_CBGAIN
,
1927 .type
= V4L2_CTRL_TYPE_INTEGER
,
1929 .max
= (1 << 12) - 1,
1934 static const struct v4l2_ctrl_config vpfe_isif_gain_offset
= {
1935 .ops
= &vpfe_isif_ctrl_ops
,
1936 .id
= VPFE_ISIF_CID_GAIN_OFFSET
,
1937 .name
= "Gain Offset",
1938 .type
= V4L2_CTRL_TYPE_INTEGER
,
1940 .max
= (1 << 12) - 1,
1945 static void isif_remove(struct vpfe_isif_device
*isif
,
1946 struct platform_device
*pdev
)
1948 struct resource
*res
;
1951 iounmap(isif
->isif_cfg
.base_addr
);
1952 iounmap(isif
->isif_cfg
.linear_tbl0_addr
);
1953 iounmap(isif
->isif_cfg
.linear_tbl1_addr
);
1956 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, i
);
1958 release_mem_region(res
->start
,
1959 resource_size(res
));
1964 static void isif_config_defaults(struct vpfe_isif_device
*isif
)
1966 isif
->isif_cfg
.ycbcr
.v4l2_pix_fmt
= V4L2_PIX_FMT_UYVY
;
1967 isif
->isif_cfg
.ycbcr
.pix_fmt
= ISIF_PIXFMT_YCBCR_8BIT
;
1968 isif
->isif_cfg
.ycbcr
.frm_fmt
= ISIF_FRMFMT_INTERLACED
;
1969 isif
->isif_cfg
.ycbcr
.fid_pol
= VPFE_PINPOL_POSITIVE
;
1970 isif
->isif_cfg
.ycbcr
.vd_pol
= VPFE_PINPOL_POSITIVE
;
1971 isif
->isif_cfg
.ycbcr
.hd_pol
= VPFE_PINPOL_POSITIVE
;
1972 isif
->isif_cfg
.ycbcr
.pix_order
= ISIF_PIXORDER_CBYCRY
;
1973 isif
->isif_cfg
.ycbcr
.buf_type
= ISIF_BUFTYPE_FLD_INTERLEAVED
;
1975 isif
->isif_cfg
.bayer
.v4l2_pix_fmt
= V4L2_PIX_FMT_SGRBG10ALAW8
;
1976 isif
->isif_cfg
.bayer
.pix_fmt
= ISIF_PIXFMT_RAW
;
1977 isif
->isif_cfg
.bayer
.frm_fmt
= ISIF_FRMFMT_PROGRESSIVE
;
1978 isif
->isif_cfg
.bayer
.fid_pol
= VPFE_PINPOL_POSITIVE
;
1979 isif
->isif_cfg
.bayer
.vd_pol
= VPFE_PINPOL_POSITIVE
;
1980 isif
->isif_cfg
.bayer
.hd_pol
= VPFE_PINPOL_POSITIVE
;
1981 isif
->isif_cfg
.bayer
.cfa_pat
= ISIF_CFA_PAT_MOSAIC
;
1982 isif
->isif_cfg
.bayer
.data_msb
= ISIF_BIT_MSB_11
;
1983 isif
->isif_cfg
.data_pack
= ISIF_PACK_8BIT
;
1986 * vpfe_isif_init() - Initialize V4L2 subdev and media entity
1987 * @isif: VPFE isif module
1988 * @pdev: Pointer to platform device structure.
1989 * Return 0 on success and a negative error code on failure.
1991 int vpfe_isif_init(struct vpfe_isif_device
*isif
, struct platform_device
*pdev
)
1993 struct v4l2_subdev
*sd
= &isif
->subdev
;
1994 struct media_pad
*pads
= &isif
->pads
[0];
1995 struct media_entity
*me
= &sd
->entity
;
1996 static resource_size_t res_len
;
1997 struct resource
*res
;
2002 /* Get the ISIF base address, linearization table0 and table1 addr. */
2004 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, i
);
2007 goto fail_nobase_res
;
2009 res_len
= resource_size(res
);
2010 res
= request_mem_region(res
->start
, res_len
, res
->name
);
2013 goto fail_nobase_res
;
2015 addr
= ioremap_nocache(res
->start
, res_len
);
2018 goto fail_base_iomap
;
2022 /* ISIF base address */
2023 isif
->isif_cfg
.base_addr
= addr
;
2026 /* ISIF linear tbl0 address */
2027 isif
->isif_cfg
.linear_tbl0_addr
= addr
;
2030 /* ISIF linear tbl0 address */
2031 isif
->isif_cfg
.linear_tbl1_addr
= addr
;
2036 davinci_cfg_reg(DM365_VIN_CAM_WEN
);
2037 davinci_cfg_reg(DM365_VIN_CAM_VD
);
2038 davinci_cfg_reg(DM365_VIN_CAM_HD
);
2039 davinci_cfg_reg(DM365_VIN_YIN4_7_EN
);
2040 davinci_cfg_reg(DM365_VIN_YIN0_3_EN
);
2043 isif
->video_out
.ops
= &isif_video_ops
;
2044 v4l2_subdev_init(sd
, &isif_v4l2_ops
);
2045 sd
->internal_ops
= &isif_v4l2_internal_ops
;
2046 strlcpy(sd
->name
, "DAVINCI ISIF", sizeof(sd
->name
));
2047 sd
->grp_id
= 1 << 16; /* group ID for davinci subdevs */
2048 v4l2_set_subdevdata(sd
, isif
);
2049 sd
->flags
|= V4L2_SUBDEV_FL_HAS_EVENTS
| V4L2_SUBDEV_FL_HAS_DEVNODE
;
2050 pads
[ISIF_PAD_SINK
].flags
= MEDIA_PAD_FL_SINK
;
2051 pads
[ISIF_PAD_SOURCE
].flags
= MEDIA_PAD_FL_SOURCE
;
2053 isif
->input
= ISIF_INPUT_NONE
;
2054 isif
->output
= ISIF_OUTPUT_NONE
;
2055 me
->ops
= &isif_media_ops
;
2056 status
= media_entity_init(me
, ISIF_PADS_NUM
, pads
, 0);
2059 isif
->video_out
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
2060 status
= vpfe_video_init(&isif
->video_out
, "ISIF");
2062 pr_err("Failed to init isif-out video device\n");
2065 v4l2_ctrl_handler_init(&isif
->ctrls
, 6);
2066 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_crgain
, NULL
);
2067 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_cgrgain
, NULL
);
2068 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_cgbgain
, NULL
);
2069 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_cbgain
, NULL
);
2070 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_gain_offset
, NULL
);
2071 v4l2_ctrl_new_custom(&isif
->ctrls
, &vpfe_isif_dpcm_pred
, NULL
);
2073 v4l2_ctrl_handler_setup(&isif
->ctrls
);
2074 sd
->ctrl_handler
= &isif
->ctrls
;
2075 isif_config_defaults(isif
);
2078 release_mem_region(res
->start
, res_len
);
2081 if (isif
->isif_cfg
.base_addr
)
2082 iounmap(isif
->isif_cfg
.base_addr
);
2083 if (isif
->isif_cfg
.linear_tbl0_addr
)
2084 iounmap(isif
->isif_cfg
.linear_tbl0_addr
);
2087 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, i
);
2088 release_mem_region(res
->start
, res_len
);
2093 v4l2_ctrl_handler_free(&isif
->ctrls
);
2094 isif_remove(isif
, pdev
);
2099 * vpfe_isif_cleanup - isif module cleanup
2100 * @isif: pointer to isif subdevice
2101 * @dev: pointer to platform device structure
2104 vpfe_isif_cleanup(struct vpfe_isif_device
*isif
, struct platform_device
*pdev
)
2106 isif_remove(isif
, pdev
);