1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/module.h>
19#include <linux/uaccess.h>
20#include <linux/delay.h>
21#include <linux/device.h>
22#include <linux/mm.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25
26#include <media/v4l2-event.h>
27#include <media/v4l2-mediabus.h>
28#include "atomisp_cmd.h"
29#include "atomisp_common.h"
30#include "atomisp_compat.h"
31#include "atomisp_internal.h"
32
33const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
34 { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR },
35 { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GBRG },
36 { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GRBG },
37 { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_RGGB },
38 { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_BGGR },
39 { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GBRG },
40 { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GRBG },
41 { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_RGGB },
42 { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_BGGR },
43 { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GBRG },
44 { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GRBG },
45 { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_RGGB },
46 { MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
47 { MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
48#if 0
49 { MEDIA_BUS_FMT_JPEG_1X8, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
50 { V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, IA_CSS_FRAME_FORMAT_NV12, 0 },
51 { V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, IA_CSS_FRAME_FORMAT_NV21, 0 },
52#endif
53 { V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0 },
54#if 0
55 { V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
56#endif
57
58 { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 },
59 {}
60};
61
62static const struct {
63 u32 code;
64 u32 compressed;
65} compressed_codes[] = {
66 { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
67 { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
68 { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
69 { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
70};
71
72u32 atomisp_subdev_uncompressed_code(u32 code)
73{
74 unsigned int i;
75
76 for (i = 0; i < ARRAY_SIZE(compressed_codes); i++)
77 if (code == compressed_codes[i].compressed)
78 return compressed_codes[i].code;
79
80 return code;
81}
82
83bool atomisp_subdev_is_compressed(u32 code)
84{
85 int i;
86
87 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
88 if (code == atomisp_in_fmt_conv[i].code)
89 return atomisp_in_fmt_conv[i].bpp !=
90 atomisp_in_fmt_conv[i].depth;
91
92 return false;
93}
94
95const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
96{
97 int i;
98
99 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
100 if (code == atomisp_in_fmt_conv[i].code)
101 return atomisp_in_fmt_conv + i;
102
103 return NULL;
104}
105
106const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
107 enum atomisp_input_format atomisp_in_fmt)
108{
109 int i;
110
111 for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
112 if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt)
113 return atomisp_in_fmt_conv + i;
114
115 return NULL;
116}
117
118bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
119 unsigned int source_pad)
120{
121 struct v4l2_mbus_framefmt *sink, *src;
122
123 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
124 V4L2_SUBDEV_FORMAT_ACTIVE,
125 ATOMISP_SUBDEV_PAD_SINK);
126 src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
127 V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
128
129 return atomisp_is_mbuscode_raw(sink->code)
130 && !atomisp_is_mbuscode_raw(src->code);
131}
132
133uint16_t atomisp_subdev_source_pad(struct video_device *vdev)
134{
135 struct media_link *link;
136 u16 ret = 0;
137
138 list_for_each_entry(link, &vdev->entity.links, list) {
139 if (link->source) {
140 ret = link->source->index;
141 break;
142 }
143 }
144 return ret;
145}
146
147
148
149
150
151
152
153
154
155
156
157
158
159static long isp_subdev_ioctl(struct v4l2_subdev *sd,
160 unsigned int cmd, void *arg)
161{
162 return 0;
163}
164
165
166
167
168
169
170
171
172static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
173{
174 return 0;
175}
176
177static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
178 struct v4l2_fh *fh,
179 struct v4l2_event_subscription *sub)
180{
181 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
182 struct atomisp_device *isp = isp_sd->isp;
183
184 if (sub->type != V4L2_EVENT_FRAME_SYNC &&
185 sub->type != V4L2_EVENT_FRAME_END &&
186 sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY &&
187 sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
188 sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
189 sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
190 sub->type != V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE &&
191 sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
192 return -EINVAL;
193
194 if (sub->type == V4L2_EVENT_FRAME_SYNC &&
195 !atomisp_css_valid_sof(isp))
196 return -EINVAL;
197
198 return v4l2_event_subscribe(fh, sub, 16, NULL);
199}
200
201static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
202 struct v4l2_fh *fh,
203 struct v4l2_event_subscription *sub)
204{
205 return v4l2_event_unsubscribe(fh, sub);
206}
207
208
209
210
211
212
213
214
215static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
216 struct v4l2_subdev_pad_config *cfg,
217 struct v4l2_subdev_mbus_code_enum *code)
218{
219 if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
220 return -EINVAL;
221
222 code->code = atomisp_in_fmt_conv[code->index].code;
223
224 return 0;
225}
226
227static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
228 uint32_t target)
229{
230 switch (pad) {
231 case ATOMISP_SUBDEV_PAD_SINK:
232 switch (target) {
233 case V4L2_SEL_TGT_CROP:
234 return 0;
235 }
236 break;
237 default:
238 switch (target) {
239 case V4L2_SEL_TGT_COMPOSE:
240 return 0;
241 }
242 break;
243 }
244
245 return -EINVAL;
246}
247
248struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
249 struct v4l2_subdev_pad_config *cfg,
250 u32 which, uint32_t pad,
251 uint32_t target)
252{
253 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
254
255 if (which == V4L2_SUBDEV_FORMAT_TRY) {
256 switch (target) {
257 case V4L2_SEL_TGT_CROP:
258 return v4l2_subdev_get_try_crop(sd, cfg, pad);
259 case V4L2_SEL_TGT_COMPOSE:
260 return v4l2_subdev_get_try_compose(sd, cfg, pad);
261 }
262 }
263
264 switch (target) {
265 case V4L2_SEL_TGT_CROP:
266 return &isp_sd->fmt[pad].crop;
267 case V4L2_SEL_TGT_COMPOSE:
268 return &isp_sd->fmt[pad].compose;
269 }
270
271 return NULL;
272}
273
274struct v4l2_mbus_framefmt
275*atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
276 struct v4l2_subdev_pad_config *cfg, uint32_t which,
277 uint32_t pad)
278{
279 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
280
281 if (which == V4L2_SUBDEV_FORMAT_TRY)
282 return v4l2_subdev_get_try_format(sd, cfg, pad);
283
284 return &isp_sd->fmt[pad].fmt;
285}
286
287static void isp_get_fmt_rect(struct v4l2_subdev *sd,
288 struct v4l2_subdev_pad_config *cfg, uint32_t which,
289 struct v4l2_mbus_framefmt **ffmt,
290 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
291 struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
292{
293 unsigned int i;
294
295 for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
296 ffmt[i] = atomisp_subdev_get_ffmt(sd, cfg, which, i);
297 crop[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
298 V4L2_SEL_TGT_CROP);
299 comp[i] = atomisp_subdev_get_rect(sd, cfg, which, i,
300 V4L2_SEL_TGT_COMPOSE);
301 }
302}
303
304static void isp_subdev_propagate(struct v4l2_subdev *sd,
305 struct v4l2_subdev_pad_config *cfg,
306 u32 which, uint32_t pad, uint32_t target,
307 uint32_t flags)
308{
309 struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
310 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
311 *comp[ATOMISP_SUBDEV_PADS_NUM];
312
313 if (flags & V4L2_SEL_FLAG_KEEP_CONFIG)
314 return;
315
316 isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
317
318 switch (pad) {
319 case ATOMISP_SUBDEV_PAD_SINK: {
320 struct v4l2_rect r = {0};
321
322
323 r.width = ffmt[pad]->width;
324 r.height = ffmt[pad]->height;
325
326 atomisp_subdev_set_selection(sd, cfg, which, pad,
327 target, flags, &r);
328 break;
329 }
330 }
331}
332
333static int isp_subdev_get_selection(struct v4l2_subdev *sd,
334 struct v4l2_subdev_pad_config *cfg,
335 struct v4l2_subdev_selection *sel)
336{
337 struct v4l2_rect *rec;
338 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
339
340 if (rval)
341 return rval;
342
343 rec = atomisp_subdev_get_rect(sd, cfg, sel->which, sel->pad,
344 sel->target);
345 if (!rec)
346 return -EINVAL;
347
348 sel->r = *rec;
349 return 0;
350}
351
352static char *atomisp_pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK",
353 "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
354 "ATOMISP_SUBDEV_PAD_SOURCE_VF",
355 "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
356 "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO"
357 };
358
359int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
360 struct v4l2_subdev_pad_config *cfg,
361 u32 which, uint32_t pad, uint32_t target,
362 u32 flags, struct v4l2_rect *r)
363{
364 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
365 struct atomisp_device *isp = isp_sd->isp;
366 struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
367 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
368 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
369 *comp[ATOMISP_SUBDEV_PADS_NUM];
370 enum atomisp_input_stream_id stream_id;
371 unsigned int i;
372 unsigned int padding_w = pad_w;
373 unsigned int padding_h = pad_h;
374
375 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
376
377 isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
378
379 dev_dbg(isp->dev,
380 "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
381 atomisp_pad_str[pad], target == V4L2_SEL_TGT_CROP
382 ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
383 r->left, r->top, r->width, r->height,
384 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
385 : "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
386
387 r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
388 r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
389
390 switch (pad) {
391 case ATOMISP_SUBDEV_PAD_SINK: {
392
393 unsigned int dvs_w, dvs_h;
394
395 crop[pad]->width = ffmt[pad]->width;
396 crop[pad]->height = ffmt[pad]->height;
397
398
399
400 if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
401 "ov2722", 6) && crop[pad]->height == 1092) {
402 padding_w = 12;
403 padding_h = 12;
404 }
405
406 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) {
407 padding_w = 0;
408 padding_h = 0;
409 }
410
411 if (atomisp_subdev_format_conversion(isp_sd,
412 isp_sd->capture_pad)
413 && crop[pad]->width && crop[pad]->height)
414 crop[pad]->width -= padding_w, crop[pad]->height -= padding_h;
415
416
417 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA)
418 isp_sd->params.video_dis_en = 0;
419
420 if (isp_sd->params.video_dis_en &&
421 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
422 !isp_sd->continuous_mode->val) {
423
424
425
426
427
428 crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
429 ATOM_ISP_STEP_WIDTH);
430 crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
431 ATOM_ISP_STEP_HEIGHT);
432 }
433
434 crop[pad]->width = min(crop[pad]->width, r->width);
435 crop[pad]->height = min(crop[pad]->height, r->height);
436
437 if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
438 for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
439 i < ATOMISP_SUBDEV_PADS_NUM; i++) {
440 struct v4l2_rect tmp = *crop[pad];
441
442 atomisp_subdev_set_selection(
443 sd, cfg, which, i, V4L2_SEL_TGT_COMPOSE,
444 flags, &tmp);
445 }
446 }
447
448 if (which == V4L2_SUBDEV_FORMAT_TRY)
449 break;
450
451 if (isp_sd->params.video_dis_en &&
452 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
453 !isp_sd->continuous_mode->val) {
454 dvs_w = rounddown(crop[pad]->width / 5,
455 ATOM_ISP_STEP_WIDTH);
456 dvs_h = rounddown(crop[pad]->height / 5,
457 ATOM_ISP_STEP_HEIGHT);
458 } else if (!isp_sd->params.video_dis_en &&
459 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
460
461
462
463
464 dvs_w = dvs_h = 12;
465 } else
466 dvs_w = dvs_h = 0;
467
468 atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
469 atomisp_css_input_set_effective_resolution(isp_sd, stream_id,
470 crop[pad]->width, crop[pad]->height);
471
472 break;
473 }
474 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
475 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
476
477
478 if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
479
480 r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
481 r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
482 }
483
484 if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
485 && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
486 isp_sd->params.yuv_ds_en = false;
487 else
488 isp_sd->params.yuv_ds_en = true;
489
490 comp[pad]->width = r->width;
491 comp[pad]->height = r->height;
492
493 if (r->width == 0 || r->height == 0 ||
494 crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
495 crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
496 break;
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511 if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
512 crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
513 atomisp_css_input_set_effective_resolution(isp_sd,
514 stream_id,
515 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
516 height * r->width / r->height,
517 ATOM_ISP_STEP_WIDTH),
518 crop[ATOMISP_SUBDEV_PAD_SINK]->height);
519 else
520 atomisp_css_input_set_effective_resolution(isp_sd,
521 stream_id,
522 crop[ATOMISP_SUBDEV_PAD_SINK]->width,
523 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
524 width * r->height / r->width,
525 ATOM_ISP_STEP_WIDTH));
526
527 break;
528 }
529 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
530 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
531 comp[pad]->width = r->width;
532 comp[pad]->height = r->height;
533 break;
534 default:
535 return -EINVAL;
536 }
537
538
539 if (pad != ATOMISP_SUBDEV_PAD_SINK) {
540 ffmt[pad]->width = comp[pad]->width;
541 ffmt[pad]->height = comp[pad]->height;
542 }
543
544 if (!atomisp_subdev_get_rect(sd, cfg, which, pad, target))
545 return -EINVAL;
546 *r = *atomisp_subdev_get_rect(sd, cfg, which, pad, target);
547
548 dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
549 r->left, r->top, r->width, r->height);
550
551 return 0;
552}
553
554static int isp_subdev_set_selection(struct v4l2_subdev *sd,
555 struct v4l2_subdev_pad_config *cfg,
556 struct v4l2_subdev_selection *sel)
557{
558 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
559
560 if (rval)
561 return rval;
562
563 return atomisp_subdev_set_selection(sd, cfg, sel->which, sel->pad,
564 sel->target, sel->flags, &sel->r);
565}
566
567static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd)
568{
569 struct v4l2_control ctrl = {0};
570 struct atomisp_device *isp = asd->isp;
571 int hbin, vbin;
572 int ret;
573
574 if (isp->inputs[asd->input_curr].type == FILE_INPUT ||
575 isp->inputs[asd->input_curr].type == TEST_PATTERN)
576 return 0;
577
578 ctrl.id = V4L2_CID_BIN_FACTOR_HORZ;
579 ret =
580 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
581 &ctrl);
582 hbin = ctrl.value;
583 ctrl.id = V4L2_CID_BIN_FACTOR_VERT;
584 ret |=
585 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
586 &ctrl);
587 vbin = ctrl.value;
588
589
590
591
592
593
594
595 if (ret || hbin != vbin)
596 hbin = 0;
597
598 return hbin;
599}
600
601void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
602 struct v4l2_subdev_pad_config *cfg, uint32_t which,
603 u32 pad, struct v4l2_mbus_framefmt *ffmt)
604{
605 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
606 struct atomisp_device *isp = isp_sd->isp;
607 struct v4l2_mbus_framefmt *__ffmt =
608 atomisp_subdev_get_ffmt(sd, cfg, which, pad);
609 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
610 enum atomisp_input_stream_id stream_id;
611
612 dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
613 atomisp_pad_str[pad], ffmt->width, ffmt->height, ffmt->code,
614 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
615 : "V4L2_SUBDEV_FORMAT_ACTIVE");
616
617 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
618
619 switch (pad) {
620 case ATOMISP_SUBDEV_PAD_SINK: {
621 const struct atomisp_in_fmt_conv *fc =
622 atomisp_find_in_fmt_conv(ffmt->code);
623
624 if (!fc) {
625 fc = atomisp_in_fmt_conv;
626 ffmt->code = fc->code;
627 dev_dbg(isp->dev, "using 0x%8.8x instead\n",
628 ffmt->code);
629 }
630
631 *__ffmt = *ffmt;
632
633 isp_subdev_propagate(sd, cfg, which, pad,
634 V4L2_SEL_TGT_CROP, 0);
635
636 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
637 atomisp_css_input_set_resolution(isp_sd,
638 stream_id, ffmt);
639 atomisp_css_input_set_binning_factor(isp_sd,
640 stream_id,
641 atomisp_get_sensor_bin_factor(isp_sd));
642 atomisp_css_input_set_bayer_order(isp_sd, stream_id,
643 fc->bayer_order);
644 atomisp_css_input_set_format(isp_sd, stream_id,
645 fc->atomisp_in_fmt);
646 atomisp_css_set_default_isys_config(isp_sd, stream_id,
647 ffmt);
648 }
649
650 break;
651 }
652 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
653 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
654 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
655 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
656 __ffmt->code = ffmt->code;
657 break;
658 }
659}
660
661
662
663
664
665
666
667
668
669
670
671static int isp_subdev_get_format(struct v4l2_subdev *sd,
672 struct v4l2_subdev_pad_config *cfg,
673 struct v4l2_subdev_format *fmt)
674{
675 fmt->format = *atomisp_subdev_get_ffmt(sd, cfg, fmt->which, fmt->pad);
676
677 return 0;
678}
679
680
681
682
683
684
685
686
687
688
689
690static int isp_subdev_set_format(struct v4l2_subdev *sd,
691 struct v4l2_subdev_pad_config *cfg,
692 struct v4l2_subdev_format *fmt)
693{
694 atomisp_subdev_set_ffmt(sd, cfg, fmt->which, fmt->pad, &fmt->format);
695
696 return 0;
697}
698
699
700static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
701 .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power,
702 .subscribe_event = isp_subdev_subscribe_event,
703 .unsubscribe_event = isp_subdev_unsubscribe_event,
704};
705
706
707static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
708 .enum_mbus_code = isp_subdev_enum_mbus_code,
709 .get_fmt = isp_subdev_get_format,
710 .set_fmt = isp_subdev_set_format,
711 .get_selection = isp_subdev_get_selection,
712 .set_selection = isp_subdev_set_selection,
713 .link_validate = v4l2_subdev_link_validate_default,
714};
715
716
717static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
718 .core = &isp_subdev_v4l2_core_ops,
719 .pad = &isp_subdev_v4l2_pad_ops,
720};
721
722static void isp_subdev_init_params(struct atomisp_sub_device *asd)
723{
724 unsigned int i;
725
726
727 INIT_LIST_HEAD(&asd->s3a_stats);
728 INIT_LIST_HEAD(&asd->s3a_stats_in_css);
729 INIT_LIST_HEAD(&asd->s3a_stats_ready);
730 INIT_LIST_HEAD(&asd->dis_stats);
731 INIT_LIST_HEAD(&asd->dis_stats_in_css);
732 spin_lock_init(&asd->dis_stats_lock);
733 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
734 INIT_LIST_HEAD(&asd->metadata[i]);
735 INIT_LIST_HEAD(&asd->metadata_in_css[i]);
736 INIT_LIST_HEAD(&asd->metadata_ready[i]);
737 }
738}
739
740
741
742
743
744
745
746
747
748
749static int isp_subdev_link_setup(struct media_entity *entity,
750 const struct media_pad *local,
751 const struct media_pad *remote, u32 flags)
752{
753 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
754 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
755 struct atomisp_device *isp = isp_sd->isp;
756 unsigned int i;
757
758 switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) {
759 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
760
761 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
762 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
763 break;
764 }
765
766 if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE)
767 return -EBUSY;
768
769 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
770 if (remote->entity != &isp->csi2_port[i].subdev.entity)
771 continue;
772
773 isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i;
774 return 0;
775 }
776
777 return -EINVAL;
778
779 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE:
780
781 if (flags & MEDIA_LNK_FL_ENABLED) {
782 if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 &&
783 isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1
784 + ATOMISP_CAMERA_NR_PORTS))
785 return -EBUSY;
786 isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY;
787 } else {
788 if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY)
789 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
790 }
791 break;
792
793 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE:
794
795 break;
796
797 case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE:
798
799 break;
800
801 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE:
802
803 break;
804
805 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE:
806
807 break;
808
809 default:
810 return -EINVAL;
811 }
812
813 return 0;
814}
815
816
817static const struct media_entity_operations isp_subdev_media_ops = {
818 .link_setup = isp_subdev_link_setup,
819 .link_validate = v4l2_subdev_link_validate,
820
821};
822
823static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
824{
825 struct atomisp_device *isp = asd->isp;
826 struct v4l2_ctrl *ctrl = asd->run_mode;
827 struct v4l2_ctrl *c;
828 s32 mode;
829
830 if (ctrl->val != ATOMISP_RUN_MODE_VIDEO &&
831 asd->continuous_mode->val)
832 mode = ATOMISP_RUN_MODE_PREVIEW;
833 else
834 mode = ctrl->val;
835
836 c = v4l2_ctrl_find(
837 isp->inputs[asd->input_curr].camera->ctrl_handler,
838 V4L2_CID_RUN_MODE);
839
840 if (c)
841 return v4l2_ctrl_s_ctrl(c, mode);
842
843 return 0;
844}
845
846int atomisp_update_run_mode(struct atomisp_sub_device *asd)
847{
848 int rval;
849
850 mutex_lock(asd->ctrl_handler.lock);
851 rval = __atomisp_update_run_mode(asd);
852 mutex_unlock(asd->ctrl_handler.lock);
853
854 return rval;
855}
856
857static int s_ctrl(struct v4l2_ctrl *ctrl)
858{
859 struct atomisp_sub_device *asd = container_of(
860 ctrl->handler, struct atomisp_sub_device, ctrl_handler);
861
862 switch (ctrl->id) {
863 case V4L2_CID_RUN_MODE:
864 return __atomisp_update_run_mode(asd);
865 case V4L2_CID_DEPTH_MODE:
866 if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
867 dev_err(asd->isp->dev,
868 "ISP is streaming, it is not supported to change the depth mode\n");
869 return -EINVAL;
870 }
871 break;
872 }
873
874 return 0;
875}
876
877static const struct v4l2_ctrl_ops ctrl_ops = {
878 .s_ctrl = &s_ctrl,
879};
880
881static const struct v4l2_ctrl_config ctrl_fmt_auto = {
882 .ops = &ctrl_ops,
883 .id = V4L2_CID_FMT_AUTO,
884 .name = "Automatic format guessing",
885 .type = V4L2_CTRL_TYPE_BOOLEAN,
886 .min = 0,
887 .max = 1,
888 .step = 1,
889 .def = 1,
890};
891
892static const char *const ctrl_run_mode_menu[] = {
893 NULL,
894 "Video",
895 "Still capture",
896 "Continuous capture",
897 "Preview",
898};
899
900static const struct v4l2_ctrl_config ctrl_run_mode = {
901 .ops = &ctrl_ops,
902 .id = V4L2_CID_RUN_MODE,
903 .name = "Atomisp run mode",
904 .type = V4L2_CTRL_TYPE_MENU,
905 .min = 1,
906 .def = 1,
907 .max = 4,
908 .qmenu = ctrl_run_mode_menu,
909};
910
911static const char *const ctrl_vfpp_mode_menu[] = {
912 "Enable",
913 "Disable to scaler mode",
914 "Disable to low latency mode",
915};
916
917static const struct v4l2_ctrl_config ctrl_vfpp = {
918 .id = V4L2_CID_VFPP,
919 .name = "Atomisp vf postprocess",
920 .type = V4L2_CTRL_TYPE_MENU,
921 .min = 0,
922 .def = 0,
923 .max = 2,
924 .qmenu = ctrl_vfpp_mode_menu,
925};
926
927
928
929
930
931
932
933
934static const struct v4l2_ctrl_config ctrl_continuous_mode = {
935 .ops = &ctrl_ops,
936 .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE,
937 .type = V4L2_CTRL_TYPE_BOOLEAN,
938 .name = "Continuous mode",
939 .min = 0,
940 .max = 1,
941 .step = 1,
942 .def = 0,
943};
944
945
946
947
948
949
950
951
952
953
954
955
956static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
957 .ops = &ctrl_ops,
958 .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
959 .type = V4L2_CTRL_TYPE_INTEGER,
960 .name = "Continuous raw ringbuffer size",
961 .min = 1,
962 .max = 100,
963 .step = 1,
964 .def = 3,
965};
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
982 .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
983 .type = V4L2_CTRL_TYPE_BOOLEAN,
984 .name = "Continuous viewfinder",
985 .min = 0,
986 .max = 1,
987 .step = 1,
988 .def = 0,
989};
990
991
992
993
994
995
996
997
998
999static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
1000 .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
1001 .type = V4L2_CTRL_TYPE_BOOLEAN,
1002 .name = "Lock Unlock Raw Buffer",
1003 .min = 0,
1004 .max = 1,
1005 .step = 1,
1006 .def = 0,
1007};
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017static const struct v4l2_ctrl_config ctrl_disable_dz = {
1018 .id = V4L2_CID_DISABLE_DZ,
1019 .type = V4L2_CTRL_TYPE_BOOLEAN,
1020 .name = "Disable digital zoom",
1021 .min = 0,
1022 .max = 1,
1023 .step = 1,
1024 .def = 0,
1025};
1026
1027
1028
1029
1030
1031
1032
1033
1034static const struct v4l2_ctrl_config ctrl_depth_mode = {
1035 .ops = &ctrl_ops,
1036 .id = V4L2_CID_DEPTH_MODE,
1037 .type = V4L2_CTRL_TYPE_BOOLEAN,
1038 .name = "Depth mode",
1039 .min = 0,
1040 .max = 1,
1041 .step = 1,
1042 .def = 0,
1043};
1044
1045
1046
1047
1048
1049
1050
1051
1052static const struct v4l2_ctrl_config ctrl_select_isp_version = {
1053 .ops = &ctrl_ops,
1054 .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION,
1055 .type = V4L2_CTRL_TYPE_BOOLEAN,
1056 .name = "Select Isp version",
1057 .min = 0,
1058 .max = 1,
1059 .step = 1,
1060 .def = 0,
1061};
1062
1063#if 0
1064
1065
1066
1067
1068
1069
1070
1071static const struct v4l2_ctrl_config ctrl_ion_dev_fd = {
1072 .ops = &ctrl_ops,
1073 .id = V4L2_CID_ATOMISP_ION_DEVICE_FD,
1074 .type = V4L2_CTRL_TYPE_INTEGER,
1075 .name = "Ion Device Fd",
1076 .min = -1,
1077 .max = 1024,
1078 .step = 1,
1079 .def = ION_FD_UNSET
1080};
1081#endif
1082
1083static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
1084 struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
1085{
1086 pipe->type = buf_type;
1087 pipe->asd = asd;
1088 pipe->isp = asd->isp;
1089 spin_lock_init(&pipe->irq_lock);
1090 INIT_LIST_HEAD(&pipe->activeq);
1091 INIT_LIST_HEAD(&pipe->activeq_out);
1092 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
1093 INIT_LIST_HEAD(&pipe->per_frame_params);
1094 memset(pipe->frame_request_config_id,
1095 0, VIDEO_MAX_FRAME * sizeof(unsigned int));
1096 memset(pipe->frame_params,
1097 0, VIDEO_MAX_FRAME *
1098 sizeof(struct atomisp_css_params_with_list *));
1099}
1100
1101static void atomisp_init_acc_pipe(struct atomisp_sub_device *asd,
1102 struct atomisp_acc_pipe *pipe)
1103{
1104 pipe->asd = asd;
1105 pipe->isp = asd->isp;
1106 INIT_LIST_HEAD(&asd->acc.fw);
1107 INIT_LIST_HEAD(&asd->acc.memory_maps);
1108 ida_init(&asd->acc.ida);
1109}
1110
1111
1112
1113
1114
1115
1116
1117static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
1118{
1119 struct v4l2_subdev *sd = &asd->subdev;
1120 struct media_pad *pads = asd->pads;
1121 struct media_entity *me = &sd->entity;
1122 int ret;
1123
1124 asd->input = ATOMISP_SUBDEV_INPUT_NONE;
1125
1126 v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
1127 sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index);
1128 v4l2_set_subdevdata(sd, asd);
1129 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1130
1131 pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1132 pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
1133 pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
1134 pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
1135 pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
1136
1137 asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
1138 MEDIA_BUS_FMT_SBGGR10_1X10;
1139 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
1140 MEDIA_BUS_FMT_SBGGR10_1X10;
1141 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
1142 MEDIA_BUS_FMT_SBGGR10_1X10;
1143 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
1144 MEDIA_BUS_FMT_SBGGR10_1X10;
1145 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
1146 MEDIA_BUS_FMT_SBGGR10_1X10;
1147
1148 me->ops = &isp_subdev_media_ops;
1149 me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
1150 ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
1151 if (ret < 0)
1152 return ret;
1153
1154 atomisp_init_subdev_pipe(asd, &asd->video_in,
1155 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1156
1157 atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
1158 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1159
1160 atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
1161 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1162
1163 atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
1164 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1165
1166 atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
1167 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1168
1169 atomisp_init_acc_pipe(asd, &asd->video_acc);
1170
1171 ret = atomisp_video_init(&asd->video_in, "MEMORY");
1172 if (ret < 0)
1173 return ret;
1174
1175 ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE");
1176 if (ret < 0)
1177 return ret;
1178
1179 ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER");
1180 if (ret < 0)
1181 return ret;
1182
1183 ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW");
1184 if (ret < 0)
1185 return ret;
1186
1187 ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO");
1188 if (ret < 0)
1189 return ret;
1190
1191 atomisp_acc_init(&asd->video_acc, "ACC");
1192
1193 ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
1194 if (ret)
1195 return ret;
1196
1197 asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1198 &ctrl_fmt_auto, NULL);
1199 asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1200 &ctrl_run_mode, NULL);
1201 asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1202 &ctrl_vfpp, NULL);
1203 asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1204 &ctrl_continuous_mode, NULL);
1205 asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1206 &ctrl_continuous_viewfinder,
1207 NULL);
1208 asd->continuous_raw_buffer_size =
1209 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1210 &ctrl_continuous_raw_buffer_size,
1211 NULL);
1212
1213 asd->enable_raw_buffer_lock =
1214 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1215 &ctrl_enable_raw_buffer_lock,
1216 NULL);
1217 asd->depth_mode =
1218 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1219 &ctrl_depth_mode,
1220 NULL);
1221 asd->disable_dz =
1222 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1223 &ctrl_disable_dz,
1224 NULL);
1225 if (IS_ISP2401) {
1226 asd->select_isp_version = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1227 &ctrl_select_isp_version,
1228 NULL);
1229 }
1230
1231
1232 asd->subdev.ctrl_handler = &asd->ctrl_handler;
1233 spin_lock_init(&asd->raw_buffer_bitmap_lock);
1234 return asd->ctrl_handler.error;
1235}
1236
1237int atomisp_create_pads_links(struct atomisp_device *isp)
1238{
1239 struct atomisp_sub_device *asd;
1240 int i, j, ret = 0;
1241
1242 isp->num_of_streams = 2;
1243 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
1244 for (j = 0; j < isp->num_of_streams; j++) {
1245 ret =
1246 media_create_pad_link(&isp->csi2_port[i].subdev.
1247 entity, CSI2_PAD_SOURCE,
1248 &isp->asd[j].subdev.entity,
1249 ATOMISP_SUBDEV_PAD_SINK, 0);
1250 if (ret < 0)
1251 return ret;
1252 }
1253 }
1254 for (i = 0; i < isp->input_cnt - 2; i++) {
1255 ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
1256 &isp->csi2_port[isp->inputs[i].
1257 port].subdev.entity,
1258 CSI2_PAD_SINK,
1259 MEDIA_LNK_FL_ENABLED |
1260 MEDIA_LNK_FL_IMMUTABLE);
1261 if (ret < 0)
1262 return ret;
1263 }
1264 for (i = 0; i < isp->num_of_streams; i++) {
1265 asd = &isp->asd[i];
1266 ret = media_create_pad_link(&asd->subdev.entity,
1267 ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
1268 &asd->video_out_preview.vdev.entity,
1269 0, 0);
1270 if (ret < 0)
1271 return ret;
1272 ret = media_create_pad_link(&asd->subdev.entity,
1273 ATOMISP_SUBDEV_PAD_SOURCE_VF,
1274 &asd->video_out_vf.vdev.entity, 0,
1275 0);
1276 if (ret < 0)
1277 return ret;
1278 ret = media_create_pad_link(&asd->subdev.entity,
1279 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
1280 &asd->video_out_capture.vdev.entity,
1281 0, 0);
1282 if (ret < 0)
1283 return ret;
1284 ret = media_create_pad_link(&asd->subdev.entity,
1285 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
1286 &asd->video_out_video_capture.vdev.
1287 entity, 0, 0);
1288 if (ret < 0)
1289 return ret;
1290
1291
1292
1293
1294 if (asd->index)
1295 return 0;
1296 ret = media_create_pad_link(&asd->video_in.vdev.entity,
1297 0, &asd->subdev.entity,
1298 ATOMISP_SUBDEV_PAD_SINK, 0);
1299 if (ret < 0)
1300 return ret;
1301 }
1302 return 0;
1303}
1304
1305static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
1306{
1307 v4l2_ctrl_handler_free(&asd->ctrl_handler);
1308
1309 media_entity_cleanup(&asd->subdev.entity);
1310}
1311
1312void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
1313{
1314 struct v4l2_fh *fh, *fh_tmp;
1315 struct v4l2_event event;
1316 unsigned int i, pending_event;
1317
1318 list_for_each_entry_safe(fh, fh_tmp,
1319 &asd->subdev.devnode->fh_list, list) {
1320 pending_event = v4l2_event_pending(fh);
1321 for (i = 0; i < pending_event; i++)
1322 v4l2_event_dequeue(fh, &event, 1);
1323 }
1324}
1325
1326void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
1327{
1328 atomisp_subdev_cleanup_entities(asd);
1329 v4l2_device_unregister_subdev(&asd->subdev);
1330 atomisp_video_unregister(&asd->video_in);
1331 atomisp_video_unregister(&asd->video_out_preview);
1332 atomisp_video_unregister(&asd->video_out_vf);
1333 atomisp_video_unregister(&asd->video_out_capture);
1334 atomisp_video_unregister(&asd->video_out_video_capture);
1335 atomisp_acc_unregister(&asd->video_acc);
1336}
1337
1338int atomisp_subdev_register_entities(struct atomisp_sub_device *asd,
1339 struct v4l2_device *vdev)
1340{
1341 int ret;
1342 u32 device_caps;
1343
1344
1345
1346
1347
1348
1349 device_caps = V4L2_CAP_VIDEO_CAPTURE |
1350 V4L2_CAP_STREAMING;
1351
1352
1353
1354 ret = v4l2_device_register_subdev(vdev, &asd->subdev);
1355 if (ret < 0)
1356 goto error;
1357
1358 asd->video_out_capture.vdev.v4l2_dev = vdev;
1359 asd->video_out_capture.vdev.device_caps = device_caps |
1360 V4L2_CAP_VIDEO_OUTPUT;
1361 ret = video_register_device(&asd->video_out_capture.vdev,
1362 VFL_TYPE_VIDEO, -1);
1363 if (ret < 0)
1364 goto error;
1365
1366 asd->video_out_vf.vdev.v4l2_dev = vdev;
1367 asd->video_out_vf.vdev.device_caps = device_caps |
1368 V4L2_CAP_VIDEO_OUTPUT;
1369 ret = video_register_device(&asd->video_out_vf.vdev,
1370 VFL_TYPE_VIDEO, -1);
1371 if (ret < 0)
1372 goto error;
1373 asd->video_out_preview.vdev.v4l2_dev = vdev;
1374 asd->video_out_preview.vdev.device_caps = device_caps |
1375 V4L2_CAP_VIDEO_OUTPUT;
1376 ret = video_register_device(&asd->video_out_preview.vdev,
1377 VFL_TYPE_VIDEO, -1);
1378 if (ret < 0)
1379 goto error;
1380 asd->video_out_video_capture.vdev.v4l2_dev = vdev;
1381 asd->video_out_video_capture.vdev.device_caps = device_caps |
1382 V4L2_CAP_VIDEO_OUTPUT;
1383 ret = video_register_device(&asd->video_out_video_capture.vdev,
1384 VFL_TYPE_VIDEO, -1);
1385 if (ret < 0)
1386 goto error;
1387 asd->video_acc.vdev.v4l2_dev = vdev;
1388 asd->video_acc.vdev.device_caps = device_caps |
1389 V4L2_CAP_VIDEO_OUTPUT;
1390 ret = video_register_device(&asd->video_acc.vdev,
1391 VFL_TYPE_VIDEO, -1);
1392 if (ret < 0)
1393 goto error;
1394
1395
1396
1397
1398
1399 if (asd->index)
1400 return 0;
1401
1402 asd->video_in.vdev.v4l2_dev = vdev;
1403 asd->video_in.vdev.device_caps = device_caps |
1404 V4L2_CAP_VIDEO_CAPTURE;
1405 ret = video_register_device(&asd->video_in.vdev,
1406 VFL_TYPE_VIDEO, -1);
1407 if (ret < 0)
1408 goto error;
1409
1410 return 0;
1411
1412error:
1413 atomisp_subdev_unregister_entities(asd);
1414 return ret;
1415}
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425int atomisp_subdev_init(struct atomisp_device *isp)
1426{
1427 struct atomisp_sub_device *asd;
1428 int i, ret = 0;
1429
1430
1431
1432
1433
1434 isp->num_of_streams = 2;
1435 isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) *
1436 isp->num_of_streams, GFP_KERNEL);
1437 if (!isp->asd)
1438 return -ENOMEM;
1439 for (i = 0; i < isp->num_of_streams; i++) {
1440 asd = &isp->asd[i];
1441 spin_lock_init(&asd->lock);
1442 asd->isp = isp;
1443 isp_subdev_init_params(asd);
1444 asd->index = i;
1445 ret = isp_subdev_init_entities(asd);
1446 if (ret < 0) {
1447 atomisp_subdev_cleanup_entities(asd);
1448 break;
1449 }
1450 }
1451
1452 return ret;
1453}
1454