]> Pileus Git - ~andy/linux/blob - drivers/staging/media/davinci_vpfe/dm365_isif.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[~andy/linux] / drivers / staging / media / davinci_vpfe / dm365_isif.c
1 /*
2  * Copyright (C) 2012 Texas Instruments Inc
3  *
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.
7  *
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.
12  *
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
16  *
17  * Contributors:
18  *      Manjunath Hadli <manjunath.hadli@ti.com>
19  *      Prabhakar Lad <prabhakar.lad@ti.com>
20  */
21
22 #include "dm365_isif.h"
23 #include "vpfe_mc_capture.h"
24
25 #define MAX_WIDTH       4096
26 #define MAX_HEIGHT      4096
27
28 static const unsigned int isif_fmts[] = {
29         V4L2_MBUS_FMT_YUYV8_2X8,
30         V4L2_MBUS_FMT_UYVY8_2X8,
31         V4L2_MBUS_FMT_YUYV8_1X16,
32         V4L2_MBUS_FMT_YUYV10_1X20,
33         V4L2_MBUS_FMT_SGRBG12_1X12,
34         V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
35         V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
36 };
37
38 #define ISIF_COLPTN_R_Ye        0x0
39 #define ISIF_COLPTN_Gr_Cy       0x1
40 #define ISIF_COLPTN_Gb_G        0x2
41 #define ISIF_COLPTN_B_Mg        0x3
42
43 #define ISIF_CCOLP_CP01_0       0
44 #define ISIF_CCOLP_CP03_2       2
45 #define ISIF_CCOLP_CP05_4       4
46 #define ISIF_CCOLP_CP07_6       6
47 #define ISIF_CCOLP_CP11_0       8
48 #define ISIF_CCOLP_CP13_2       10
49 #define ISIF_CCOLP_CP15_4       12
50 #define ISIF_CCOLP_CP17_6       14
51
52 static const u32 isif_sgrbg_pattern =
53         ISIF_COLPTN_Gr_Cy <<  ISIF_CCOLP_CP01_0 |
54         ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP03_2 |
55         ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP05_4 |
56         ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP07_6 |
57         ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP11_0 |
58         ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP13_2 |
59         ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP15_4 |
60         ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP17_6;
61
62 static const u32 isif_srggb_pattern =
63         ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP01_0 |
64         ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP03_2 |
65         ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP05_4 |
66         ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP07_6 |
67         ISIF_COLPTN_R_Ye  << ISIF_CCOLP_CP11_0 |
68         ISIF_COLPTN_Gr_Cy << ISIF_CCOLP_CP13_2 |
69         ISIF_COLPTN_Gb_G  << ISIF_CCOLP_CP15_4 |
70         ISIF_COLPTN_B_Mg  << ISIF_CCOLP_CP17_6;
71
72 static inline u32 isif_read(void *__iomem base_addr, u32 offset)
73 {
74         return readl(base_addr + offset);
75 }
76
77 static inline void isif_write(void *__iomem base_addr, u32 val, u32 offset)
78 {
79         writel(val, base_addr + offset);
80 }
81
82 static inline u32 isif_merge(void *__iomem base_addr, u32 mask, u32 val,
83                              u32 offset)
84 {
85         u32 new_val = (isif_read(base_addr, offset) & ~mask) | (val & mask);
86
87         isif_write(base_addr, new_val, offset);
88
89         return new_val;
90 }
91
92 static void isif_enable_output_to_sdram(struct vpfe_isif_device *isif, int en)
93 {
94         isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_WEN_MASK,
95                    en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN);
96 }
97
98 static inline void
99 isif_regw_lin_tbl(struct vpfe_isif_device *isif, u32 val, u32 offset, int i)
100 {
101         if (!i)
102                 writel(val, isif->isif_cfg.linear_tbl0_addr + offset);
103         else
104                 writel(val, isif->isif_cfg.linear_tbl1_addr + offset);
105 }
106
107 static void isif_disable_all_modules(struct vpfe_isif_device *isif)
108 {
109         /* disable BC */
110         isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG);
111         /* disable vdfc */
112         isif_write(isif->isif_cfg.base_addr, 0, DFCCTL);
113         /* disable CSC */
114         isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
115         /* disable linearization */
116         isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
117 }
118
119 static void isif_enable(struct vpfe_isif_device *isif, int en)
120 {
121         if (!en)
122                 /* Before disable isif, disable all ISIF modules */
123                 isif_disable_all_modules(isif);
124
125         /*
126          * wait for next VD. Assume lowest scan rate is 12 Hz. So
127          * 100 msec delay is good enough
128          */
129         msleep(100);
130         isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK,
131                    en, SYNCEN);
132 }
133
134 /*
135  * ISIF helper functions
136  */
137
138 #define DM365_ISIF_MDFS_OFFSET          15
139 #define DM365_ISIF_MDFS_MASK            0x1
140
141 /* get field id in isif hardware */
142 enum v4l2_field vpfe_isif_get_fid(struct vpfe_device *vpfe_dev)
143 {
144         struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
145         u32 field_status;
146
147         field_status = isif_read(isif->isif_cfg.base_addr, MODESET);
148         field_status = (field_status >> DM365_ISIF_MDFS_OFFSET) &
149                         DM365_ISIF_MDFS_MASK;
150         return field_status;
151 }
152
153 static int
154 isif_set_pixel_format(struct vpfe_isif_device *isif, unsigned int pixfmt)
155 {
156         if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
157                 if (pixfmt == V4L2_PIX_FMT_SBGGR16)
158                         isif->isif_cfg.data_pack = ISIF_PACK_16BIT;
159                 else if ((pixfmt == V4L2_PIX_FMT_SGRBG10DPCM8) ||
160                                 (pixfmt == V4L2_PIX_FMT_SGRBG10ALAW8))
161                         isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
162                 else
163                         return -EINVAL;
164
165                 isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
166                 isif->isif_cfg.bayer.v4l2_pix_fmt = pixfmt;
167         } else {
168                 if (pixfmt == V4L2_PIX_FMT_YUYV)
169                         isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_YCBYCR;
170                 else if (pixfmt == V4L2_PIX_FMT_UYVY)
171                         isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
172                 else
173                         return -EINVAL;
174
175                 isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
176                 isif->isif_cfg.ycbcr.v4l2_pix_fmt = pixfmt;
177         }
178
179         return 0;
180 }
181
182 static int
183 isif_set_frame_format(struct vpfe_isif_device *isif,
184                       enum isif_frmfmt frm_fmt)
185 {
186         if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
187                 isif->isif_cfg.bayer.frm_fmt = frm_fmt;
188         else
189                 isif->isif_cfg.ycbcr.frm_fmt = frm_fmt;
190
191         return 0;
192 }
193
194 static int isif_set_image_window(struct vpfe_isif_device *isif)
195 {
196         struct v4l2_rect *win = &isif->crop;
197
198         if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12) {
199                 isif->isif_cfg.bayer.win.top = win->top;
200                 isif->isif_cfg.bayer.win.left = win->left;
201                 isif->isif_cfg.bayer.win.width = win->width;
202                 isif->isif_cfg.bayer.win.height = win->height;
203                 return 0;
204         }
205         isif->isif_cfg.ycbcr.win.top = win->top;
206         isif->isif_cfg.ycbcr.win.left = win->left;
207         isif->isif_cfg.ycbcr.win.width = win->width;
208         isif->isif_cfg.ycbcr.win.height = win->height;
209
210         return 0;
211 }
212
213 static int
214 isif_set_buftype(struct vpfe_isif_device *isif, enum isif_buftype buf_type)
215 {
216         if (isif->formats[ISIF_PAD_SINK].code == V4L2_MBUS_FMT_SGRBG12_1X12)
217                 isif->isif_cfg.bayer.buf_type = buf_type;
218         else
219                 isif->isif_cfg.ycbcr.buf_type = buf_type;
220
221         return 0;
222 }
223
224 /* configure format in isif hardware */
225 static int
226 isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad)
227 {
228         struct vpfe_isif_device *vpfe_isif = &vpfe_dev->vpfe_isif;
229         enum isif_frmfmt frm_fmt = ISIF_FRMFMT_INTERLACED;
230         struct v4l2_pix_format format;
231         int ret = 0;
232
233         v4l2_fill_pix_format(&format, &vpfe_dev->vpfe_isif.formats[pad]);
234         mbus_to_pix(&vpfe_dev->vpfe_isif.formats[pad], &format);
235
236         if (isif_set_pixel_format(vpfe_isif, format.pixelformat) < 0) {
237                 v4l2_err(&vpfe_dev->v4l2_dev,
238                          "Failed to set pixel format in isif\n");
239                 return -EINVAL;
240         }
241
242         /* call for s_crop will override these values */
243         vpfe_isif->crop.left = 0;
244         vpfe_isif->crop.top = 0;
245         vpfe_isif->crop.width = format.width;
246         vpfe_isif->crop.height = format.height;
247
248         /* configure the image window */
249         isif_set_image_window(vpfe_isif);
250
251         switch (vpfe_dev->vpfe_isif.formats[pad].field) {
252         case V4L2_FIELD_INTERLACED:
253                 /* do nothing, since it is default */
254                 ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_INTERLEAVED);
255                 break;
256
257         case V4L2_FIELD_NONE:
258                 frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
259                 /* buffer type only applicable for interlaced scan */
260                 break;
261
262         case V4L2_FIELD_SEQ_TB:
263                 ret = isif_set_buftype(vpfe_isif, ISIF_BUFTYPE_FLD_SEPARATED);
264                 break;
265
266         default:
267                 return -EINVAL;
268         }
269
270         /* set the frame format */
271         if (!ret)
272                 ret = isif_set_frame_format(vpfe_isif, frm_fmt);
273
274         return ret;
275 }
276
277 /*
278  * isif_try_format() - Try video format on a pad
279  * @isif: VPFE isif device
280  * @fh: V4L2 subdev file handle
281  * @fmt: pointer to v4l2 subdev format structure
282  */
283 static void
284 isif_try_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
285                 struct v4l2_subdev_format *fmt)
286 {
287         unsigned int width = fmt->format.width;
288         unsigned int height = fmt->format.height;
289         unsigned int i;
290
291         for (i = 0; i < ARRAY_SIZE(isif_fmts); i++) {
292                 if (fmt->format.code == isif_fmts[i])
293                         break;
294         }
295
296         /* If not found, use YUYV8_2x8 as default */
297         if (i >= ARRAY_SIZE(isif_fmts))
298                 fmt->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
299
300         /* Clamp the size. */
301         fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH);
302         fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT);
303
304         /* The data formatter truncates the number of horizontal output
305          * pixels to a multiple of 16. To avoid clipping data, allow
306          * callers to request an output size bigger than the input size
307          * up to the nearest multiple of 16.
308          */
309         if (fmt->pad == ISIF_PAD_SOURCE)
310                 fmt->format.width &= ~15;
311 }
312
313 /*
314  * vpfe_isif_buffer_isr() - isif module non-progressive buffer scheduling isr
315  * @isif: Pointer to isif subdevice.
316  */
317 void vpfe_isif_buffer_isr(struct vpfe_isif_device *isif)
318 {
319         struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
320         struct vpfe_video_device *video = &isif->video_out;
321         enum v4l2_field field;
322         int fid;
323
324         if (!video->started)
325                 return;
326
327         field = video->fmt.fmt.pix.field;
328
329         if (field == V4L2_FIELD_NONE) {
330                 /* handle progressive frame capture */
331                 if (video->cur_frm != video->next_frm)
332                         vpfe_video_process_buffer_complete(video);
333                 return;
334         }
335
336         /* interlaced or TB capture check which field we
337          * are in hardware
338          */
339         fid = vpfe_isif_get_fid(vpfe_dev);
340
341         /* switch the software maintained field id */
342         video->field_id ^= 1;
343         if (fid == video->field_id) {
344                 /* we are in-sync here,continue */
345                 if (fid == 0) {
346                         /*
347                          * One frame is just being captured. If the
348                          * next frame is available, release the current
349                          * frame and move on
350                          */
351                         if (video->cur_frm != video->next_frm)
352                                 vpfe_video_process_buffer_complete(video);
353                         /*
354                          * based on whether the two fields are stored
355                          * interleavely or separately in memory,
356                          * reconfigure the ISIF memory address
357                          */
358                         if (field == V4L2_FIELD_SEQ_TB)
359                                 vpfe_video_schedule_bottom_field(video);
360                         return;
361                 }
362                 /*
363                  * if one field is just being captured configure
364                  * the next frame get the next frame from the
365                  * empty queue if no frame is available hold on
366                  * to the current buffer
367                  */
368                 spin_lock(&video->dma_queue_lock);
369                 if (!list_empty(&video->dma_queue) &&
370                 video->cur_frm == video->next_frm)
371                         vpfe_video_schedule_next_buffer(video);
372                 spin_unlock(&video->dma_queue_lock);
373         } else if (fid == 0) {
374                 /*
375                  * out of sync. Recover from any hardware out-of-sync.
376                  * May loose one frame
377                  */
378                 video->field_id = fid;
379         }
380 }
381
382 /*
383  * vpfe_isif_vidint1_isr() - ISIF module progressive buffer scheduling isr
384  * @isif: Pointer to isif subdevice.
385  */
386 void vpfe_isif_vidint1_isr(struct vpfe_isif_device *isif)
387 {
388         struct vpfe_video_device *video = &isif->video_out;
389
390         if (!video->started)
391                 return;
392
393         spin_lock(&video->dma_queue_lock);
394         if (video->fmt.fmt.pix.field == V4L2_FIELD_NONE &&
395             !list_empty(&video->dma_queue) && video->cur_frm == video->next_frm)
396                 vpfe_video_schedule_next_buffer(video);
397
398         spin_unlock(&video->dma_queue_lock);
399 }
400
401 /*
402  * VPFE video operations
403  */
404
405 static int isif_video_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
406 {
407         struct vpfe_isif_device *isif = &vpfe_dev->vpfe_isif;
408
409         isif_write(isif->isif_cfg.base_addr, (addr >> 21) &
410                 ISIF_CADU_BITS, CADU);
411         isif_write(isif->isif_cfg.base_addr, (addr >> 5) &
412                 ISIF_CADL_BITS, CADL);
413
414         return 0;
415 }
416
417 static const struct vpfe_video_operations isif_video_ops = {
418         .queue = isif_video_queue,
419 };
420
421 /*
422  * V4L2 subdev operations
423  */
424
425 /* Parameter operations */
426 static int isif_get_params(struct v4l2_subdev *sd, void *params)
427 {
428         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
429
430         /* only raw module parameters can be set through the IOCTL */
431         if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
432                 return -EINVAL;
433         memcpy(params, &isif->isif_cfg.bayer.config_params,
434                         sizeof(isif->isif_cfg.bayer.config_params));
435         return 0;
436 }
437
438 static int isif_validate_df_csc_params(struct vpfe_isif_df_csc *df_csc)
439 {
440         struct vpfe_isif_color_space_conv *csc;
441         int err = -EINVAL;
442         int csc_df_en;
443         int i;
444
445         if (!df_csc->df_or_csc) {
446                 /* csc configuration */
447                 csc = &df_csc->csc;
448                 if (csc->en) {
449                         csc_df_en = 1;
450                         for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++)
451                                 if (csc->coeff[i].integer >
452                                     ISIF_CSC_COEF_INTEG_MASK ||
453                                     csc->coeff[i].decimal >
454                                     ISIF_CSC_COEF_DECIMAL_MASK) {
455                                         pr_err("Invalid CSC coefficients\n");
456                                         return err;
457                                 }
458                 }
459         }
460         if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) {
461                 pr_err("Invalid df_csc start pix value\n");
462                 return err;
463         }
464
465         if (df_csc->num_pixels > ISIF_DF_NUMPIX) {
466                 pr_err("Invalid df_csc num pixels value\n");
467                 return err;
468         }
469
470         if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) {
471                 pr_err("Invalid df_csc start_line value\n");
472                 return err;
473         }
474
475         if (df_csc->num_lines > ISIF_DF_NUMLINES) {
476                 pr_err("Invalid df_csc num_lines value\n");
477                 return err;
478         }
479
480         return 0;
481 }
482
483 #define DM365_ISIF_MAX_VDFLSFT          4
484 #define DM365_ISIF_MAX_VDFSLV           4095
485 #define DM365_ISIF_MAX_DFCMEM0          0x1fff
486 #define DM365_ISIF_MAX_DFCMEM1          0x1fff
487
488 static int isif_validate_dfc_params(struct vpfe_isif_dfc *dfc)
489 {
490         int err = -EINVAL;
491         int i;
492
493         if (!dfc->en)
494                 return 0;
495
496         if (dfc->corr_whole_line > 1) {
497                 pr_err("Invalid corr_whole_line value\n");
498                 return err;
499         }
500
501         if (dfc->def_level_shift > DM365_ISIF_MAX_VDFLSFT) {
502                 pr_err("Invalid def_level_shift value\n");
503                 return err;
504         }
505
506         if (dfc->def_sat_level > DM365_ISIF_MAX_VDFSLV) {
507                 pr_err("Invalid def_sat_level value\n");
508                 return err;
509         }
510
511         if (!dfc->num_vdefects ||
512             dfc->num_vdefects > VPFE_ISIF_VDFC_TABLE_SIZE) {
513                 pr_err("Invalid num_vdefects value\n");
514                 return err;
515         }
516
517         for (i = 0; i < VPFE_ISIF_VDFC_TABLE_SIZE; i++) {
518                 if (dfc->table[i].pos_vert > DM365_ISIF_MAX_DFCMEM0) {
519                         pr_err("Invalid pos_vert value\n");
520                         return err;
521                 }
522                 if (dfc->table[i].pos_horz > DM365_ISIF_MAX_DFCMEM1) {
523                         pr_err("Invalid pos_horz value\n");
524                         return err;
525                 }
526         }
527
528         return 0;
529 }
530
531 #define DM365_ISIF_MAX_CLVRV                    0xfff
532 #define DM365_ISIF_MAX_CLDC                     0x1fff
533 #define DM365_ISIF_MAX_CLHSH                    0x1fff
534 #define DM365_ISIF_MAX_CLHSV                    0x1fff
535 #define DM365_ISIF_MAX_CLVSH                    0x1fff
536 #define DM365_ISIF_MAX_CLVSV                    0x1fff
537 #define DM365_ISIF_MAX_HEIGHT_BLACK_REGION      0x1fff
538
539 static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp *bclamp)
540 {
541         int err = -EINVAL;
542
543         if (bclamp->dc_offset > DM365_ISIF_MAX_CLDC) {
544                 pr_err("Invalid bclamp dc_offset value\n");
545                 return err;
546         }
547         if (!bclamp->en)
548                 return 0;
549         if (bclamp->horz.clamp_pix_limit > 1) {
550                 pr_err("Invalid bclamp horz clamp_pix_limit value\n");
551                 return err;
552         }
553         if (bclamp->horz.win_count_calc < 1 ||
554                         bclamp->horz.win_count_calc > 32) {
555                 pr_err("Invalid bclamp horz win_count_calc value\n");
556                 return err;
557         }
558         if (bclamp->horz.win_start_h_calc > DM365_ISIF_MAX_CLHSH) {
559                 pr_err("Invalid bclamp win_start_v_calc value\n");
560                 return err;
561         }
562
563         if (bclamp->horz.win_start_v_calc > DM365_ISIF_MAX_CLHSV) {
564                 pr_err("Invalid bclamp win_start_v_calc value\n");
565                 return err;
566         }
567         if (bclamp->vert.reset_clamp_val > DM365_ISIF_MAX_CLVRV) {
568                 pr_err("Invalid bclamp reset_clamp_val value\n");
569                 return err;
570         }
571         if (bclamp->vert.ob_v_sz_calc > DM365_ISIF_MAX_HEIGHT_BLACK_REGION) {
572                 pr_err("Invalid bclamp ob_v_sz_calc value\n");
573                 return err;
574         }
575         if (bclamp->vert.ob_start_h > DM365_ISIF_MAX_CLVSH) {
576                 pr_err("Invalid bclamp ob_start_h value\n");
577                 return err;
578         }
579         if (bclamp->vert.ob_start_v > DM365_ISIF_MAX_CLVSV) {
580                 pr_err("Invalid bclamp ob_start_h value\n");
581                 return err;
582         }
583         return 0;
584 }
585
586 static int
587 isif_validate_raw_params(struct vpfe_isif_raw_config *params)
588 {
589         int ret;
590
591         ret = isif_validate_df_csc_params(&params->df_csc);
592         if (ret)
593                 return ret;
594         ret = isif_validate_dfc_params(&params->dfc);
595         if (ret)
596                 return ret;
597         ret = isif_validate_bclamp_params(&params->bclamp);
598         return ret;
599 }
600
601 static int isif_set_params(struct v4l2_subdev *sd, void *params)
602 {
603         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
604         struct vpfe_isif_raw_config isif_raw_params;
605         int ret = -EINVAL;
606
607         /* only raw module parameters can be set through the IOCTL */
608         if (isif->formats[ISIF_PAD_SINK].code != V4L2_MBUS_FMT_SGRBG12_1X12)
609                 return ret;
610
611         memcpy(&isif_raw_params, params, sizeof(isif_raw_params));
612         if (!isif_validate_raw_params(&isif_raw_params)) {
613                 memcpy(&isif->isif_cfg.bayer.config_params, &isif_raw_params,
614                         sizeof(isif_raw_params));
615                 ret = 0;
616         }
617         return ret;
618 }
619 /*
620  * isif_ioctl() - isif module private ioctl's
621  * @sd: VPFE isif V4L2 subdevice
622  * @cmd: ioctl command
623  * @arg: ioctl argument
624  *
625  * Return 0 on success or a negative error code otherwise.
626  */
627 static long isif_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
628 {
629         int ret;
630
631         switch (cmd) {
632         case VIDIOC_VPFE_ISIF_S_RAW_PARAMS:
633                 ret = isif_set_params(sd, arg);
634                 break;
635
636         case VIDIOC_VPFE_ISIF_G_RAW_PARAMS:
637                 ret = isif_get_params(sd, arg);
638                 break;
639
640         default:
641                 ret = -ENOIOCTLCMD;
642         }
643         return ret;
644 }
645
646 static void isif_config_gain_offset(struct vpfe_isif_device *isif)
647 {
648         struct vpfe_isif_gain_offsets_adj *gain_off_ptr =
649                 &isif->isif_cfg.bayer.config_params.gain_offset;
650         void *__iomem base = isif->isif_cfg.base_addr;
651         u32 val;
652
653         val = ((gain_off_ptr->gain_sdram_en & 1) << GAIN_SDRAM_EN_SHIFT) |
654               ((gain_off_ptr->gain_ipipe_en & 1) << GAIN_IPIPE_EN_SHIFT) |
655               ((gain_off_ptr->gain_h3a_en & 1) << GAIN_H3A_EN_SHIFT) |
656               ((gain_off_ptr->offset_sdram_en & 1) << OFST_SDRAM_EN_SHIFT) |
657               ((gain_off_ptr->offset_ipipe_en & 1) << OFST_IPIPE_EN_SHIFT) |
658               ((gain_off_ptr->offset_h3a_en & 1) << OFST_H3A_EN_SHIFT);
659         isif_merge(base, GAIN_OFFSET_EN_MASK, val, CGAMMAWD);
660
661         isif_write(base, isif->isif_cfg.isif_gain_params.cr_gain, CRGAIN);
662         isif_write(base, isif->isif_cfg.isif_gain_params.cgr_gain, CGRGAIN);
663         isif_write(base, isif->isif_cfg.isif_gain_params.cgb_gain, CGBGAIN);
664         isif_write(base, isif->isif_cfg.isif_gain_params.cb_gain, CBGAIN);
665         isif_write(base, isif->isif_cfg.isif_gain_params.offset & OFFSET_MASK,
666                    COFSTA);
667
668 }
669
670 static void isif_config_bclamp(struct vpfe_isif_device *isif,
671                    struct vpfe_isif_black_clamp *bc)
672 {
673         u32 val;
674
675         /**
676          * DC Offset is always added to image data irrespective of bc enable
677          * status
678          */
679         val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK;
680         isif_write(isif->isif_cfg.base_addr, val, CLDCOFST);
681
682         if (!bc->en)
683                 return;
684
685         val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) <<
686                 ISIF_BC_MODE_COLOR_SHIFT;
687
688         /* Enable BC and horizontal clamp calculation paramaters */
689         val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) <<
690               ISIF_HORZ_BC_MODE_SHIFT);
691
692         isif_write(isif->isif_cfg.base_addr, val, CLAMPCFG);
693
694         if (bc->horz.mode != VPFE_ISIF_HORZ_BC_DISABLE) {
695                 /*
696                  * Window count for calculation
697                  * Base window selection
698                  * pixel limit
699                  * Horizontal size of window
700                  * vertical size of the window
701                  * Horizontal start position of the window
702                  * Vertical start position of the window
703                  */
704                 val = (bc->horz.win_count_calc & ISIF_HORZ_BC_WIN_COUNT_MASK) |
705                       ((bc->horz.base_win_sel_calc & 1) <<
706                       ISIF_HORZ_BC_WIN_SEL_SHIFT) |
707                       ((bc->horz.clamp_pix_limit & 1) <<
708                       ISIF_HORZ_BC_PIX_LIMIT_SHIFT) |
709                       ((bc->horz.win_h_sz_calc &
710                       ISIF_HORZ_BC_WIN_H_SIZE_MASK) <<
711                       ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) |
712                       ((bc->horz.win_v_sz_calc &
713                       ISIF_HORZ_BC_WIN_V_SIZE_MASK) <<
714                       ISIF_HORZ_BC_WIN_V_SIZE_SHIFT);
715
716                 isif_write(isif->isif_cfg.base_addr, val, CLHWIN0);
717
718                 val = bc->horz.win_start_h_calc & ISIF_HORZ_BC_WIN_START_H_MASK;
719                 isif_write(isif->isif_cfg.base_addr, val, CLHWIN1);
720
721                 val = bc->horz.win_start_v_calc & ISIF_HORZ_BC_WIN_START_V_MASK;
722                 isif_write(isif->isif_cfg.base_addr, val, CLHWIN2);
723         }
724
725         /* vertical clamp calculation paramaters */
726         /* OB H Valid */
727         val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK;
728
729         /* Reset clamp value sel for previous line */
730         val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) <<
731                                 ISIF_VERT_BC_RST_VAL_SEL_SHIFT;
732
733         /* Line average coefficient */
734         val |= bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT;
735         isif_write(isif->isif_cfg.base_addr, val, CLVWIN0);
736
737         /* Configured reset value */
738         if (bc->vert.reset_val_sel == VPFE_ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) {
739                 val = bc->vert.reset_clamp_val & ISIF_VERT_BC_RST_VAL_MASK;
740                 isif_write(isif->isif_cfg.base_addr, val, CLVRV);
741         }
742
743         /* Optical Black horizontal start position */
744         val = bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK;
745         isif_write(isif->isif_cfg.base_addr, val, CLVWIN1);
746
747         /* Optical Black vertical start position */
748         val = bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK;
749         isif_write(isif->isif_cfg.base_addr, val, CLVWIN2);
750
751         val = bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK;
752         isif_write(isif->isif_cfg.base_addr, val, CLVWIN3);
753
754         /* Vertical start position for BC subtraction */
755         val = bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK;
756         isif_write(isif->isif_cfg.base_addr, val, CLSV);
757 }
758
759 /* This function will configure the window size to be capture in ISIF reg */
760 static void
761 isif_setwin(struct vpfe_isif_device *isif, struct v4l2_rect *image_win,
762             enum isif_frmfmt frm_fmt, int ppc, int mode)
763 {
764         int horz_nr_pixels;
765         int vert_nr_lines;
766         int horz_start;
767         int vert_start;
768         int mid_img;
769
770         /*
771          * ppc - per pixel count. indicates how many pixels per cell
772          * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
773          * raw capture this is 1
774          */
775         horz_start = image_win->left << (ppc - 1);
776         horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
777
778         /* Writing the horizontal info into the registers */
779         isif_write(isif->isif_cfg.base_addr,
780                    horz_start & START_PX_HOR_MASK, SPH);
781         isif_write(isif->isif_cfg.base_addr,
782                    horz_nr_pixels & NUM_PX_HOR_MASK, LNH);
783         vert_start = image_win->top;
784
785         if (frm_fmt == ISIF_FRMFMT_INTERLACED) {
786                 vert_nr_lines = (image_win->height >> 1) - 1;
787                 vert_start >>= 1;
788                 /* To account for VD since line 0 doesn't have any data */
789                 vert_start += 1;
790         } else {
791                 /* To account for VD since line 0 doesn't have any data */
792                 vert_start += 1;
793                 vert_nr_lines = image_win->height - 1;
794                 /* configure VDINT0 and VDINT1 */
795                 mid_img = vert_start + (image_win->height / 2);
796                 isif_write(isif->isif_cfg.base_addr, mid_img, VDINT1);
797         }
798
799         if (!mode)
800                 isif_write(isif->isif_cfg.base_addr, 0, VDINT0);
801         else
802                 isif_write(isif->isif_cfg.base_addr, vert_nr_lines, VDINT0);
803         isif_write(isif->isif_cfg.base_addr,
804                    vert_start & START_VER_ONE_MASK, SLV0);
805         isif_write(isif->isif_cfg.base_addr,
806                    vert_start & START_VER_TWO_MASK, SLV1);
807         isif_write(isif->isif_cfg.base_addr,
808                    vert_nr_lines & NUM_LINES_VER, LNV);
809 }
810
811 #define DM365_ISIF_DFCMWR_MEMORY_WRITE          1
812 #define DM365_ISIF_DFCMRD_MEMORY_READ           0x2
813
814 static void
815 isif_config_dfc(struct vpfe_isif_device *isif, struct vpfe_isif_dfc *vdfc)
816 {
817 #define DFC_WRITE_WAIT_COUNT    1000
818         u32 count = DFC_WRITE_WAIT_COUNT;
819         u32 val;
820         int i;
821
822         if (!vdfc->en)
823                 return;
824
825         /* Correction mode */
826         val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) <<
827                ISIF_VDFC_CORR_MOD_SHIFT;
828
829         /* Correct whole line or partial */
830         if (vdfc->corr_whole_line)
831                 val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT;
832
833         /* level shift value */
834         val |= (vdfc->def_level_shift & ISIF_VDFC_LEVEL_SHFT_MASK) <<
835                 ISIF_VDFC_LEVEL_SHFT_SHIFT;
836
837         isif_write(isif->isif_cfg.base_addr, val, DFCCTL);
838
839         /* Defect saturation level */
840         val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK;
841         isif_write(isif->isif_cfg.base_addr, val, VDFSATLV);
842
843         isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_vert &
844                    ISIF_VDFC_POS_MASK, DFCMEM0);
845         isif_write(isif->isif_cfg.base_addr, vdfc->table[0].pos_horz &
846                    ISIF_VDFC_POS_MASK, DFCMEM1);
847         if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
848             vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
849                 isif_write(isif->isif_cfg.base_addr,
850                            vdfc->table[0].level_at_pos, DFCMEM2);
851                 isif_write(isif->isif_cfg.base_addr,
852                            vdfc->table[0].level_up_pixels, DFCMEM3);
853                 isif_write(isif->isif_cfg.base_addr,
854                            vdfc->table[0].level_low_pixels, DFCMEM4);
855         }
856
857         val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
858         /* set DFCMARST and set DFCMWR */
859         val |= 1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT;
860         val |= 1;
861         isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
862
863         while (count && (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x01))
864                 count--;
865
866         val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
867         if (!count) {
868                 pr_debug("defect table write timeout !!\n");
869                 return;
870         }
871
872         for (i = 1; i < vdfc->num_vdefects; i++) {
873                 isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_vert &
874                         ISIF_VDFC_POS_MASK, DFCMEM0);
875
876                 isif_write(isif->isif_cfg.base_addr, vdfc->table[i].pos_horz &
877                         ISIF_VDFC_POS_MASK, DFCMEM1);
878
879                 if (vdfc->corr_mode == VPFE_ISIF_VDFC_NORMAL ||
880                     vdfc->corr_mode == VPFE_ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
881                         isif_write(isif->isif_cfg.base_addr,
882                                    vdfc->table[i].level_at_pos, DFCMEM2);
883                         isif_write(isif->isif_cfg.base_addr,
884                                    vdfc->table[i].level_up_pixels, DFCMEM3);
885                         isif_write(isif->isif_cfg.base_addr,
886                                    vdfc->table[i].level_low_pixels, DFCMEM4);
887                 }
888                 val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
889                 /* clear DFCMARST and set DFCMWR */
890                 val &= ~(1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT);
891                 val |= 1;
892                 isif_write(isif->isif_cfg.base_addr, val, DFCMEMCTL);
893
894                 count = DFC_WRITE_WAIT_COUNT;
895                 while (count && (isif_read(isif->isif_cfg.base_addr,
896                         DFCMEMCTL) & 0x01))
897                         count--;
898
899                 val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
900                 if (!count) {
901                         pr_debug("defect table write timeout !!\n");
902                         return;
903                 }
904         }
905         if (vdfc->num_vdefects < VPFE_ISIF_VDFC_TABLE_SIZE) {
906                 /* Extra cycle needed */
907                 isif_write(isif->isif_cfg.base_addr, 0, DFCMEM0);
908                 isif_write(isif->isif_cfg.base_addr,
909                            DM365_ISIF_MAX_DFCMEM1, DFCMEM1);
910                 isif_write(isif->isif_cfg.base_addr,
911                            DM365_ISIF_DFCMWR_MEMORY_WRITE, DFCMEMCTL);
912         }
913         /* enable VDFC */
914         isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
915                    (1 << ISIF_VDFC_EN_SHIFT), DFCCTL);
916
917         isif_merge(isif->isif_cfg.base_addr, (1 << ISIF_VDFC_EN_SHIFT),
918                    (0 << ISIF_VDFC_EN_SHIFT), DFCCTL);
919
920         isif_write(isif->isif_cfg.base_addr, 0x6, DFCMEMCTL);
921         for (i = 0 ; i < vdfc->num_vdefects; i++) {
922                 count = DFC_WRITE_WAIT_COUNT;
923                 while (count &&
924                         (isif_read(isif->isif_cfg.base_addr, DFCMEMCTL) & 0x2))
925                         count--;
926                 val = isif_read(isif->isif_cfg.base_addr, DFCMEMCTL);
927                 if (!count) {
928                         pr_debug("defect table write timeout !!\n");
929                         return;
930                 }
931                 isif_write(isif->isif_cfg.base_addr,
932                            DM365_ISIF_DFCMRD_MEMORY_READ, DFCMEMCTL);
933         }
934 }
935
936 static void
937 isif_config_csc(struct vpfe_isif_device *isif, struct vpfe_isif_df_csc *df_csc)
938 {
939         u32 val1;
940         u32 val2;
941         u32 i;
942
943         if (!df_csc->csc.en) {
944                 isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
945                 return;
946         }
947         /* initialize all bits to 0 */
948         val1 = 0;
949         for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) {
950                 if ((i % 2) == 0) {
951                         /* CSCM - LSB */
952                         val1 = ((df_csc->csc.coeff[i].integer &
953                                 ISIF_CSC_COEF_INTEG_MASK) <<
954                                 ISIF_CSC_COEF_INTEG_SHIFT) |
955                                 ((df_csc->csc.coeff[i].decimal &
956                                 ISIF_CSC_COEF_DECIMAL_MASK));
957                 } else {
958
959                         /* CSCM - MSB */
960                         val2 = ((df_csc->csc.coeff[i].integer &
961                                 ISIF_CSC_COEF_INTEG_MASK) <<
962                                 ISIF_CSC_COEF_INTEG_SHIFT) |
963                                 ((df_csc->csc.coeff[i].decimal &
964                                 ISIF_CSC_COEF_DECIMAL_MASK));
965                         val2 <<= ISIF_CSCM_MSB_SHIFT;
966                         val2 |= val1;
967                         isif_write(isif->isif_cfg.base_addr, val2,
968                                    (CSCM0 + ((i-1) << 1)));
969                 }
970         }
971         /* program the active area */
972         isif_write(isif->isif_cfg.base_addr, df_csc->start_pix &
973                 ISIF_DF_CSC_SPH_MASK, FMTSPH);
974         /*
975          * one extra pixel as required for CSC. Actually number of
976          * pixel - 1 should be configured in this register. So we
977          * need to subtract 1 before writing to FMTSPH, but we will
978          * not do this since csc requires one extra pixel
979          */
980         isif_write(isif->isif_cfg.base_addr, df_csc->num_pixels &
981                 ISIF_DF_CSC_SPH_MASK, FMTLNH);
982         isif_write(isif->isif_cfg.base_addr, df_csc->start_line &
983                 ISIF_DF_CSC_SPH_MASK, FMTSLV);
984         /*
985          * one extra line as required for CSC. See reason documented for
986          * num_pixels
987          */
988         isif_write(isif->isif_cfg.base_addr, df_csc->num_lines &
989                 ISIF_DF_CSC_SPH_MASK, FMTLNV);
990         /* Enable CSC */
991         isif_write(isif->isif_cfg.base_addr, 1, CSCCTL);
992 }
993
994 static void
995 isif_config_linearization(struct vpfe_isif_device *isif,
996                           struct vpfe_isif_linearize *linearize)
997 {
998         u32 val;
999         u32 i;
1000
1001         if (!linearize->en) {
1002                 isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
1003                 return;
1004         }
1005         /* shift value for correction */
1006         val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) <<
1007               ISIF_LIN_CORRSFT_SHIFT;
1008         /* enable */
1009         val |= 1;
1010         isif_write(isif->isif_cfg.base_addr, val, LINCFG0);
1011         /* Scale factor */
1012         val = (linearize->scale_fact.integer & 1) <<
1013               ISIF_LIN_SCALE_FACT_INTEG_SHIFT;
1014         val |= linearize->scale_fact.decimal & ISIF_LIN_SCALE_FACT_DECIMAL_MASK;
1015         isif_write(isif->isif_cfg.base_addr, val, LINCFG1);
1016
1017         for (i = 0; i < VPFE_ISIF_LINEAR_TAB_SIZE; i++) {
1018                 val = linearize->table[i] & ISIF_LIN_ENTRY_MASK;
1019                 if (i%2)
1020                         isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 1);
1021                 else
1022                         isif_regw_lin_tbl(isif, val, ((i >> 1) << 2), 0);
1023         }
1024 }
1025
1026 static void
1027 isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul)
1028 {
1029         u32 val;
1030
1031         /* Horizontal pattern */
1032         val = cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT;
1033         val |= cul->hcpat_odd;
1034         isif_write(isif->isif_cfg.base_addr, val, CULH);
1035         /* vertical pattern */
1036         isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV);
1037         /* LPF */
1038         isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT,
1039                    cul->en_lpf << ISIF_LPF_SHIFT, MODESET);
1040 }
1041
1042 static int isif_get_pix_fmt(u32 mbus_code)
1043 {
1044         switch (mbus_code) {
1045         case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
1046         case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
1047         case V4L2_MBUS_FMT_SGRBG12_1X12:
1048                 return ISIF_PIXFMT_RAW;
1049
1050         case V4L2_MBUS_FMT_YUYV8_2X8:
1051         case V4L2_MBUS_FMT_UYVY8_2X8:
1052         case V4L2_MBUS_FMT_YUYV10_2X10:
1053         case V4L2_MBUS_FMT_Y8_1X8:
1054                 return ISIF_PIXFMT_YCBCR_8BIT;
1055
1056         case V4L2_MBUS_FMT_YUYV8_1X16:
1057         case V4L2_MBUS_FMT_YUYV10_1X20:
1058                 return ISIF_PIXFMT_YCBCR_16BIT;
1059
1060         default:
1061                 break;
1062         }
1063         return -EINVAL;
1064 }
1065
1066 #define ISIF_INTERLACE_INVERSE_MODE             0x4b6d
1067 #define ISIF_INTERLACE_NON_INVERSE_MODE         0x0b6d
1068 #define ISIF_PROGRESSIVE_INVERSE_MODE           0x4000
1069 #define ISIF_PROGRESSIVE_NON_INVERSE_MODE       0x0000
1070
1071 static int isif_config_raw(struct v4l2_subdev *sd, int mode)
1072 {
1073         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1074         struct isif_params_raw *params = &isif->isif_cfg.bayer;
1075         struct vpfe_isif_raw_config *module_params =
1076                                 &isif->isif_cfg.bayer.config_params;
1077         struct v4l2_mbus_framefmt *format;
1078         int pix_fmt;
1079         u32 val;
1080
1081         format = &isif->formats[ISIF_PAD_SINK];
1082
1083         /* In case of user has set BT656IF earlier, it should be reset
1084          * when configuring for raw input.
1085          */
1086         isif_write(isif->isif_cfg.base_addr, 0, REC656IF);
1087         /* Configure CCDCFG register
1088          * Set CCD Not to swap input since input is RAW data
1089          * Set FID detection function to Latch at V-Sync
1090          * Set WENLOG - isif valid area
1091          * Set TRGSEL
1092          * Set EXTRG
1093          * Packed to 8 or 16 bits
1094          */
1095         val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC |
1096               ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN |
1097               ISIF_CCDCFG_EXTRG_DISABLE | (isif->isif_cfg.data_pack &
1098               ISIF_DATA_PACK_MASK);
1099         isif_write(isif->isif_cfg.base_addr, val, CCDCFG);
1100
1101         pix_fmt = isif_get_pix_fmt(format->code);
1102         if (pix_fmt < 0) {
1103                 pr_debug("Invalid pix_fmt(input mode)\n");
1104                 return -EINVAL;
1105         }
1106         /*
1107          * Configure the vertical sync polarity(MODESET.VDPOL)
1108          * Configure the horizontal sync polarity (MODESET.HDPOL)
1109          * Configure frame id polarity (MODESET.FLDPOL)
1110          * Configure data polarity
1111          * Configure External WEN Selection
1112          * Configure frame format(progressive or interlace)
1113          * Configure pixel format (Input mode)
1114          * Configure the data shift
1115          */
1116         val = ISIF_VDHDOUT_INPUT | ((params->vd_pol & ISIF_VD_POL_MASK) <<
1117               ISIF_VD_POL_SHIFT) | ((params->hd_pol & ISIF_HD_POL_MASK) <<
1118               ISIF_HD_POL_SHIFT) | ((params->fid_pol & ISIF_FID_POL_MASK) <<
1119               ISIF_FID_POL_SHIFT) | ((ISIF_DATAPOL_NORMAL &
1120               ISIF_DATAPOL_MASK) << ISIF_DATAPOL_SHIFT) | ((ISIF_EXWEN_DISABLE &
1121               ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) | ((params->frm_fmt &
1122               ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) | ((pix_fmt &
1123               ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT);
1124
1125         /* currently only V4L2_MBUS_FMT_SGRBG12_1X12 is
1126          * supported. shift appropriately depending on
1127          * different MBUS fmt's added
1128          */
1129         if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
1130                 val |= ((VPFE_ISIF_NO_SHIFT &
1131                         ISIF_DATASFT_MASK) << ISIF_DATASFT_SHIFT);
1132
1133         isif_write(isif->isif_cfg.base_addr, val, MODESET);
1134         /*
1135          * Configure GAMMAWD register
1136          * CFA pattern setting
1137          */
1138         val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) <<
1139                 ISIF_GAMMAWD_CFA_SHIFT;
1140         /* Gamma msb */
1141         if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10ALAW8)
1142                 val = val | ISIF_ALAW_ENABLE;
1143
1144         val = val | ((params->data_msb & ISIF_ALAW_GAMA_WD_MASK) <<
1145                         ISIF_ALAW_GAMA_WD_SHIFT);
1146
1147         isif_write(isif->isif_cfg.base_addr, val, CGAMMAWD);
1148         /* Configure DPCM compression settings */
1149         if (params->v4l2_pix_fmt == V4L2_PIX_FMT_SGRBG10DPCM8) {
1150                 val =  1 << ISIF_DPCM_EN_SHIFT;
1151                 val |= (params->dpcm_predictor &
1152                         ISIF_DPCM_PREDICTOR_MASK) << ISIF_DPCM_PREDICTOR_SHIFT;
1153         }
1154         isif_write(isif->isif_cfg.base_addr, val, MISC);
1155         /* Configure Gain & Offset */
1156         isif_config_gain_offset(isif);
1157         /* Configure Color pattern */
1158         if (format->code == V4L2_MBUS_FMT_SGRBG12_1X12)
1159                 val = isif_sgrbg_pattern;
1160         else
1161                 /* default set to rggb */
1162                 val = isif_srggb_pattern;
1163
1164         isif_write(isif->isif_cfg.base_addr, val, CCOLP);
1165
1166         /* Configure HSIZE register  */
1167         val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) <<
1168               ISIF_HSIZE_FLIP_SHIFT;
1169
1170         /* calculate line offset in 32 bytes based on pack value */
1171         if (isif->isif_cfg.data_pack == ISIF_PACK_8BIT)
1172                 val |= ((params->win.width + 31) >> 5) & ISIF_LINEOFST_MASK;
1173         else if (isif->isif_cfg.data_pack == ISIF_PACK_12BIT)
1174                 val |= ((((params->win.width + (params->win.width >> 2)) +
1175                         31) >> 5) & ISIF_LINEOFST_MASK);
1176         else
1177                 val |= (((params->win.width * 2) + 31) >> 5) &
1178                         ISIF_LINEOFST_MASK;
1179         isif_write(isif->isif_cfg.base_addr, val, HSIZE);
1180         /* Configure SDOFST register  */
1181         if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) {
1182                 if (params->image_invert_en)
1183                         /* For interlace inverse mode */
1184                         isif_write(isif->isif_cfg.base_addr,
1185                                    ISIF_INTERLACE_INVERSE_MODE, SDOFST);
1186                 else
1187                         /* For interlace non inverse mode */
1188                         isif_write(isif->isif_cfg.base_addr,
1189                                    ISIF_INTERLACE_NON_INVERSE_MODE, SDOFST);
1190         } else if (params->frm_fmt == ISIF_FRMFMT_PROGRESSIVE) {
1191                 if (params->image_invert_en)
1192                         isif_write(isif->isif_cfg.base_addr,
1193                                    ISIF_PROGRESSIVE_INVERSE_MODE, SDOFST);
1194                 else
1195                         /* For progessive non inverse mode */
1196                         isif_write(isif->isif_cfg.base_addr,
1197                                    ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST);
1198         }
1199         /* Configure video window */
1200         isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
1201         /* Configure Black Clamp */
1202         isif_config_bclamp(isif, &module_params->bclamp);
1203         /* Configure Vertical Defection Pixel Correction */
1204         isif_config_dfc(isif, &module_params->dfc);
1205         if (!module_params->df_csc.df_or_csc)
1206                 /* Configure Color Space Conversion */
1207                 isif_config_csc(isif, &module_params->df_csc);
1208
1209         isif_config_linearization(isif, &module_params->linearize);
1210         /* Configure Culling */
1211         isif_config_culling(isif, &module_params->culling);
1212         /* Configure Horizontal and vertical offsets(DFC,LSC,Gain) */
1213         val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK;
1214         isif_write(isif->isif_cfg.base_addr, val, DATAHOFST);
1215
1216         val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK;
1217         isif_write(isif->isif_cfg.base_addr, val, DATAVOFST);
1218
1219         return 0;
1220 }
1221
1222 #define DM365_ISIF_HSIZE_MASK           0xffffffe0
1223 #define DM365_ISIF_SDOFST_2_LINES       0x00000249
1224
1225 /* This function will configure ISIF for YCbCr parameters. */
1226 static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode)
1227 {
1228         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1229         struct isif_ycbcr_config *params = &isif->isif_cfg.ycbcr;
1230         struct v4l2_mbus_framefmt *format;
1231         int pix_fmt;
1232         u32 modeset;
1233         u32 ccdcfg;
1234
1235         format = &isif->formats[ISIF_PAD_SINK];
1236         /*
1237          * first reset the ISIF
1238          * all registers have default values after reset
1239          * This is important since we assume default values to be set in
1240          * a lot of registers that we didn't touch
1241          */
1242         /* start with all bits zero */
1243         ccdcfg = modeset = 0;
1244         pix_fmt = isif_get_pix_fmt(format->code);
1245         if (pix_fmt < 0) {
1246                 pr_debug("Invalid pix_fmt(input mode)\n");
1247                 return -EINVAL;
1248         }
1249         /* configure pixel format or input mode */
1250         modeset = modeset | ((pix_fmt & ISIF_INPUT_MASK) <<
1251                   ISIF_INPUT_SHIFT) | ((params->frm_fmt & ISIF_FRM_FMT_MASK) <<
1252                   ISIF_FRM_FMT_SHIFT) | (((params->fid_pol &
1253                   ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT)) |
1254                   (((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) |
1255                   (((params->vd_pol & ISIF_VD_POL_MASK) << ISIF_VD_POL_SHIFT));
1256         /* pack the data to 8-bit CCDCCFG */
1257         switch (format->code) {
1258         case V4L2_MBUS_FMT_YUYV8_2X8:
1259         case V4L2_MBUS_FMT_UYVY8_2X8:
1260                 if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
1261                         pr_debug("Invalid pix_fmt(input mode)\n");
1262                         return -EINVAL;
1263                 }
1264                 modeset |= ((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK) <<
1265                                 ISIF_VD_POL_SHIFT);
1266                 isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
1267                 ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR;
1268                 break;
1269
1270         case V4L2_MBUS_FMT_YUYV10_2X10:
1271                 if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
1272                         pr_debug("Invalid pix_fmt(input mode)\n");
1273                         return -EINVAL;
1274                 }
1275                 /* setup BT.656, embedded sync  */
1276                 isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
1277                 /* enable 10 bit mode in ccdcfg */
1278                 ccdcfg = ccdcfg | ISIF_PACK_8BIT | ISIF_YCINSWP_YCBCR |
1279                         ISIF_BW656_ENABLE;
1280                 break;
1281
1282         case V4L2_MBUS_FMT_YUYV10_1X20:
1283                 if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
1284                         pr_debug("Invalid pix_fmt(input mode)\n");
1285                         return -EINVAL;
1286                 }
1287                 isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
1288                 break;
1289
1290         case V4L2_MBUS_FMT_Y8_1X8:
1291                 ccdcfg |= ISIF_PACK_8BIT;
1292                 ccdcfg |= ISIF_YCINSWP_YCBCR;
1293                 if (pix_fmt != ISIF_PIXFMT_YCBCR_8BIT) {
1294                         pr_debug("Invalid pix_fmt(input mode)\n");
1295                         return -EINVAL;
1296                 }
1297                 break;
1298
1299         case V4L2_MBUS_FMT_YUYV8_1X16:
1300                 if (pix_fmt != ISIF_PIXFMT_YCBCR_16BIT) {
1301                         pr_debug("Invalid pix_fmt(input mode)\n");
1302                         return -EINVAL;
1303                 }
1304                 break;
1305
1306         default:
1307                 /* should never come here */
1308                 pr_debug("Invalid interface type\n");
1309                 return -EINVAL;
1310         }
1311         isif_write(isif->isif_cfg.base_addr, modeset, MODESET);
1312         /* Set up pix order */
1313         ccdcfg |= (params->pix_order & ISIF_PIX_ORDER_MASK) <<
1314                 ISIF_PIX_ORDER_SHIFT;
1315         isif_write(isif->isif_cfg.base_addr, ccdcfg, CCDCFG);
1316         /* configure video window */
1317         if (format->code == V4L2_MBUS_FMT_YUYV10_1X20 ||
1318                         format->code == V4L2_MBUS_FMT_YUYV8_1X16)
1319                 isif_setwin(isif, &params->win, params->frm_fmt, 1, mode);
1320         else
1321                 isif_setwin(isif, &params->win, params->frm_fmt, 2, mode);
1322
1323         /*
1324          * configure the horizontal line offset
1325          * this is done by rounding up width to a multiple of 16 pixels
1326          * and multiply by two to account for y:cb:cr 4:2:2 data
1327          */
1328         isif_write(isif->isif_cfg.base_addr,
1329                    ((((params->win.width * 2) + 31) &
1330                    DM365_ISIF_HSIZE_MASK) >> 5), HSIZE);
1331
1332         /* configure the memory line offset */
1333         if (params->frm_fmt == ISIF_FRMFMT_INTERLACED &&
1334             params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED)
1335                 /* two fields are interleaved in memory */
1336                 isif_write(isif->isif_cfg.base_addr,
1337                            DM365_ISIF_SDOFST_2_LINES, SDOFST);
1338         return 0;
1339 }
1340
1341 static int isif_configure(struct v4l2_subdev *sd, int mode)
1342 {
1343         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1344         struct v4l2_mbus_framefmt *format;
1345
1346         format = &isif->formats[ISIF_PAD_SINK];
1347
1348         switch (format->code) {
1349         case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
1350         case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
1351         case V4L2_MBUS_FMT_SGRBG12_1X12:
1352                 return isif_config_raw(sd, mode);
1353
1354         case V4L2_MBUS_FMT_YUYV8_2X8:
1355         case V4L2_MBUS_FMT_UYVY8_2X8:
1356         case V4L2_MBUS_FMT_YUYV10_2X10:
1357         case V4L2_MBUS_FMT_Y8_1X8:
1358         case V4L2_MBUS_FMT_YUYV8_1X16:
1359         case V4L2_MBUS_FMT_YUYV10_1X20:
1360                 return isif_config_ycbcr(sd, mode);
1361
1362         default:
1363                 break;
1364         }
1365         return -EINVAL;
1366 }
1367
1368 /*
1369  * isif_set_stream() - Enable/Disable streaming on the ISIF module
1370  * @sd: VPFE ISIF V4L2 subdevice
1371  * @enable: Enable/disable stream
1372  */
1373 static int isif_set_stream(struct v4l2_subdev *sd, int enable)
1374 {
1375         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1376         int ret;
1377
1378         if (enable) {
1379                 ret = isif_configure(sd,
1380                         (isif->output == ISIF_OUTPUT_MEMORY) ? 0 : 1);
1381                 if (ret)
1382                         return ret;
1383                 if (isif->output == ISIF_OUTPUT_MEMORY)
1384                         isif_enable_output_to_sdram(isif, 1);
1385                 isif_enable(isif, 1);
1386         } else {
1387                 isif_enable(isif, 0);
1388                 isif_enable_output_to_sdram(isif, 0);
1389         }
1390
1391         return 0;
1392 }
1393
1394 /*
1395  * __isif_get_format() - helper function for getting isif format
1396  * @isif: pointer to isif private structure.
1397  * @pad: pad number.
1398  * @fh: V4L2 subdev file handle.
1399  * @which: wanted subdev format.
1400  */
1401 static struct v4l2_mbus_framefmt *
1402 __isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
1403                   unsigned int pad, enum v4l2_subdev_format_whence which)
1404 {
1405         if (which == V4L2_SUBDEV_FORMAT_TRY) {
1406                 struct v4l2_subdev_format fmt;
1407
1408                 fmt.pad = pad;
1409                 fmt.which = which;
1410
1411                 return v4l2_subdev_get_try_format(fh, pad);
1412         }
1413         return &isif->formats[pad];
1414 }
1415
1416 /*
1417 * isif_set_format() - set format on pad
1418 * @sd    : VPFE ISIF device
1419 * @fh    : V4L2 subdev file handle
1420 * @fmt   : pointer to v4l2 subdev format structure
1421 *
1422 * Return 0 on success or -EINVAL if format or pad is invalid
1423 */
1424 static int
1425 isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1426                 struct v4l2_subdev_format *fmt)
1427 {
1428         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1429         struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
1430         struct v4l2_mbus_framefmt *format;
1431
1432         format = __isif_get_format(isif, fh, fmt->pad, fmt->which);
1433         if (format == NULL)
1434                 return -EINVAL;
1435
1436         isif_try_format(isif, fh, fmt);
1437         memcpy(format, &fmt->format, sizeof(*format));
1438
1439         if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
1440                 return 0;
1441
1442         if (fmt->pad == ISIF_PAD_SOURCE)
1443                 return isif_config_format(vpfe_dev, fmt->pad);
1444
1445         return 0;
1446 }
1447
1448 /*
1449  * isif_get_format() - Retrieve the video format on a pad
1450  * @sd: VPFE ISIF V4L2 subdevice
1451  * @fh: V4L2 subdev file handle
1452  * @fmt: pointer to v4l2 subdev format structure
1453  *
1454  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
1455  * to the format type.
1456  */
1457 static int
1458 isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1459                 struct v4l2_subdev_format *fmt)
1460 {
1461         struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
1462         struct v4l2_mbus_framefmt *format;
1463
1464         format = __isif_get_format(vpfe_isif, fh, fmt->pad, fmt->which);
1465         if (format == NULL)
1466                 return -EINVAL;
1467
1468         memcpy(&fmt->format, format, sizeof(fmt->format));
1469
1470         return 0;
1471 }
1472
1473 /*
1474  * isif_enum_frame_size() - enum frame sizes on pads
1475  * @sd: VPFE isif V4L2 subdevice
1476  * @fh: V4L2 subdev file handle
1477  * @code: pointer to v4l2_subdev_frame_size_enum structure
1478  */
1479 static int
1480 isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1481                      struct v4l2_subdev_frame_size_enum *fse)
1482 {
1483         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1484         struct v4l2_subdev_format format;
1485
1486         if (fse->index != 0)
1487                 return -EINVAL;
1488
1489         format.pad = fse->pad;
1490         format.format.code = fse->code;
1491         format.format.width = 1;
1492         format.format.height = 1;
1493         format.which = V4L2_SUBDEV_FORMAT_TRY;
1494         isif_try_format(isif, fh, &format);
1495         fse->min_width = format.format.width;
1496         fse->min_height = format.format.height;
1497
1498         if (format.format.code != fse->code)
1499                 return -EINVAL;
1500
1501         format.pad = fse->pad;
1502         format.format.code = fse->code;
1503         format.format.width = -1;
1504         format.format.height = -1;
1505         format.which = V4L2_SUBDEV_FORMAT_TRY;
1506         isif_try_format(isif, fh, &format);
1507         fse->max_width = format.format.width;
1508         fse->max_height = format.format.height;
1509
1510         return 0;
1511 }
1512
1513 /*
1514  * isif_enum_mbus_code() - enum mbus codes for pads
1515  * @sd: VPFE isif V4L2 subdevice
1516  * @fh: V4L2 subdev file handle
1517  * @code: pointer to v4l2_subdev_mbus_code_enum structure
1518  */
1519 static int
1520 isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1521                     struct v4l2_subdev_mbus_code_enum *code)
1522 {
1523         switch (code->pad) {
1524         case ISIF_PAD_SINK:
1525         case ISIF_PAD_SOURCE:
1526                 if (code->index >= ARRAY_SIZE(isif_fmts))
1527                         return -EINVAL;
1528                 code->code = isif_fmts[code->index];
1529                 break;
1530
1531         default:
1532                 return -EINVAL;
1533         }
1534
1535         return 0;
1536 }
1537
1538 /*
1539  * isif_pad_set_crop() - set crop rectangle on pad
1540  * @sd: VPFE isif V4L2 subdevice
1541  * @fh: V4L2 subdev file handle
1542  * @code: pointer to v4l2_subdev_mbus_code_enum structure
1543  *
1544  * Return 0 on success, -EINVAL if pad is invalid
1545  */
1546 static int
1547 isif_pad_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1548                   struct v4l2_subdev_crop *crop)
1549 {
1550         struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
1551         struct v4l2_mbus_framefmt *format;
1552
1553         /* check wether its a valid pad */
1554         if (crop->pad != ISIF_PAD_SINK)
1555                 return -EINVAL;
1556
1557         format = __isif_get_format(vpfe_isif, fh, crop->pad, crop->which);
1558         if (format == NULL)
1559                 return -EINVAL;
1560
1561         /* check wether crop rect is within limits */
1562         if (crop->rect.top < 0 || crop->rect.left < 0 ||
1563                 (crop->rect.left + crop->rect.width >
1564                 vpfe_isif->formats[ISIF_PAD_SINK].width) ||
1565                 (crop->rect.top + crop->rect.height >
1566                         vpfe_isif->formats[ISIF_PAD_SINK].height)) {
1567                 crop->rect.left = 0;
1568                 crop->rect.top = 0;
1569                 crop->rect.width = format->width;
1570                 crop->rect.height = format->height;
1571         }
1572         /* adjust the width to 16 pixel boundary */
1573         crop->rect.width = ((crop->rect.width + 15) & ~0xf);
1574         vpfe_isif->crop = crop->rect;
1575         if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
1576                 isif_set_image_window(vpfe_isif);
1577         } else {
1578                 struct v4l2_rect *rect;
1579
1580                 rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
1581                 memcpy(rect, &vpfe_isif->crop, sizeof(*rect));
1582         }
1583         return 0;
1584 }
1585
1586 /*
1587  * isif_pad_get_crop() - 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
1591  *
1592  * Return 0 on success, -EINVAL if pad is invalid
1593  */
1594 static int
1595 isif_pad_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
1596                   struct v4l2_subdev_crop *crop)
1597 {
1598         struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
1599
1600         /* check wether its a valid pad */
1601         if (crop->pad != ISIF_PAD_SINK)
1602                 return -EINVAL;
1603
1604         if (crop->which == V4L2_SUBDEV_FORMAT_TRY) {
1605                 struct v4l2_rect *rect;
1606                 rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
1607                 memcpy(&crop->rect, rect, sizeof(*rect));
1608         } else {
1609                 crop->rect = vpfe_isif->crop;
1610         }
1611
1612         return 0;
1613 }
1614
1615 /*
1616  * isif_init_formats() - Initialize formats on all pads
1617  * @sd: VPFE isif V4L2 subdevice
1618  * @fh: V4L2 subdev file handle
1619  *
1620  * Initialize all pad formats with default values. If fh is not NULL, try
1621  * formats are initialized on the file handle. Otherwise active formats are
1622  * initialized on the device.
1623  */
1624 static int
1625 isif_init_formats(struct v4l2_subdev *sd,
1626                   struct v4l2_subdev_fh *fh)
1627 {
1628         struct v4l2_subdev_format format;
1629         struct v4l2_subdev_crop crop;
1630
1631         memset(&format, 0, sizeof(format));
1632         format.pad = ISIF_PAD_SINK;
1633         format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1634         format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
1635         format.format.width = MAX_WIDTH;
1636         format.format.height = MAX_HEIGHT;
1637         isif_set_format(sd, fh, &format);
1638
1639         memset(&format, 0, sizeof(format));
1640         format.pad = ISIF_PAD_SOURCE;
1641         format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1642         format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
1643         format.format.width = MAX_WIDTH;
1644         format.format.height = MAX_HEIGHT;
1645         isif_set_format(sd, fh, &format);
1646
1647         memset(&crop, 0, sizeof(crop));
1648         crop.pad = ISIF_PAD_SINK;
1649         crop.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
1650         crop.rect.width = MAX_WIDTH;
1651         crop.rect.height = MAX_HEIGHT;
1652         isif_pad_set_crop(sd, fh, &crop);
1653
1654         return 0;
1655 }
1656
1657 /* subdev core operations */
1658 static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = {
1659         .ioctl = isif_ioctl,
1660 };
1661
1662 /* subdev file operations */
1663 static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = {
1664         .open = isif_init_formats,
1665 };
1666
1667 /* subdev video operations */
1668 static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = {
1669         .s_stream = isif_set_stream,
1670 };
1671
1672 /* subdev pad operations */
1673 static const struct v4l2_subdev_pad_ops isif_v4l2_pad_ops = {
1674         .enum_mbus_code = isif_enum_mbus_code,
1675         .enum_frame_size = isif_enum_frame_size,
1676         .get_fmt = isif_get_format,
1677         .set_fmt = isif_set_format,
1678         .set_crop = isif_pad_set_crop,
1679         .get_crop = isif_pad_get_crop,
1680 };
1681
1682 /* subdev operations */
1683 static const struct v4l2_subdev_ops isif_v4l2_ops = {
1684         .core = &isif_v4l2_core_ops,
1685         .video = &isif_v4l2_video_ops,
1686         .pad = &isif_v4l2_pad_ops,
1687 };
1688
1689 /*
1690  * Media entity operations
1691  */
1692
1693 /*
1694  * isif_link_setup() - Setup isif connections
1695  * @entity: isif media entity
1696  * @local: Pad at the local end of the link
1697  * @remote: Pad at the remote end of the link
1698  * @flags: Link flags
1699  *
1700  * return -EINVAL or zero on success
1701  */
1702 static int
1703 isif_link_setup(struct media_entity *entity, const struct media_pad *local,
1704                 const struct media_pad *remote, u32 flags)
1705 {
1706         struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
1707         struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
1708
1709         switch (local->index | media_entity_type(remote->entity)) {
1710         case ISIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
1711                 /* read from decoder/sensor */
1712                 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
1713                         isif->input = ISIF_INPUT_NONE;
1714                         break;
1715                 }
1716                 if (isif->input != ISIF_INPUT_NONE)
1717                         return -EBUSY;
1718                 isif->input = ISIF_INPUT_PARALLEL;
1719                 break;
1720
1721         case ISIF_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
1722                 /* write to memory */
1723                 if (flags & MEDIA_LNK_FL_ENABLED)
1724                         isif->output = ISIF_OUTPUT_MEMORY;
1725                 else
1726                         isif->output = ISIF_OUTPUT_NONE;
1727                 break;
1728
1729         case ISIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
1730                 if (flags & MEDIA_LNK_FL_ENABLED)
1731                         isif->output = ISIF_OUTPUT_IPIPEIF;
1732                 else
1733                         isif->output = ISIF_OUTPUT_NONE;
1734                 break;
1735
1736         default:
1737                 return -EINVAL;
1738         }
1739
1740         return 0;
1741 }
1742 static const struct media_entity_operations isif_media_ops = {
1743         .link_setup = isif_link_setup,
1744 };
1745
1746 /*
1747  * vpfe_isif_unregister_entities() - isif unregister entity
1748  * @isif - pointer to isif subdevice structure.
1749  */
1750 void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif)
1751 {
1752         vpfe_video_unregister(&isif->video_out);
1753         /* cleanup entity */
1754         media_entity_cleanup(&isif->subdev.entity);
1755         /* unregister subdev */
1756         v4l2_device_unregister_subdev(&isif->subdev);
1757 }
1758
1759 static void isif_restore_defaults(struct vpfe_isif_device *isif)
1760 {
1761         enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
1762         int i;
1763
1764         memset(&isif->isif_cfg.bayer.config_params, 0,
1765                sizeof(struct vpfe_isif_raw_config));
1766
1767         isif->isif_cfg.bayer.config_params.linearize.corr_shft =
1768                                         VPFE_ISIF_NO_SHIFT;
1769         isif->isif_cfg.bayer.config_params.linearize.scale_fact.integer = 1;
1770         isif->isif_cfg.bayer.config_params.culling.hcpat_odd =
1771                         ISIF_CULLING_HCAPT_ODD;
1772         isif->isif_cfg.bayer.config_params.culling.hcpat_even =
1773                         ISIF_CULLING_HCAPT_EVEN;
1774         isif->isif_cfg.bayer.config_params.culling.vcpat = ISIF_CULLING_VCAPT;
1775         /* Enable clock to ISIF, IPIPEIF and BL */
1776         vpss_enable_clock(VPSS_CCDC_CLOCK, 1);
1777         vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
1778         vpss_enable_clock(VPSS_BL_CLOCK, 1);
1779
1780         /* set all registers to default value */
1781         for (i = 0; i <= 0x1f8; i += 4)
1782                 isif_write(isif->isif_cfg.base_addr, 0, i);
1783         /* no culling support */
1784         isif_write(isif->isif_cfg.base_addr, 0xffff, CULH);
1785         isif_write(isif->isif_cfg.base_addr, 0xff, CULV);
1786
1787         /* Set default offset and gain */
1788         isif_config_gain_offset(isif);
1789         vpss_select_ccdc_source(source);
1790 }
1791
1792 /*
1793  * vpfe_isif_register_entities() - isif register entity
1794  * @isif - pointer to isif subdevice structure.
1795  * @vdev: pointer to v4l2 device structure.
1796  */
1797 int vpfe_isif_register_entities(struct vpfe_isif_device *isif,
1798                             struct v4l2_device *vdev)
1799 {
1800         struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
1801         unsigned int flags;
1802         int ret;
1803
1804         /* Register the subdev */
1805         ret = v4l2_device_register_subdev(vdev, &isif->subdev);
1806         if (ret < 0)
1807                 return ret;
1808
1809         isif_restore_defaults(isif);
1810         ret = vpfe_video_register(&isif->video_out, vdev);
1811         if (ret) {
1812                 pr_err("Failed to register isif video out device\n");
1813                 goto out_video_register;
1814         }
1815         isif->video_out.vpfe_dev = vpfe_dev;
1816         flags = 0;
1817         /* connect isif to video node */
1818         ret = media_entity_create_link(&isif->subdev.entity, 1,
1819                                        &isif->video_out.video_dev.entity,
1820                                        0, flags);
1821         if (ret < 0)
1822                 goto out_create_link;
1823         return 0;
1824 out_create_link:
1825         vpfe_video_unregister(&isif->video_out);
1826 out_video_register:
1827         v4l2_device_unregister_subdev(&isif->subdev);
1828         return ret;
1829 }
1830
1831 /* -------------------------------------------------------------------
1832  * V4L2 subdev control operations
1833  */
1834
1835 static int vpfe_isif_s_ctrl(struct v4l2_ctrl *ctrl)
1836 {
1837         struct vpfe_isif_device *isif =
1838              container_of(ctrl->handler, struct vpfe_isif_device, ctrls);
1839         struct isif_oper_config *config = &isif->isif_cfg;
1840
1841         switch (ctrl->id) {
1842         case VPFE_CID_DPCM_PREDICTOR:
1843                 config->bayer.dpcm_predictor = ctrl->val;
1844                 break;
1845
1846         case VPFE_ISIF_CID_CRGAIN:
1847                 config->isif_gain_params.cr_gain = ctrl->val;
1848                 break;
1849
1850         case VPFE_ISIF_CID_CGRGAIN:
1851                 config->isif_gain_params.cgr_gain = ctrl->val;
1852                 break;
1853
1854         case VPFE_ISIF_CID_CGBGAIN:
1855                 config->isif_gain_params.cgb_gain = ctrl->val;
1856                 break;
1857
1858         case VPFE_ISIF_CID_CBGAIN:
1859                 config->isif_gain_params.cb_gain = ctrl->val;
1860                 break;
1861
1862         case VPFE_ISIF_CID_GAIN_OFFSET:
1863                 config->isif_gain_params.offset = ctrl->val;
1864                 break;
1865
1866         default:
1867                 return -EINVAL;
1868         }
1869         return 0;
1870 }
1871
1872 static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = {
1873         .s_ctrl = vpfe_isif_s_ctrl,
1874 };
1875
1876 static const struct v4l2_ctrl_config vpfe_isif_dpcm_pred = {
1877         .ops = &vpfe_isif_ctrl_ops,
1878         .id = VPFE_CID_DPCM_PREDICTOR,
1879         .name = "DPCM Predictor",
1880         .type = V4L2_CTRL_TYPE_INTEGER,
1881         .min = 0,
1882         .max = 1,
1883         .step = 1,
1884         .def = 0,
1885 };
1886
1887 static const struct v4l2_ctrl_config vpfe_isif_crgain = {
1888         .ops = &vpfe_isif_ctrl_ops,
1889         .id = VPFE_ISIF_CID_CRGAIN,
1890         .name = "CRGAIN",
1891         .type = V4L2_CTRL_TYPE_INTEGER,
1892         .min = 0,
1893         .max = (1 << 12) - 1,
1894         .step = 1,
1895         .def = 0,
1896 };
1897
1898 static const struct v4l2_ctrl_config vpfe_isif_cgrgain = {
1899         .ops = &vpfe_isif_ctrl_ops,
1900         .id = VPFE_ISIF_CID_CGRGAIN,
1901         .name = "CGRGAIN",
1902         .type = V4L2_CTRL_TYPE_INTEGER,
1903         .min = 0,
1904         .max = (1 << 12) - 1,
1905         .step = 1,
1906         .def = 0,
1907 };
1908
1909 static const struct v4l2_ctrl_config vpfe_isif_cgbgain = {
1910         .ops = &vpfe_isif_ctrl_ops,
1911         .id = VPFE_ISIF_CID_CGBGAIN,
1912         .name = "CGBGAIN",
1913         .type = V4L2_CTRL_TYPE_INTEGER,
1914         .min = 0,
1915         .max = (1 << 12) - 1,
1916         .step = 1,
1917         .def = 0,
1918 };
1919
1920 static const struct v4l2_ctrl_config vpfe_isif_cbgain = {
1921         .ops = &vpfe_isif_ctrl_ops,
1922         .id = VPFE_ISIF_CID_CBGAIN,
1923         .name = "CBGAIN",
1924         .type = V4L2_CTRL_TYPE_INTEGER,
1925         .min = 0,
1926         .max = (1 << 12) - 1,
1927         .step = 1,
1928         .def = 0,
1929 };
1930
1931 static const struct v4l2_ctrl_config vpfe_isif_gain_offset = {
1932         .ops = &vpfe_isif_ctrl_ops,
1933         .id = VPFE_ISIF_CID_GAIN_OFFSET,
1934         .name = "Gain Offset",
1935         .type = V4L2_CTRL_TYPE_INTEGER,
1936         .min = 0,
1937         .max = (1 << 12) - 1,
1938         .step = 1,
1939         .def = 0,
1940 };
1941
1942 static void isif_remove(struct vpfe_isif_device *isif,
1943                         struct platform_device *pdev)
1944 {
1945         struct resource *res;
1946         int i = 0;
1947
1948         iounmap(isif->isif_cfg.base_addr);
1949         iounmap(isif->isif_cfg.linear_tbl0_addr);
1950         iounmap(isif->isif_cfg.linear_tbl1_addr);
1951
1952         while (i < 3) {
1953                 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1954                 if (res)
1955                         release_mem_region(res->start,
1956                                            resource_size(res));
1957                 i++;
1958         }
1959 }
1960
1961 static void isif_config_defaults(struct vpfe_isif_device *isif)
1962 {
1963         isif->isif_cfg.ycbcr.v4l2_pix_fmt = V4L2_PIX_FMT_UYVY;
1964         isif->isif_cfg.ycbcr.pix_fmt = ISIF_PIXFMT_YCBCR_8BIT;
1965         isif->isif_cfg.ycbcr.frm_fmt = ISIF_FRMFMT_INTERLACED;
1966         isif->isif_cfg.ycbcr.fid_pol = VPFE_PINPOL_POSITIVE;
1967         isif->isif_cfg.ycbcr.vd_pol = VPFE_PINPOL_POSITIVE;
1968         isif->isif_cfg.ycbcr.hd_pol = VPFE_PINPOL_POSITIVE;
1969         isif->isif_cfg.ycbcr.pix_order = ISIF_PIXORDER_CBYCRY;
1970         isif->isif_cfg.ycbcr.buf_type = ISIF_BUFTYPE_FLD_INTERLEAVED;
1971
1972         isif->isif_cfg.bayer.v4l2_pix_fmt = V4L2_PIX_FMT_SGRBG10ALAW8;
1973         isif->isif_cfg.bayer.pix_fmt = ISIF_PIXFMT_RAW;
1974         isif->isif_cfg.bayer.frm_fmt = ISIF_FRMFMT_PROGRESSIVE;
1975         isif->isif_cfg.bayer.fid_pol = VPFE_PINPOL_POSITIVE;
1976         isif->isif_cfg.bayer.vd_pol = VPFE_PINPOL_POSITIVE;
1977         isif->isif_cfg.bayer.hd_pol = VPFE_PINPOL_POSITIVE;
1978         isif->isif_cfg.bayer.cfa_pat = ISIF_CFA_PAT_MOSAIC;
1979         isif->isif_cfg.bayer.data_msb = ISIF_BIT_MSB_11;
1980         isif->isif_cfg.data_pack = ISIF_PACK_8BIT;
1981 }
1982 /*
1983  * vpfe_isif_init() - Initialize V4L2 subdev and media entity
1984  * @isif: VPFE isif module
1985  * @pdev: Pointer to platform device structure.
1986  * Return 0 on success and a negative error code on failure.
1987  */
1988 int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev)
1989 {
1990         struct v4l2_subdev *sd = &isif->subdev;
1991         struct media_pad *pads = &isif->pads[0];
1992         struct media_entity *me = &sd->entity;
1993         static resource_size_t res_len;
1994         struct resource *res;
1995         void *__iomem addr;
1996         int status;
1997         int i = 0;
1998
1999         /* Get the ISIF base address, linearization table0 and table1 addr. */
2000         while (i < 3) {
2001                 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
2002                 if (!res) {
2003                         status = -ENOENT;
2004                         goto fail_nobase_res;
2005                 }
2006                 res_len = resource_size(res);
2007                 res = request_mem_region(res->start, res_len, res->name);
2008                 if (!res) {
2009                         status = -EBUSY;
2010                         goto fail_nobase_res;
2011                 }
2012                 addr = ioremap_nocache(res->start, res_len);
2013                 if (!addr) {
2014                         status = -EBUSY;
2015                         goto fail_base_iomap;
2016                 }
2017                 switch (i) {
2018                 case 0:
2019                         /* ISIF base address */
2020                         isif->isif_cfg.base_addr = addr;
2021                         break;
2022                 case 1:
2023                         /* ISIF linear tbl0 address */
2024                         isif->isif_cfg.linear_tbl0_addr = addr;
2025                         break;
2026                 default:
2027                         /* ISIF linear tbl0 address */
2028                         isif->isif_cfg.linear_tbl1_addr = addr;
2029                         break;
2030                 }
2031                 i++;
2032         }
2033         davinci_cfg_reg(DM365_VIN_CAM_WEN);
2034         davinci_cfg_reg(DM365_VIN_CAM_VD);
2035         davinci_cfg_reg(DM365_VIN_CAM_HD);
2036         davinci_cfg_reg(DM365_VIN_YIN4_7_EN);
2037         davinci_cfg_reg(DM365_VIN_YIN0_3_EN);
2038
2039         /* queue ops */
2040         isif->video_out.ops = &isif_video_ops;
2041         v4l2_subdev_init(sd, &isif_v4l2_ops);
2042         sd->internal_ops = &isif_v4l2_internal_ops;
2043         strlcpy(sd->name, "DAVINCI ISIF", sizeof(sd->name));
2044         sd->grp_id = 1 << 16;   /* group ID for davinci subdevs */
2045         v4l2_set_subdevdata(sd, isif);
2046         sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
2047         pads[ISIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2048         pads[ISIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
2049
2050         isif->input = ISIF_INPUT_NONE;
2051         isif->output = ISIF_OUTPUT_NONE;
2052         me->ops = &isif_media_ops;
2053         status = media_entity_init(me, ISIF_PADS_NUM, pads, 0);
2054         if (status)
2055                 goto isif_fail;
2056         isif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2057         status = vpfe_video_init(&isif->video_out, "ISIF");
2058         if (status) {
2059                 pr_err("Failed to init isif-out video device\n");
2060                 goto isif_fail;
2061         }
2062         v4l2_ctrl_handler_init(&isif->ctrls, 6);
2063         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_crgain, NULL);
2064         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgrgain, NULL);
2065         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cgbgain, NULL);
2066         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_cbgain, NULL);
2067         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_gain_offset, NULL);
2068         v4l2_ctrl_new_custom(&isif->ctrls, &vpfe_isif_dpcm_pred, NULL);
2069
2070         v4l2_ctrl_handler_setup(&isif->ctrls);
2071         sd->ctrl_handler = &isif->ctrls;
2072         isif_config_defaults(isif);
2073         return 0;
2074 fail_base_iomap:
2075         release_mem_region(res->start, res_len);
2076         i--;
2077 fail_nobase_res:
2078         if (isif->isif_cfg.base_addr)
2079                 iounmap(isif->isif_cfg.base_addr);
2080         if (isif->isif_cfg.linear_tbl0_addr)
2081                 iounmap(isif->isif_cfg.linear_tbl0_addr);
2082
2083         while (i >= 0) {
2084                 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
2085                 release_mem_region(res->start, res_len);
2086                 i--;
2087         }
2088         return status;
2089 isif_fail:
2090         v4l2_ctrl_handler_free(&isif->ctrls);
2091         isif_remove(isif, pdev);
2092         return status;
2093 }
2094
2095 /*
2096  * vpfe_isif_cleanup - isif module cleanup
2097  * @isif: pointer to isif subdevice
2098  * @dev: pointer to platform device structure
2099  */
2100 void
2101 vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev)
2102 {
2103         isif_remove(isif, pdev);
2104 }