1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
29static 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
53static 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
63static 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
73static inline u32 isif_read(void __iomem *base_addr, u32 offset)
74{
75 return readl(base_addr + offset);
76}
77
78static inline void isif_write(void __iomem *base_addr, u32 val, u32 offset)
79{
80 writel(val, base_addr + offset);
81}
82
83static 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
93static 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
99static inline void
100isif_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
108static void isif_disable_all_modules(struct vpfe_isif_device *isif)
109{
110
111 isif_write(isif->isif_cfg.base_addr, 0, CLAMPCFG);
112
113 isif_write(isif->isif_cfg.base_addr, 0, DFCCTL);
114
115 isif_write(isif->isif_cfg.base_addr, 0, CSCCTL);
116
117 isif_write(isif->isif_cfg.base_addr, 0, LINCFG0);
118}
119
120static void isif_enable(struct vpfe_isif_device *isif, int en)
121{
122 if (!en)
123
124 isif_disable_all_modules(isif);
125
126
127
128
129
130 msleep(100);
131 isif_merge(isif->isif_cfg.base_addr, ISIF_SYNCEN_VDHDEN_MASK,
132 en, SYNCEN);
133}
134
135
136
137
138
139#define DM365_ISIF_MDFS_OFFSET 15
140#define DM365_ISIF_MDFS_MASK 0x1
141
142
143enum 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
153static int
154isif_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
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 == 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
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 == 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
213static int
214isif_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
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,
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
298 if (i >= ARRAY_SIZE(isif_fmts))
299 fmt->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
300
301
302 fmt->format.width = clamp_t(u32, width, 32, MAX_WIDTH);
303 fmt->format.height = clamp_t(u32, height, 32, MAX_HEIGHT);
304
305
306
307
308
309
310 if (fmt->pad == ISIF_PAD_SOURCE)
311 fmt->format.width &= ~15;
312}
313
314
315
316
317
318void 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
332 if (video->cur_frm != video->next_frm)
333 vpfe_video_process_buffer_complete(video);
334 return;
335 }
336
337
338
339
340 fid = vpfe_isif_get_fid(vpfe_dev);
341
342
343 video->field_id ^= 1;
344 if (fid == video->field_id) {
345
346 if (fid == 0) {
347
348
349
350
351
352 if (video->cur_frm != video->next_frm)
353 vpfe_video_process_buffer_complete(video);
354
355
356
357
358
359 if (field == V4L2_FIELD_SEQ_TB)
360 vpfe_video_schedule_bottom_field(video);
361 return;
362 }
363
364
365
366
367
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
377
378
379 video->field_id = fid;
380 }
381}
382
383
384
385
386
387void 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
404
405
406static 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
418static const struct vpfe_video_operations isif_video_ops = {
419 .queue = isif_video_queue,
420};
421
422
423
424
425
426
427static int isif_get_params(struct v4l2_subdev *sd, void *params)
428{
429 struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
430
431
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
439static 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
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
487static 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
538static 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
585static int
586isif_validate_raw_params(struct vpfe_isif_raw_config *params)
587{
588 int ret;
589
590 ret = isif_validate_df_csc_params(¶ms->df_csc);
591 if (ret)
592 return ret;
593 ret = isif_validate_dfc_params(¶ms->dfc);
594 if (ret)
595 return ret;
596 return isif_validate_bclamp_params(¶ms->bclamp);
597}
598
599static 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
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
619
620
621
622
623
624
625static 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
639static 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
663static void isif_config_bclamp(struct vpfe_isif_device *isif,
664 struct vpfe_isif_black_clamp *bc)
665{
666 u32 val;
667
668
669
670
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
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
690
691
692
693
694
695
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
719
720 val = bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK;
721
722
723 val |= (bc->vert.reset_val_sel & ISIF_VERT_BC_RST_VAL_SEL_MASK) <<
724 ISIF_VERT_BC_RST_VAL_SEL_SHIFT;
725
726
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
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
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
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
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
753static void
754isif_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
765
766
767
768 horz_start = image_win->left << (ppc - 1);
769 horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
770
771
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
782 vert_start += 1;
783 } else {
784
785 vert_start += 1;
786 vert_nr_lines = image_win->height - 1;
787
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
807static void
808isif_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
819 val = (vdfc->corr_mode & ISIF_VDFC_CORR_MOD_MASK) <<
820 ISIF_VDFC_CORR_MOD_SHIFT;
821
822
823 if (vdfc->corr_whole_line)
824 val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT;
825
826
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
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
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
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
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
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
929static void
930isif_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
941 val1 = 0;
942 for (i = 0; i < VPFE_ISIF_CSC_NUM_COEFF; i++) {
943 if ((i % 2) == 0) {
944
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
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
965 isif_write(isif->isif_cfg.base_addr, df_csc->start_pix &
966 ISIF_DF_CSC_SPH_MASK, FMTSPH);
967
968
969
970
971
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
979
980
981 isif_write(isif->isif_cfg.base_addr, df_csc->num_lines &
982 ISIF_DF_CSC_SPH_MASK, FMTLNV);
983
984 isif_write(isif->isif_cfg.base_addr, 1, CSCCTL);
985}
986
987static void
988isif_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
999 val = (linearize->corr_shft & ISIF_LIN_CORRSFT_MASK) <<
1000 ISIF_LIN_CORRSFT_SHIFT;
1001
1002 val |= 1;
1003 isif_write(isif->isif_cfg.base_addr, val, LINCFG0);
1004
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
1019static void
1020isif_config_culling(struct vpfe_isif_device *isif, struct vpfe_isif_cul *cul)
1021{
1022 u32 val;
1023
1024
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
1029 isif_write(isif->isif_cfg.base_addr, cul->vcpat, CULV);
1030
1031 isif_merge(isif->isif_cfg.base_addr, ISIF_LPF_MASK << ISIF_LPF_SHIFT,
1032 cul->en_lpf << ISIF_LPF_SHIFT, MODESET);
1033}
1034
1035static 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
1064static 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
1077
1078
1079 isif_write(isif->isif_cfg.base_addr, 0, REC656IF);
1080
1081
1082
1083
1084
1085
1086
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
1101
1102
1103
1104
1105
1106
1107
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
1119
1120
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
1129
1130
1131 val = (params->cfa_pat & ISIF_GAMMAWD_CFA_MASK) <<
1132 ISIF_GAMMAWD_CFA_SHIFT;
1133
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
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
1149 isif_config_gain_offset(isif);
1150
1151 if (format->code == MEDIA_BUS_FMT_SGRBG12_1X12)
1152 val = isif_sgrbg_pattern;
1153 else
1154
1155 val = isif_srggb_pattern;
1156
1157 isif_write(isif->isif_cfg.base_addr, val, CCOLP);
1158
1159
1160 val = (params->horz_flip_en & ISIF_HSIZE_FLIP_MASK) <<
1161 ISIF_HSIZE_FLIP_SHIFT;
1162
1163
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
1174 if (params->frm_fmt == ISIF_FRMFMT_INTERLACED) {
1175 if (params->image_invert_en)
1176
1177 isif_write(isif->isif_cfg.base_addr,
1178 ISIF_INTERLACE_INVERSE_MODE, SDOFST);
1179 else
1180
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
1189 isif_write(isif->isif_cfg.base_addr,
1190 ISIF_PROGRESSIVE_NON_INVERSE_MODE, SDOFST);
1191 }
1192
1193 isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode);
1194
1195 isif_config_bclamp(isif, &module_params->bclamp);
1196
1197 isif_config_dfc(isif, &module_params->dfc);
1198 if (!module_params->df_csc.df_or_csc)
1199
1200 isif_config_csc(isif, &module_params->df_csc);
1201
1202 isif_config_linearization(isif, &module_params->linearize);
1203
1204 isif_config_culling(isif, &module_params->culling);
1205
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
1219static 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
1231
1232
1233
1234
1235
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
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
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
1270 isif_write(isif->isif_cfg.base_addr, 3, REC656IF);
1271
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
1302 pr_debug("Invalid interface type\n");
1303 return -EINVAL;
1304 }
1305 isif_write(isif->isif_cfg.base_addr, modeset, MODESET);
1306
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
1311 if (format->code == MEDIA_BUS_FMT_YUYV10_1X20 ||
1312 format->code == MEDIA_BUS_FMT_YUYV8_1X16)
1313 isif_setwin(isif, ¶ms->win, params->frm_fmt, 1, mode);
1314 else
1315 isif_setwin(isif, ¶ms->win, params->frm_fmt, 2, mode);
1316
1317
1318
1319
1320
1321
1322 isif_write(isif->isif_cfg.base_addr,
1323 ((((params->win.width * 2) + 31) &
1324 DM365_ISIF_HSIZE_MASK) >> 5), HSIZE);
1325
1326
1327 if (params->frm_fmt == ISIF_FRMFMT_INTERLACED &&
1328 params->buf_type == ISIF_BUFTYPE_FLD_INTERLEAVED)
1329
1330 isif_write(isif->isif_cfg.base_addr,
1331 DM365_ISIF_SDOFST_2_LINES, SDOFST);
1332 return 0;
1333}
1334
1335static 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
1364
1365
1366
1367static 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
1390
1391
1392
1393
1394
1395static 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
1413
1414
1415
1416
1417
1418
1419static int
1420isif_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
1445
1446
1447
1448
1449
1450
1451
1452static int
1453isif_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
1470
1471
1472
1473
1474static int
1475isif_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
1510
1511
1512
1513
1514static int
1515isif_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
1535
1536
1537
1538
1539
1540
1541static int
1542isif_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
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
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
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
1584
1585
1586
1587
1588
1589
1590static int
1591isif_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
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
1615
1616
1617
1618
1619
1620
1621static int
1622isif_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
1656static const struct v4l2_subdev_core_ops isif_v4l2_core_ops = {
1657 .ioctl = isif_ioctl,
1658};
1659
1660
1661static const struct v4l2_subdev_internal_ops isif_v4l2_internal_ops = {
1662 .open = isif_init_formats,
1663};
1664
1665
1666static const struct v4l2_subdev_video_ops isif_v4l2_video_ops = {
1667 .s_stream = isif_set_stream,
1668};
1669
1670
1671static 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
1681static 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
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700static int
1701isif_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
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
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
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}
1745static const struct media_entity_operations isif_media_ops = {
1746 .link_setup = isif_link_setup,
1747};
1748
1749
1750
1751
1752
1753void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif)
1754{
1755 vpfe_video_unregister(&isif->video_out);
1756
1757 v4l2_device_unregister_subdev(&isif->subdev);
1758
1759 media_entity_cleanup(&isif->subdev.entity);
1760}
1761
1762static 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
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
1784 for (i = 0; i <= 0x1f8; i += 4)
1785 isif_write(isif->isif_cfg.base_addr, 0, i);
1786
1787 isif_write(isif->isif_cfg.base_addr, 0xffff, CULH);
1788 isif_write(isif->isif_cfg.base_addr, 0xff, CULV);
1789
1790
1791 isif_config_gain_offset(isif);
1792 vpss_select_ccdc_source(source);
1793}
1794
1795
1796
1797
1798
1799
1800int 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
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
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;
1827out_create_link:
1828 vpfe_video_unregister(&isif->video_out);
1829out_video_register:
1830 v4l2_device_unregister_subdev(&isif->subdev);
1831 return ret;
1832}
1833
1834
1835
1836
1837
1838static 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
1875static const struct v4l2_ctrl_ops vpfe_isif_ctrl_ops = {
1876 .s_ctrl = vpfe_isif_s_ctrl,
1877};
1878
1879static 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
1890static 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
1901static 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
1912static 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
1923static 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
1934static 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
1945static 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
1964static 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
1987
1988
1989
1990
1991int 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
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
2023 isif->isif_cfg.base_addr = addr;
2024 break;
2025 case 1:
2026
2027 isif->isif_cfg.linear_tbl0_addr = addr;
2028 break;
2029 default:
2030
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
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;
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;
2077fail_base_iomap:
2078 release_mem_region(res->start, res_len);
2079 i--;
2080fail_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;
2092isif_fail:
2093 v4l2_ctrl_handler_free(&isif->ctrls);
2094 isif_remove(isif, pdev);
2095 return status;
2096}
2097
2098
2099
2100
2101
2102
2103void
2104vpfe_isif_cleanup(struct vpfe_isif_device *isif, struct platform_device *pdev)
2105{
2106 isif_remove(isif, pdev);
2107}
2108