1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "dm365_ipipeif.h"
23#include "vpfe_mc_capture.h"
24
25static const unsigned int ipipeif_input_fmts[] = {
26 V4L2_MBUS_FMT_UYVY8_2X8,
27 V4L2_MBUS_FMT_SGRBG12_1X12,
28 V4L2_MBUS_FMT_Y8_1X8,
29 V4L2_MBUS_FMT_UV8_1X8,
30 V4L2_MBUS_FMT_YDYUYDYV8_1X16,
31 V4L2_MBUS_FMT_SBGGR8_1X8,
32};
33
34static const unsigned int ipipeif_output_fmts[] = {
35 V4L2_MBUS_FMT_UYVY8_2X8,
36 V4L2_MBUS_FMT_SGRBG12_1X12,
37 V4L2_MBUS_FMT_Y8_1X8,
38 V4L2_MBUS_FMT_UV8_1X8,
39 V4L2_MBUS_FMT_YDYUYDYV8_1X16,
40 V4L2_MBUS_FMT_SBGGR8_1X8,
41 V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
42 V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8,
43};
44
45static int
46ipipeif_get_pack_mode(enum v4l2_mbus_pixelcode in_pix_fmt)
47{
48 switch (in_pix_fmt) {
49 case V4L2_MBUS_FMT_SBGGR8_1X8:
50 case V4L2_MBUS_FMT_Y8_1X8:
51 case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
52 case V4L2_MBUS_FMT_UV8_1X8:
53 return IPIPEIF_5_1_PACK_8_BIT;
54
55 case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
56 return IPIPEIF_5_1_PACK_8_BIT_A_LAW;
57
58 case V4L2_MBUS_FMT_SGRBG12_1X12:
59 return IPIPEIF_5_1_PACK_16_BIT;
60
61 case V4L2_MBUS_FMT_SBGGR12_1X12:
62 return IPIPEIF_5_1_PACK_12_BIT;
63
64 default:
65 return IPIPEIF_5_1_PACK_16_BIT;
66 }
67}
68
69static inline u32 ipipeif_read(void *addr, u32 offset)
70{
71 return readl(addr + offset);
72}
73
74static inline void ipipeif_write(u32 val, void *addr, u32 offset)
75{
76 writel(val, addr + offset);
77}
78
79static void ipipeif_config_dpc(void *addr, struct ipipeif_dpc *dpc)
80{
81 u32 val = 0;
82
83 if (dpc->en) {
84 val = (dpc->en & 1) << IPIPEIF_DPC2_EN_SHIFT;
85 val |= dpc->thr & IPIPEIF_DPC2_THR_MASK;
86 }
87 ipipeif_write(val, addr, IPIPEIF_DPC2);
88}
89
90#define IPIPEIF_MODE_CONTINUOUS 0
91#define IPIPEIF_MODE_ONE_SHOT 1
92
93static int get_oneshot_mode(enum ipipeif_input_entity input)
94{
95 if (input == IPIPEIF_INPUT_MEMORY)
96 return IPIPEIF_MODE_ONE_SHOT;
97 else if (input == IPIPEIF_INPUT_ISIF)
98 return IPIPEIF_MODE_CONTINUOUS;
99
100 return -EINVAL;
101}
102
103static int
104ipipeif_get_cfg_src1(struct vpfe_ipipeif_device *ipipeif)
105{
106 struct v4l2_mbus_framefmt *informat;
107
108 informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
109 if (ipipeif->input == IPIPEIF_INPUT_MEMORY &&
110 (informat->code == V4L2_MBUS_FMT_Y8_1X8 ||
111 informat->code == V4L2_MBUS_FMT_UV8_1X8))
112 return IPIPEIF_CCDC;
113
114 return IPIPEIF_SRC1_PARALLEL_PORT;
115}
116
117static int
118ipipeif_get_data_shift(struct vpfe_ipipeif_device *ipipeif)
119{
120 struct v4l2_mbus_framefmt *informat;
121
122 informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
123
124 switch (informat->code) {
125 case V4L2_MBUS_FMT_SGRBG12_1X12:
126 return IPIPEIF_5_1_BITS11_0;
127
128 case V4L2_MBUS_FMT_Y8_1X8:
129 case V4L2_MBUS_FMT_UV8_1X8:
130 return IPIPEIF_5_1_BITS11_0;
131
132 default:
133 return IPIPEIF_5_1_BITS7_0;
134 }
135}
136
137static enum ipipeif_input_source
138ipipeif_get_source(struct vpfe_ipipeif_device *ipipeif)
139{
140 struct v4l2_mbus_framefmt *informat;
141
142 informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
143 if (ipipeif->input == IPIPEIF_INPUT_ISIF)
144 return IPIPEIF_CCDC;
145
146 if (informat->code == V4L2_MBUS_FMT_UYVY8_2X8)
147 return IPIPEIF_SDRAM_YUV;
148
149 return IPIPEIF_SDRAM_RAW;
150}
151
152void vpfe_ipipeif_ss_buffer_isr(struct vpfe_ipipeif_device *ipipeif)
153{
154 struct vpfe_video_device *video_in = &ipipeif->video_in;
155
156 if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
157 return;
158
159 spin_lock(&video_in->dma_queue_lock);
160 vpfe_video_process_buffer_complete(video_in);
161 video_in->state = VPFE_VIDEO_BUFFER_NOT_QUEUED;
162 vpfe_video_schedule_next_buffer(video_in);
163 spin_unlock(&video_in->dma_queue_lock);
164}
165
166int vpfe_ipipeif_decimation_enabled(struct vpfe_device *vpfe_dev)
167{
168 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
169
170 return ipipeif->config.decimation;
171}
172
173int vpfe_ipipeif_get_rsz(struct vpfe_device *vpfe_dev)
174{
175 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
176
177 return ipipeif->config.rsz;
178}
179
180#define RD_DATA_15_2 0x7
181
182
183
184
185
186
187static int ipipeif_hw_setup(struct v4l2_subdev *sd)
188{
189 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
190 struct v4l2_mbus_framefmt *informat, *outformat;
191 struct ipipeif_params params = ipipeif->config;
192 enum ipipeif_input_source ipipeif_source;
193 enum v4l2_mbus_pixelcode isif_port_if;
194 void *ipipeif_base_addr;
195 unsigned int val;
196 int data_shift;
197 int pack_mode;
198 int source1;
199
200 ipipeif_base_addr = ipipeif->ipipeif_base_addr;
201
202
203 vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
204
205 informat = &ipipeif->formats[IPIPEIF_PAD_SINK];
206 outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE];
207
208
209 val = get_oneshot_mode(ipipeif->input);
210 if (val < 0) {
211 pr_err("ipipeif: links setup required");
212 return -EINVAL;
213 }
214 val = val << ONESHOT_SHIFT;
215
216 ipipeif_source = ipipeif_get_source(ipipeif);
217 val |= ipipeif_source << INPSRC_SHIFT;
218
219 val |= params.clock_select << CLKSEL_SHIFT;
220 val |= params.avg_filter << AVGFILT_SHIFT;
221 val |= params.decimation << DECIM_SHIFT;
222
223 pack_mode = ipipeif_get_pack_mode(informat->code);
224 val |= pack_mode << PACK8IN_SHIFT;
225
226 source1 = ipipeif_get_cfg_src1(ipipeif);
227 val |= source1 << INPSRC1_SHIFT;
228
229 data_shift = ipipeif_get_data_shift(ipipeif);
230 if (ipipeif_source != IPIPEIF_SDRAM_YUV)
231 val |= data_shift << DATASFT_SHIFT;
232 else
233 val &= ~(RD_DATA_15_2 << DATASFT_SHIFT);
234
235 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG1);
236
237 switch (ipipeif_source) {
238 case IPIPEIF_CCDC:
239 ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
240 break;
241
242 case IPIPEIF_SDRAM_RAW:
243 case IPIPEIF_CCDC_DARKFM:
244 ipipeif_write(ipipeif->gain, ipipeif_base_addr, IPIPEIF_GAIN);
245
246 case IPIPEIF_SDRAM_YUV:
247 val |= data_shift << DATASFT_SHIFT;
248 ipipeif_write(params.ppln, ipipeif_base_addr, IPIPEIF_PPLN);
249 ipipeif_write(params.lpfr, ipipeif_base_addr, IPIPEIF_LPFR);
250 ipipeif_write(informat->width, ipipeif_base_addr, IPIPEIF_HNUM);
251 ipipeif_write(informat->height,
252 ipipeif_base_addr, IPIPEIF_VNUM);
253 break;
254
255 default:
256 return -EINVAL;
257 }
258
259
260 if (params.decimation)
261 ipipeif_write(params.rsz, ipipeif_base_addr, IPIPEIF_RSZ);
262
263
264 val = params.if_5_1.align_sync & 1;
265 val <<= IPIPEIF_INIRSZ_ALNSYNC_SHIFT;
266 val |= params.if_5_1.rsz_start & IPIPEIF_INIRSZ_MASK;
267 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_INIRSZ);
268 isif_port_if = informat->code;
269
270 if (isif_port_if == V4L2_MBUS_FMT_Y8_1X8)
271 isif_port_if = V4L2_MBUS_FMT_YUYV8_1X16;
272 else if (isif_port_if == V4L2_MBUS_FMT_UV8_1X8)
273 isif_port_if = V4L2_MBUS_FMT_SGRBG12_1X12;
274
275
276 switch (ipipeif_source) {
277 case IPIPEIF_SDRAM_RAW:
278 val = 0;
279 if (outformat->code == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8) {
280 val = 1;
281 val |= (IPIPEIF_DPCM_8BIT_10BIT & 1) <<
282 IPIPEIF_DPCM_BITS_SHIFT;
283 val |= (ipipeif->dpcm_predictor & 1) <<
284 IPIPEIF_DPCM_PRED_SHIFT;
285 }
286 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DPCM);
287
288
289 ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc);
290
291 ipipeif_write(params.if_5_1.clip,
292 ipipeif_base_addr, IPIPEIF_OCLIP);
293
294
295
296 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CFG2);
297 switch (isif_port_if) {
298 case V4L2_MBUS_FMT_YUYV8_1X16:
299 case V4L2_MBUS_FMT_UYVY8_2X8:
300 case V4L2_MBUS_FMT_Y8_1X8:
301 RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
302 SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
303 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
304 break;
305
306 default:
307 RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
308 RESETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
309 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
310 break;
311 }
312
313 case IPIPEIF_SDRAM_YUV:
314
315 if (params.clock_select == IPIPEIF_SDRAM_CLK) {
316 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_CLKDIV);
317 val |= (params.if_5_1.clk_div.m - 1) <<
318 IPIPEIF_CLKDIV_M_SHIFT;
319 val |= (params.if_5_1.clk_div.n - 1);
320 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CLKDIV);
321 }
322 break;
323
324 case IPIPEIF_CCDC:
325 case IPIPEIF_CCDC_DARKFM:
326
327 ipipeif_config_dpc(ipipeif_base_addr, ¶ms.if_5_1.dpc);
328
329
330 val = 0;
331 if (params.if_5_1.df_gain_en) {
332 val = params.if_5_1.df_gain_thr &
333 IPIPEIF_DF_GAIN_THR_MASK;
334 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGTH);
335 val = (params.if_5_1.df_gain_en & 1) <<
336 IPIPEIF_DF_GAIN_EN_SHIFT;
337 val |= params.if_5_1.df_gain &
338 IPIPEIF_DF_GAIN_MASK;
339 }
340 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_DFSGVL);
341
342 val = VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_HDPOL_SHIFT;
343 val |= VPFE_PINPOL_POSITIVE << IPIPEIF_CFG2_VDPOL_SHIFT;
344
345 switch (isif_port_if) {
346 case V4L2_MBUS_FMT_YUYV8_1X16:
347 case V4L2_MBUS_FMT_YUYV10_1X20:
348 RESETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
349 SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
350 break;
351
352 case V4L2_MBUS_FMT_YUYV8_2X8:
353 case V4L2_MBUS_FMT_UYVY8_2X8:
354 case V4L2_MBUS_FMT_Y8_1X8:
355 case V4L2_MBUS_FMT_YUYV10_2X10:
356 SETBIT(val, IPIPEIF_CFG2_YUV8_SHIFT);
357 SETBIT(val, IPIPEIF_CFG2_YUV16_SHIFT);
358 val |= IPIPEIF_CBCR_Y << IPIPEIF_CFG2_YUV8P_SHIFT;
359 break;
360
361 default:
362
363 ipipeif_write(params.if_5_1.clip, ipipeif_base_addr,
364 IPIPEIF_OCLIP);
365 }
366 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
367 break;
368
369 default:
370 return -EINVAL;
371 }
372
373 return 0;
374}
375
376static int
377ipipeif_set_config(struct v4l2_subdev *sd, struct ipipeif_params *config)
378{
379 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
380 struct device *dev = ipipeif->subdev.v4l2_dev->dev;
381
382 if (!config) {
383 dev_err(dev, "Invalid configuration pointer\n");
384 return -EINVAL;
385 }
386
387 ipipeif->config.clock_select = config->clock_select;
388 ipipeif->config.ppln = config->ppln;
389 ipipeif->config.lpfr = config->lpfr;
390 ipipeif->config.rsz = config->rsz;
391 ipipeif->config.decimation = config->decimation;
392 if (ipipeif->config.decimation &&
393 (ipipeif->config.rsz < IPIPEIF_RSZ_MIN ||
394 ipipeif->config.rsz > IPIPEIF_RSZ_MAX)) {
395 dev_err(dev, "rsz range is %d to %d\n",
396 IPIPEIF_RSZ_MIN, IPIPEIF_RSZ_MAX);
397 return -EINVAL;
398 }
399
400 ipipeif->config.avg_filter = config->avg_filter;
401
402 ipipeif->config.if_5_1.df_gain_thr = config->if_5_1.df_gain_thr;
403 ipipeif->config.if_5_1.df_gain = config->if_5_1.df_gain;
404 ipipeif->config.if_5_1.df_gain_en = config->if_5_1.df_gain_en;
405
406 ipipeif->config.if_5_1.rsz_start = config->if_5_1.rsz_start;
407 ipipeif->config.if_5_1.align_sync = config->if_5_1.align_sync;
408 ipipeif->config.if_5_1.clip = config->if_5_1.clip;
409
410 ipipeif->config.if_5_1.dpc.en = config->if_5_1.dpc.en;
411 ipipeif->config.if_5_1.dpc.thr = config->if_5_1.dpc.thr;
412
413 ipipeif->config.if_5_1.clk_div.m = config->if_5_1.clk_div.m;
414 ipipeif->config.if_5_1.clk_div.n = config->if_5_1.clk_div.n;
415
416 return 0;
417}
418
419static int
420ipipeif_get_config(struct v4l2_subdev *sd, void __user *arg)
421{
422 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
423 struct ipipeif_params *config = (struct ipipeif_params *)arg;
424 struct device *dev = ipipeif->subdev.v4l2_dev->dev;
425
426 if (!arg) {
427 dev_err(dev, "Invalid configuration pointer\n");
428 return -EINVAL;
429 }
430
431 config->clock_select = ipipeif->config.clock_select;
432 config->ppln = ipipeif->config.ppln;
433 config->lpfr = ipipeif->config.lpfr;
434 config->rsz = ipipeif->config.rsz;
435 config->decimation = ipipeif->config.decimation;
436 config->avg_filter = ipipeif->config.avg_filter;
437
438 config->if_5_1.df_gain_thr = ipipeif->config.if_5_1.df_gain_thr;
439 config->if_5_1.df_gain = ipipeif->config.if_5_1.df_gain;
440 config->if_5_1.df_gain_en = ipipeif->config.if_5_1.df_gain_en;
441
442 config->if_5_1.rsz_start = ipipeif->config.if_5_1.rsz_start;
443 config->if_5_1.align_sync = ipipeif->config.if_5_1.align_sync;
444 config->if_5_1.clip = ipipeif->config.if_5_1.clip;
445
446 config->if_5_1.dpc.en = ipipeif->config.if_5_1.dpc.en;
447 config->if_5_1.dpc.thr = ipipeif->config.if_5_1.dpc.thr;
448
449 config->if_5_1.clk_div.m = ipipeif->config.if_5_1.clk_div.m;
450 config->if_5_1.clk_div.n = ipipeif->config.if_5_1.clk_div.n;
451
452 return 0;
453}
454
455
456
457
458
459
460
461static long ipipeif_ioctl(struct v4l2_subdev *sd,
462 unsigned int cmd, void *arg)
463{
464 struct ipipeif_params *config = (struct ipipeif_params *)arg;
465 int ret = -ENOIOCTLCMD;
466
467 switch (cmd) {
468 case VIDIOC_VPFE_IPIPEIF_S_CONFIG:
469 ret = ipipeif_set_config(sd, config);
470 break;
471
472 case VIDIOC_VPFE_IPIPEIF_G_CONFIG:
473 ret = ipipeif_get_config(sd, arg);
474 break;
475 }
476 return ret;
477}
478
479
480
481
482
483static int ipipeif_s_ctrl(struct v4l2_ctrl *ctrl)
484{
485 struct vpfe_ipipeif_device *ipipeif =
486 container_of(ctrl->handler, struct vpfe_ipipeif_device, ctrls);
487
488 switch (ctrl->id) {
489 case VPFE_CID_DPCM_PREDICTOR:
490 ipipeif->dpcm_predictor = ctrl->val;
491 break;
492
493 case V4L2_CID_GAIN:
494 ipipeif->gain = ctrl->val;
495 break;
496
497 default:
498 return -EINVAL;
499 }
500
501 return 0;
502}
503
504#define ENABLE_IPIPEIF 0x1
505
506void vpfe_ipipeif_enable(struct vpfe_device *vpfe_dev)
507{
508 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
509 void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
510 unsigned char val;
511
512 if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
513 return;
514
515 do {
516 val = ipipeif_read(ipipeif_base_addr, IPIPEIF_ENABLE);
517 } while (val & 0x1);
518
519 ipipeif_write(ENABLE_IPIPEIF, ipipeif_base_addr, IPIPEIF_ENABLE);
520}
521
522
523
524
525
526
527static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
528{
529 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
530 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
531 int ret = 0;
532
533 if (!enable)
534 return ret;
535
536 ret = ipipeif_hw_setup(sd);
537 if (!ret)
538 vpfe_ipipeif_enable(vpfe_dev);
539
540 return ret;
541}
542
543
544
545
546
547
548
549
550static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
551 struct v4l2_subdev_fh *fh,
552 struct v4l2_subdev_mbus_code_enum *code)
553{
554 switch (code->pad) {
555 case IPIPEIF_PAD_SINK:
556 if (code->index >= ARRAY_SIZE(ipipeif_input_fmts))
557 return -EINVAL;
558
559 code->code = ipipeif_input_fmts[code->index];
560 break;
561
562 case IPIPEIF_PAD_SOURCE:
563 if (code->index >= ARRAY_SIZE(ipipeif_output_fmts))
564 return -EINVAL;
565
566 code->code = ipipeif_output_fmts[code->index];
567 break;
568
569 default:
570 return -EINVAL;
571 }
572
573 return 0;
574}
575
576
577
578
579
580
581
582static int
583ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
584 struct v4l2_subdev_format *fmt)
585{
586 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
587
588 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
589 fmt->format = ipipeif->formats[fmt->pad];
590 else
591 fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
592
593 return 0;
594}
595
596#define MIN_OUT_WIDTH 32
597#define MIN_OUT_HEIGHT 32
598
599
600
601
602
603
604
605
606
607static void
608ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
609 struct v4l2_subdev_fh *fh, unsigned int pad,
610 struct v4l2_mbus_framefmt *fmt,
611 enum v4l2_subdev_format_whence which)
612{
613 unsigned int max_out_height;
614 unsigned int max_out_width;
615 unsigned int i;
616
617 max_out_width = IPIPE_MAX_OUTPUT_WIDTH_A;
618 max_out_height = IPIPE_MAX_OUTPUT_HEIGHT_A;
619
620 if (pad == IPIPEIF_PAD_SINK) {
621 for (i = 0; i < ARRAY_SIZE(ipipeif_input_fmts); i++)
622 if (fmt->code == ipipeif_input_fmts[i])
623 break;
624
625
626 if (i >= ARRAY_SIZE(ipipeif_input_fmts))
627 fmt->code = V4L2_MBUS_FMT_SGRBG12_1X12;
628 } else if (pad == IPIPEIF_PAD_SOURCE) {
629 for (i = 0; i < ARRAY_SIZE(ipipeif_output_fmts); i++)
630 if (fmt->code == ipipeif_output_fmts[i])
631 break;
632
633
634 if (i >= ARRAY_SIZE(ipipeif_output_fmts))
635 fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
636 }
637
638 fmt->width = clamp_t(u32, fmt->width, MIN_OUT_HEIGHT, max_out_width);
639 fmt->height = clamp_t(u32, fmt->height, MIN_OUT_WIDTH, max_out_height);
640}
641
642static int
643ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
644 struct v4l2_subdev_frame_size_enum *fse)
645{
646 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
647 struct v4l2_mbus_framefmt format;
648
649 if (fse->index != 0)
650 return -EINVAL;
651
652 format.code = fse->code;
653 format.width = 1;
654 format.height = 1;
655 ipipeif_try_format(ipipeif, fh, fse->pad, &format,
656 V4L2_SUBDEV_FORMAT_TRY);
657 fse->min_width = format.width;
658 fse->min_height = format.height;
659
660 if (format.code != fse->code)
661 return -EINVAL;
662
663 format.code = fse->code;
664 format.width = -1;
665 format.height = -1;
666 ipipeif_try_format(ipipeif, fh, fse->pad, &format,
667 V4L2_SUBDEV_FORMAT_TRY);
668 fse->max_width = format.width;
669 fse->max_height = format.height;
670
671 return 0;
672}
673
674
675
676
677
678
679
680
681
682static struct v4l2_mbus_framefmt *
683__ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
684 struct v4l2_subdev_fh *fh, unsigned int pad,
685 enum v4l2_subdev_format_whence which)
686{
687 if (which == V4L2_SUBDEV_FORMAT_TRY)
688 return v4l2_subdev_get_try_format(fh, pad);
689
690 return &ipipeif->formats[pad];
691}
692
693
694
695
696
697
698
699
700static int
701ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
702 struct v4l2_subdev_format *fmt)
703{
704 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
705 struct v4l2_mbus_framefmt *format;
706
707 format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
708 if (format == NULL)
709 return -EINVAL;
710
711 ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
712 *format = fmt->format;
713
714 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
715 return 0;
716
717 if (fmt->pad == IPIPEIF_PAD_SINK &&
718 ipipeif->input != IPIPEIF_INPUT_NONE)
719 ipipeif->formats[fmt->pad] = fmt->format;
720 else if (fmt->pad == IPIPEIF_PAD_SOURCE &&
721 ipipeif->output != IPIPEIF_OUTPUT_NONE)
722 ipipeif->formats[fmt->pad] = fmt->format;
723 else
724 return -EINVAL;
725
726 return 0;
727}
728
729static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
730{
731#define WIDTH_I 640
732#define HEIGHT_I 480
733
734 const struct ipipeif_params ipipeif_defaults = {
735 .clock_select = IPIPEIF_SDRAM_CLK,
736 .ppln = WIDTH_I + 8,
737 .lpfr = HEIGHT_I + 10,
738 .rsz = 16,
739 .decimation = IPIPEIF_DECIMATION_OFF,
740 .avg_filter = IPIPEIF_AVG_OFF,
741 .if_5_1 = {
742 .clk_div = {
743 .m = 1,
744 .n = 6
745 },
746 .clip = 4095,
747 },
748 };
749 memset(&ipipeif->config, 0, sizeof(struct ipipeif_params));
750 memcpy(&ipipeif->config, &ipipeif_defaults,
751 sizeof(struct ipipeif_params));
752}
753
754
755
756
757
758
759
760
761
762
763static int
764ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
765{
766 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
767 struct v4l2_subdev_format format;
768
769 memset(&format, 0, sizeof(format));
770 format.pad = IPIPEIF_PAD_SINK;
771 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
772 format.format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
773 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
774 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
775 ipipeif_set_format(sd, fh, &format);
776
777 memset(&format, 0, sizeof(format));
778 format.pad = IPIPEIF_PAD_SOURCE;
779 format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
780 format.format.code = V4L2_MBUS_FMT_UYVY8_2X8;
781 format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
782 format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
783 ipipeif_set_format(sd, fh, &format);
784
785 ipipeif_set_default_config(ipipeif);
786
787 return 0;
788}
789
790
791
792
793
794
795static int
796ipipeif_video_in_queue(struct vpfe_device *vpfe_dev, unsigned long addr)
797{
798 struct vpfe_ipipeif_device *ipipeif = &vpfe_dev->vpfe_ipipeif;
799 void *ipipeif_base_addr = ipipeif->ipipeif_base_addr;
800 unsigned int adofs;
801 u32 val;
802
803 if (ipipeif->input != IPIPEIF_INPUT_MEMORY)
804 return -EINVAL;
805
806 switch (ipipeif->formats[IPIPEIF_PAD_SINK].code) {
807 case V4L2_MBUS_FMT_Y8_1X8:
808 case V4L2_MBUS_FMT_UV8_1X8:
809 case V4L2_MBUS_FMT_YDYUYDYV8_1X16:
810 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width;
811 break;
812
813 default:
814 adofs = ipipeif->formats[IPIPEIF_PAD_SINK].width << 1;
815 break;
816 }
817
818
819 adofs += 31;
820 adofs &= ~0x1f;
821 val = (adofs >> 5) & IPIPEIF_ADOFS_LSB_MASK;
822 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADOFS);
823
824
825 val = (addr >> IPIPEIF_ADDRL_SHIFT) & IPIPEIF_ADDRL_MASK;
826 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRL);
827
828
829 val = (addr >> IPIPEIF_ADDRU_SHIFT) & IPIPEIF_ADDRU_MASK;
830 ipipeif_write(val, ipipeif_base_addr, IPIPEIF_ADDRU);
831
832 return 0;
833}
834
835
836static const struct v4l2_subdev_core_ops ipipeif_v4l2_core_ops = {
837 .ioctl = ipipeif_ioctl,
838};
839
840static const struct v4l2_ctrl_ops ipipeif_ctrl_ops = {
841 .s_ctrl = ipipeif_s_ctrl,
842};
843
844static const struct v4l2_ctrl_config vpfe_ipipeif_dpcm_pred = {
845 .ops = &ipipeif_ctrl_ops,
846 .id = VPFE_CID_DPCM_PREDICTOR,
847 .name = "DPCM Predictor",
848 .type = V4L2_CTRL_TYPE_INTEGER,
849 .min = 0,
850 .max = 1,
851 .step = 1,
852 .def = 0,
853};
854
855
856static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
857 .open = ipipeif_init_formats,
858};
859
860
861static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
862 .s_stream = ipipeif_set_stream,
863};
864
865
866static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
867 .enum_mbus_code = ipipeif_enum_mbus_code,
868 .enum_frame_size = ipipeif_enum_frame_size,
869 .get_fmt = ipipeif_get_format,
870 .set_fmt = ipipeif_set_format,
871};
872
873
874static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
875 .core = &ipipeif_v4l2_core_ops,
876 .video = &ipipeif_v4l2_video_ops,
877 .pad = &ipipeif_v4l2_pad_ops,
878};
879
880static const struct vpfe_video_operations video_in_ops = {
881 .queue = ipipeif_video_in_queue,
882};
883
884static int
885ipipeif_link_setup(struct media_entity *entity, const struct media_pad *local,
886 const struct media_pad *remote, u32 flags)
887{
888 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
889 struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
890 struct vpfe_device *vpfe = to_vpfe_device(ipipeif);
891
892 switch (local->index | media_entity_type(remote->entity)) {
893 case IPIPEIF_PAD_SINK | MEDIA_ENT_T_DEVNODE:
894
895 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
896 ipipeif->input = IPIPEIF_INPUT_NONE;
897 break;
898 }
899 ipipeif->input = IPIPEIF_INPUT_MEMORY;
900 break;
901
902 case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
903
904 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
905 ipipeif->input = IPIPEIF_INPUT_NONE;
906 break;
907 }
908 if (ipipeif->input != IPIPEIF_INPUT_NONE)
909 return -EBUSY;
910
911 ipipeif->input = IPIPEIF_INPUT_ISIF;
912 break;
913
914 case IPIPEIF_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
915 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
916 ipipeif->output = IPIPEIF_OUTPUT_NONE;
917 break;
918 }
919 if (remote->entity == &vpfe->vpfe_ipipe.subdev.entity)
920
921 ipipeif->output = IPIPEIF_OUTPUT_IPIPE;
922 else if (remote->entity == &vpfe->vpfe_resizer.
923 crop_resizer.subdev.entity)
924
925 ipipeif->output = IPIPEIF_OUTPUT_RESIZER;
926 else
927 return -EINVAL;
928 break;
929
930 default:
931 return -EINVAL;
932 }
933
934 return 0;
935}
936
937static const struct media_entity_operations ipipeif_media_ops = {
938 .link_setup = ipipeif_link_setup,
939};
940
941
942
943
944
945void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif)
946{
947
948 vpfe_video_unregister(&ipipeif->video_in);
949
950
951 v4l2_device_unregister_subdev(&ipipeif->subdev);
952
953 media_entity_cleanup(&ipipeif->subdev.entity);
954}
955
956int
957vpfe_ipipeif_register_entities(struct vpfe_ipipeif_device *ipipeif,
958 struct v4l2_device *vdev)
959{
960 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipeif);
961 unsigned int flags;
962 int ret;
963
964
965 ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
966 if (ret < 0)
967 return ret;
968
969 ret = vpfe_video_register(&ipipeif->video_in, vdev);
970 if (ret) {
971 pr_err("Failed to register ipipeif video-in device\n");
972 goto fail;
973 }
974 ipipeif->video_in.vpfe_dev = vpfe_dev;
975
976 flags = 0;
977 ret = media_entity_create_link(&ipipeif->video_in.video_dev.entity, 0,
978 &ipipeif->subdev.entity, 0, flags);
979 if (ret < 0)
980 goto fail;
981
982 return 0;
983fail:
984 v4l2_device_unregister_subdev(&ipipeif->subdev);
985
986 return ret;
987}
988
989#define IPIPEIF_GAIN_HIGH 0x3ff
990#define IPIPEIF_DEFAULT_GAIN 0x200
991
992int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif,
993 struct platform_device *pdev)
994{
995 struct v4l2_subdev *sd = &ipipeif->subdev;
996 struct media_pad *pads = &ipipeif->pads[0];
997 struct media_entity *me = &sd->entity;
998 static resource_size_t res_len;
999 struct resource *res;
1000 int ret;
1001
1002 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1003 if (!res)
1004 return -ENOENT;
1005
1006 res_len = resource_size(res);
1007 res = request_mem_region(res->start, res_len, res->name);
1008 if (!res)
1009 return -EBUSY;
1010
1011 ipipeif->ipipeif_base_addr = ioremap_nocache(res->start, res_len);
1012 if (!ipipeif->ipipeif_base_addr) {
1013 ret = -EBUSY;
1014 goto fail;
1015 }
1016
1017 v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
1018
1019 sd->internal_ops = &ipipeif_v4l2_internal_ops;
1020 strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name));
1021 sd->grp_id = 1 << 16;
1022
1023 v4l2_set_subdevdata(sd, ipipeif);
1024
1025 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1026 pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1027 pads[IPIPEIF_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1028 ipipeif->input = IPIPEIF_INPUT_NONE;
1029 ipipeif->output = IPIPEIF_OUTPUT_NONE;
1030 me->ops = &ipipeif_media_ops;
1031
1032 ret = media_entity_init(me, IPIPEIF_NUM_PADS, pads, 0);
1033 if (ret)
1034 goto fail;
1035
1036 v4l2_ctrl_handler_init(&ipipeif->ctrls, 2);
1037 v4l2_ctrl_new_std(&ipipeif->ctrls, &ipipeif_ctrl_ops,
1038 V4L2_CID_GAIN, 0,
1039 IPIPEIF_GAIN_HIGH, 1, IPIPEIF_DEFAULT_GAIN);
1040 v4l2_ctrl_new_custom(&ipipeif->ctrls, &vpfe_ipipeif_dpcm_pred, NULL);
1041 v4l2_ctrl_handler_setup(&ipipeif->ctrls);
1042 sd->ctrl_handler = &ipipeif->ctrls;
1043
1044 ipipeif->video_in.ops = &video_in_ops;
1045 ipipeif->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1046 ret = vpfe_video_init(&ipipeif->video_in, "IPIPEIF");
1047 if (ret) {
1048 pr_err("Failed to init IPIPEIF video-in device\n");
1049 goto fail;
1050 }
1051 ipipeif_set_default_config(ipipeif);
1052 return 0;
1053fail:
1054 release_mem_region(res->start, res_len);
1055 return ret;
1056}
1057
1058void
1059vpfe_ipipeif_cleanup(struct vpfe_ipipeif_device *ipipeif,
1060 struct platform_device *pdev)
1061{
1062 struct resource *res;
1063
1064 v4l2_ctrl_handler_free(&ipipeif->ctrls);
1065 iounmap(ipipeif->ipipeif_base_addr);
1066 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
1067 if (res)
1068 release_mem_region(res->start, resource_size(res));
1069
1070}
1071