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