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