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