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