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