1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Medifield PNW Camera Imaging ISP subsystem.
4 *
5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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
33 const 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 // disabled due to clang warnings
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 /* no valid V4L2 MBUS code for metadata format, so leave it 0. */
58 { 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 },
59 {}
60 };
61
62 static 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
atomisp_subdev_uncompressed_code(u32 code)72 u32 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
atomisp_subdev_is_compressed(u32 code)83 bool 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
atomisp_find_in_fmt_conv(u32 code)95 const 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
atomisp_find_in_fmt_conv_by_atomisp_in_fmt(enum atomisp_input_format atomisp_in_fmt)106 const 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
atomisp_subdev_format_conversion(struct atomisp_sub_device * asd,unsigned int source_pad)118 bool 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
atomisp_subdev_source_pad(struct video_device * vdev)133 uint16_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 * V4L2 subdev operations
149 */
150
151 /*
152 * isp_subdev_ioctl - CCDC module private ioctl's
153 * @sd: ISP V4L2 subdevice
154 * @cmd: ioctl command
155 * @arg: ioctl argument
156 *
157 * Return 0 on success or a negative error code otherwise.
158 */
isp_subdev_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)159 static long isp_subdev_ioctl(struct v4l2_subdev *sd,
160 unsigned int cmd, void *arg)
161 {
162 return 0;
163 }
164
165 /*
166 * isp_subdev_set_power - Power on/off the CCDC module
167 * @sd: ISP V4L2 subdevice
168 * @on: power on/off
169 *
170 * Return 0 on success or a negative error code otherwise.
171 */
isp_subdev_set_power(struct v4l2_subdev * sd,int on)172 static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
173 {
174 return 0;
175 }
176
isp_subdev_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)177 static 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
isp_subdev_unsubscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)201 static 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 * isp_subdev_enum_mbus_code - Handle pixel format enumeration
210 * @sd: pointer to v4l2 subdev structure
211 * @fh : V4L2 subdev file handle
212 * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
213 * return -EINVAL or zero on success
214 */
isp_subdev_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)215 static 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
isp_subdev_validate_rect(struct v4l2_subdev * sd,uint32_t pad,uint32_t target)227 static 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
atomisp_subdev_get_rect(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,u32 which,uint32_t pad,uint32_t target)248 struct 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
274 struct v4l2_mbus_framefmt
atomisp_subdev_get_ffmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,uint32_t which,uint32_t pad)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
isp_get_fmt_rect(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,uint32_t which,struct v4l2_mbus_framefmt ** ffmt,struct v4l2_rect * crop[ATOMISP_SUBDEV_PADS_NUM],struct v4l2_rect * comp[ATOMISP_SUBDEV_PADS_NUM])287 static 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
isp_subdev_propagate(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,u32 which,uint32_t pad,uint32_t target,uint32_t flags)304 static 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 /* Only crop target supported on sink pad. */
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
isp_subdev_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)333 static 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
atomisp_pad_str(unsigned int pad)352 static const char *atomisp_pad_str(unsigned int pad)
353 {
354 static const char *const pad_str[] = {
355 "ATOMISP_SUBDEV_PAD_SINK",
356 "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
357 "ATOMISP_SUBDEV_PAD_SOURCE_VF",
358 "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
359 "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO",
360 };
361
362 if (pad >= ARRAY_SIZE(pad_str))
363 return "ATOMISP_INVALID_PAD";
364 return pad_str[pad];
365 }
366
atomisp_subdev_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,u32 which,uint32_t pad,uint32_t target,u32 flags,struct v4l2_rect * r)367 int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
368 struct v4l2_subdev_pad_config *cfg,
369 u32 which, uint32_t pad, uint32_t target,
370 u32 flags, struct v4l2_rect *r)
371 {
372 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
373 struct atomisp_device *isp = isp_sd->isp;
374 struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
375 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
376 struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
377 *comp[ATOMISP_SUBDEV_PADS_NUM];
378 enum atomisp_input_stream_id stream_id;
379 unsigned int i;
380 unsigned int padding_w = pad_w;
381 unsigned int padding_h = pad_h;
382
383 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
384
385 isp_get_fmt_rect(sd, cfg, which, ffmt, crop, comp);
386
387 dev_dbg(isp->dev,
388 "sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
389 atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP
390 ? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
391 r->left, r->top, r->width, r->height,
392 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
393 : "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
394
395 r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
396 r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
397
398 switch (pad) {
399 case ATOMISP_SUBDEV_PAD_SINK: {
400 /* Only crop target supported on sink pad. */
401 unsigned int dvs_w, dvs_h;
402
403 crop[pad]->width = ffmt[pad]->width;
404 crop[pad]->height = ffmt[pad]->height;
405
406 /* Workaround for BYT 1080p perfectshot since the maxinum resolution of
407 * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
408 if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
409 "ov2722", 6) && crop[pad]->height == 1092) {
410 padding_w = 12;
411 padding_h = 12;
412 }
413
414 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA) {
415 padding_w = 0;
416 padding_h = 0;
417 }
418
419 if (atomisp_subdev_format_conversion(isp_sd,
420 isp_sd->capture_pad)
421 && crop[pad]->width && crop[pad]->height) {
422 crop[pad]->width -= padding_w;
423 crop[pad]->height -= padding_h;
424 }
425
426 /* if subdev type is SOC camera,we do not need to set DVS */
427 if (isp->inputs[isp_sd->input_curr].type == SOC_CAMERA)
428 isp_sd->params.video_dis_en = 0;
429
430 if (isp_sd->params.video_dis_en &&
431 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
432 !isp_sd->continuous_mode->val) {
433 /* This resolution contains 20 % of DVS slack
434 * (of the desired captured image before
435 * scaling, or 1 / 6 of what we get from the
436 * sensor) in both width and height. Remove
437 * it. */
438 crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
439 ATOM_ISP_STEP_WIDTH);
440 crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
441 ATOM_ISP_STEP_HEIGHT);
442 }
443
444 crop[pad]->width = min(crop[pad]->width, r->width);
445 crop[pad]->height = min(crop[pad]->height, r->height);
446
447 if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
448 for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
449 i < ATOMISP_SUBDEV_PADS_NUM; i++) {
450 struct v4l2_rect tmp = *crop[pad];
451
452 atomisp_subdev_set_selection(
453 sd, cfg, which, i, V4L2_SEL_TGT_COMPOSE,
454 flags, &tmp);
455 }
456 }
457
458 if (which == V4L2_SUBDEV_FORMAT_TRY)
459 break;
460
461 if (isp_sd->params.video_dis_en &&
462 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
463 !isp_sd->continuous_mode->val) {
464 dvs_w = rounddown(crop[pad]->width / 5,
465 ATOM_ISP_STEP_WIDTH);
466 dvs_h = rounddown(crop[pad]->height / 5,
467 ATOM_ISP_STEP_HEIGHT);
468 } else if (!isp_sd->params.video_dis_en &&
469 isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
470 /*
471 * For CSS2.0, digital zoom needs to set dvs envelope to 12
472 * when dvs is disabled.
473 */
474 dvs_w = dvs_h = 12;
475 } else
476 dvs_w = dvs_h = 0;
477
478 atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
479 atomisp_css_input_set_effective_resolution(isp_sd, stream_id,
480 crop[pad]->width, crop[pad]->height);
481
482 break;
483 }
484 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
485 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
486 /* Only compose target is supported on source pads. */
487
488 if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
489 /* Scaling is disabled in this mode */
490 r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
491 r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
492 }
493
494 if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
495 && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
496 isp_sd->params.yuv_ds_en = false;
497 else
498 isp_sd->params.yuv_ds_en = true;
499
500 comp[pad]->width = r->width;
501 comp[pad]->height = r->height;
502
503 if (r->width == 0 || r->height == 0 ||
504 crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
505 crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
506 break;
507 /*
508 * do cropping on sensor input if ratio of required resolution
509 * is different with sensor output resolution ratio:
510 *
511 * ratio = width / height
512 *
513 * if ratio_output < ratio_sensor:
514 * effect_width = sensor_height * out_width / out_height;
515 * effect_height = sensor_height;
516 * else
517 * effect_width = sensor_width;
518 * effect_height = sensor_width * out_height / out_width;
519 *
520 */
521 if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
522 crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
523 atomisp_css_input_set_effective_resolution(isp_sd,
524 stream_id,
525 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
526 height * r->width / r->height,
527 ATOM_ISP_STEP_WIDTH),
528 crop[ATOMISP_SUBDEV_PAD_SINK]->height);
529 else
530 atomisp_css_input_set_effective_resolution(isp_sd,
531 stream_id,
532 crop[ATOMISP_SUBDEV_PAD_SINK]->width,
533 rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
534 width * r->height / r->width,
535 ATOM_ISP_STEP_WIDTH));
536
537 break;
538 }
539 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
540 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
541 comp[pad]->width = r->width;
542 comp[pad]->height = r->height;
543 break;
544 default:
545 return -EINVAL;
546 }
547
548 /* Set format dimensions on non-sink pads as well. */
549 if (pad != ATOMISP_SUBDEV_PAD_SINK) {
550 ffmt[pad]->width = comp[pad]->width;
551 ffmt[pad]->height = comp[pad]->height;
552 }
553
554 if (!atomisp_subdev_get_rect(sd, cfg, which, pad, target))
555 return -EINVAL;
556 *r = *atomisp_subdev_get_rect(sd, cfg, which, pad, target);
557
558 dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
559 r->left, r->top, r->width, r->height);
560
561 return 0;
562 }
563
isp_subdev_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)564 static int isp_subdev_set_selection(struct v4l2_subdev *sd,
565 struct v4l2_subdev_pad_config *cfg,
566 struct v4l2_subdev_selection *sel)
567 {
568 int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
569
570 if (rval)
571 return rval;
572
573 return atomisp_subdev_set_selection(sd, cfg, sel->which, sel->pad,
574 sel->target, sel->flags, &sel->r);
575 }
576
atomisp_get_sensor_bin_factor(struct atomisp_sub_device * asd)577 static int atomisp_get_sensor_bin_factor(struct atomisp_sub_device *asd)
578 {
579 struct v4l2_control ctrl = {0};
580 struct atomisp_device *isp = asd->isp;
581 int hbin, vbin;
582 int ret;
583
584 if (isp->inputs[asd->input_curr].type == FILE_INPUT ||
585 isp->inputs[asd->input_curr].type == TEST_PATTERN)
586 return 0;
587
588 ctrl.id = V4L2_CID_BIN_FACTOR_HORZ;
589 ret =
590 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
591 &ctrl);
592 hbin = ctrl.value;
593 ctrl.id = V4L2_CID_BIN_FACTOR_VERT;
594 ret |=
595 v4l2_g_ctrl(isp->inputs[asd->input_curr].camera->ctrl_handler,
596 &ctrl);
597 vbin = ctrl.value;
598
599 /*
600 * ISP needs to know binning factor from sensor.
601 * In case horizontal and vertical sensor's binning factors
602 * are different or sensor does not support binning factor CID,
603 * ISP will apply default 0 value.
604 */
605 if (ret || hbin != vbin)
606 hbin = 0;
607
608 return hbin;
609 }
610
atomisp_subdev_set_ffmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,uint32_t which,u32 pad,struct v4l2_mbus_framefmt * ffmt)611 void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
612 struct v4l2_subdev_pad_config *cfg, uint32_t which,
613 u32 pad, struct v4l2_mbus_framefmt *ffmt)
614 {
615 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
616 struct atomisp_device *isp = isp_sd->isp;
617 struct v4l2_mbus_framefmt *__ffmt =
618 atomisp_subdev_get_ffmt(sd, cfg, which, pad);
619 u16 vdev_pad = atomisp_subdev_source_pad(sd->devnode);
620 enum atomisp_input_stream_id stream_id;
621
622 dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
623 atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code,
624 which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
625 : "V4L2_SUBDEV_FORMAT_ACTIVE");
626
627 stream_id = atomisp_source_pad_to_stream_id(isp_sd, vdev_pad);
628
629 switch (pad) {
630 case ATOMISP_SUBDEV_PAD_SINK: {
631 const struct atomisp_in_fmt_conv *fc =
632 atomisp_find_in_fmt_conv(ffmt->code);
633
634 if (!fc) {
635 fc = atomisp_in_fmt_conv;
636 ffmt->code = fc->code;
637 dev_dbg(isp->dev, "using 0x%8.8x instead\n",
638 ffmt->code);
639 }
640
641 *__ffmt = *ffmt;
642
643 isp_subdev_propagate(sd, cfg, which, pad,
644 V4L2_SEL_TGT_CROP, 0);
645
646 if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
647 atomisp_css_input_set_resolution(isp_sd,
648 stream_id, ffmt);
649 atomisp_css_input_set_binning_factor(isp_sd,
650 stream_id,
651 atomisp_get_sensor_bin_factor(isp_sd));
652 atomisp_css_input_set_bayer_order(isp_sd, stream_id,
653 fc->bayer_order);
654 atomisp_css_input_set_format(isp_sd, stream_id,
655 fc->atomisp_in_fmt);
656 atomisp_css_set_default_isys_config(isp_sd, stream_id,
657 ffmt);
658 }
659
660 break;
661 }
662 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
663 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
664 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
665 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
666 __ffmt->code = ffmt->code;
667 break;
668 }
669 }
670
671 /*
672 * isp_subdev_get_format - Retrieve the video format on a pad
673 * @sd : ISP V4L2 subdevice
674 * @fh : V4L2 subdev file handle
675 * @pad: Pad number
676 * @fmt: Format
677 *
678 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
679 * to the format type.
680 */
isp_subdev_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)681 static int isp_subdev_get_format(struct v4l2_subdev *sd,
682 struct v4l2_subdev_pad_config *cfg,
683 struct v4l2_subdev_format *fmt)
684 {
685 fmt->format = *atomisp_subdev_get_ffmt(sd, cfg, fmt->which, fmt->pad);
686
687 return 0;
688 }
689
690 /*
691 * isp_subdev_set_format - Set the video format on a pad
692 * @sd : ISP subdev V4L2 subdevice
693 * @fh : V4L2 subdev file handle
694 * @pad: Pad number
695 * @fmt: Format
696 *
697 * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
698 * to the format type.
699 */
isp_subdev_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)700 static int isp_subdev_set_format(struct v4l2_subdev *sd,
701 struct v4l2_subdev_pad_config *cfg,
702 struct v4l2_subdev_format *fmt)
703 {
704 atomisp_subdev_set_ffmt(sd, cfg, fmt->which, fmt->pad, &fmt->format);
705
706 return 0;
707 }
708
709 /* V4L2 subdev core operations */
710 static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
711 .ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power,
712 .subscribe_event = isp_subdev_subscribe_event,
713 .unsubscribe_event = isp_subdev_unsubscribe_event,
714 };
715
716 /* V4L2 subdev pad operations */
717 static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
718 .enum_mbus_code = isp_subdev_enum_mbus_code,
719 .get_fmt = isp_subdev_get_format,
720 .set_fmt = isp_subdev_set_format,
721 .get_selection = isp_subdev_get_selection,
722 .set_selection = isp_subdev_set_selection,
723 .link_validate = v4l2_subdev_link_validate_default,
724 };
725
726 /* V4L2 subdev operations */
727 static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
728 .core = &isp_subdev_v4l2_core_ops,
729 .pad = &isp_subdev_v4l2_pad_ops,
730 };
731
isp_subdev_init_params(struct atomisp_sub_device * asd)732 static void isp_subdev_init_params(struct atomisp_sub_device *asd)
733 {
734 unsigned int i;
735
736 /* parameters initialization */
737 INIT_LIST_HEAD(&asd->s3a_stats);
738 INIT_LIST_HEAD(&asd->s3a_stats_in_css);
739 INIT_LIST_HEAD(&asd->s3a_stats_ready);
740 INIT_LIST_HEAD(&asd->dis_stats);
741 INIT_LIST_HEAD(&asd->dis_stats_in_css);
742 spin_lock_init(&asd->dis_stats_lock);
743 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
744 INIT_LIST_HEAD(&asd->metadata[i]);
745 INIT_LIST_HEAD(&asd->metadata_in_css[i]);
746 INIT_LIST_HEAD(&asd->metadata_ready[i]);
747 }
748 }
749
750 /*
751 * isp_subdev_link_setup - Setup isp subdev connections
752 * @entity: ispsubdev media entity
753 * @local: Pad at the local end of the link
754 * @remote: Pad at the remote end of the link
755 * @flags: Link flags
756 *
757 * return -EINVAL or zero on success
758 */
isp_subdev_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)759 static int isp_subdev_link_setup(struct media_entity *entity,
760 const struct media_pad *local,
761 const struct media_pad *remote, u32 flags)
762 {
763 struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
764 struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
765 struct atomisp_device *isp = isp_sd->isp;
766 unsigned int i;
767
768 switch (local->index | is_media_entity_v4l2_subdev(remote->entity)) {
769 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
770 /* Read from the sensor CSI2-ports. */
771 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
772 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
773 break;
774 }
775
776 if (isp_sd->input != ATOMISP_SUBDEV_INPUT_NONE)
777 return -EBUSY;
778
779 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
780 if (remote->entity != &isp->csi2_port[i].subdev.entity)
781 continue;
782
783 isp_sd->input = ATOMISP_SUBDEV_INPUT_CSI2_PORT1 + i;
784 return 0;
785 }
786
787 return -EINVAL;
788
789 case ATOMISP_SUBDEV_PAD_SINK | MEDIA_ENT_F_OLD_BASE:
790 /* read from memory */
791 if (flags & MEDIA_LNK_FL_ENABLED) {
792 if (isp_sd->input >= ATOMISP_SUBDEV_INPUT_CSI2_PORT1 &&
793 isp_sd->input < (ATOMISP_SUBDEV_INPUT_CSI2_PORT1
794 + ATOMISP_CAMERA_NR_PORTS))
795 return -EBUSY;
796 isp_sd->input = ATOMISP_SUBDEV_INPUT_MEMORY;
797 } else {
798 if (isp_sd->input == ATOMISP_SUBDEV_INPUT_MEMORY)
799 isp_sd->input = ATOMISP_SUBDEV_INPUT_NONE;
800 }
801 break;
802
803 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW | MEDIA_ENT_F_OLD_BASE:
804 /* always write to memory */
805 break;
806
807 case ATOMISP_SUBDEV_PAD_SOURCE_VF | MEDIA_ENT_F_OLD_BASE:
808 /* always write to memory */
809 break;
810
811 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE | MEDIA_ENT_F_OLD_BASE:
812 /* always write to memory */
813 break;
814
815 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO | MEDIA_ENT_F_OLD_BASE:
816 /* always write to memory */
817 break;
818
819 default:
820 return -EINVAL;
821 }
822
823 return 0;
824 }
825
826 /* media operations */
827 static const struct media_entity_operations isp_subdev_media_ops = {
828 .link_setup = isp_subdev_link_setup,
829 .link_validate = v4l2_subdev_link_validate,
830 /* .set_power = v4l2_subdev_set_power, */
831 };
832
__atomisp_update_run_mode(struct atomisp_sub_device * asd)833 static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
834 {
835 struct atomisp_device *isp = asd->isp;
836 struct v4l2_ctrl *ctrl = asd->run_mode;
837 struct v4l2_ctrl *c;
838 s32 mode;
839
840 if (ctrl->val != ATOMISP_RUN_MODE_VIDEO &&
841 asd->continuous_mode->val)
842 mode = ATOMISP_RUN_MODE_PREVIEW;
843 else
844 mode = ctrl->val;
845
846 c = v4l2_ctrl_find(
847 isp->inputs[asd->input_curr].camera->ctrl_handler,
848 V4L2_CID_RUN_MODE);
849
850 if (c)
851 return v4l2_ctrl_s_ctrl(c, mode);
852
853 return 0;
854 }
855
atomisp_update_run_mode(struct atomisp_sub_device * asd)856 int atomisp_update_run_mode(struct atomisp_sub_device *asd)
857 {
858 int rval;
859
860 mutex_lock(asd->ctrl_handler.lock);
861 rval = __atomisp_update_run_mode(asd);
862 mutex_unlock(asd->ctrl_handler.lock);
863
864 return rval;
865 }
866
s_ctrl(struct v4l2_ctrl * ctrl)867 static int s_ctrl(struct v4l2_ctrl *ctrl)
868 {
869 struct atomisp_sub_device *asd = container_of(
870 ctrl->handler, struct atomisp_sub_device, ctrl_handler);
871
872 switch (ctrl->id) {
873 case V4L2_CID_RUN_MODE:
874 return __atomisp_update_run_mode(asd);
875 case V4L2_CID_DEPTH_MODE:
876 if (asd->streaming != ATOMISP_DEVICE_STREAMING_DISABLED) {
877 dev_err(asd->isp->dev,
878 "ISP is streaming, it is not supported to change the depth mode\n");
879 return -EINVAL;
880 }
881 break;
882 }
883
884 return 0;
885 }
886
887 static const struct v4l2_ctrl_ops ctrl_ops = {
888 .s_ctrl = &s_ctrl,
889 };
890
891 static const struct v4l2_ctrl_config ctrl_fmt_auto = {
892 .ops = &ctrl_ops,
893 .id = V4L2_CID_FMT_AUTO,
894 .name = "Automatic format guessing",
895 .type = V4L2_CTRL_TYPE_BOOLEAN,
896 .min = 0,
897 .max = 1,
898 .step = 1,
899 .def = 1,
900 };
901
902 static const char *const ctrl_run_mode_menu[] = {
903 NULL,
904 "Video",
905 "Still capture",
906 "Continuous capture",
907 "Preview",
908 };
909
910 static const struct v4l2_ctrl_config ctrl_run_mode = {
911 .ops = &ctrl_ops,
912 .id = V4L2_CID_RUN_MODE,
913 .name = "Atomisp run mode",
914 .type = V4L2_CTRL_TYPE_MENU,
915 .min = 1,
916 .def = 1,
917 .max = 4,
918 .qmenu = ctrl_run_mode_menu,
919 };
920
921 static const char *const ctrl_vfpp_mode_menu[] = {
922 "Enable", /* vfpp always enabled */
923 "Disable to scaler mode", /* CSS into video mode and disable */
924 "Disable to low latency mode", /* CSS into still mode and disable */
925 };
926
927 static const struct v4l2_ctrl_config ctrl_vfpp = {
928 .id = V4L2_CID_VFPP,
929 .name = "Atomisp vf postprocess",
930 .type = V4L2_CTRL_TYPE_MENU,
931 .min = 0,
932 .def = 0,
933 .max = 2,
934 .qmenu = ctrl_vfpp_mode_menu,
935 };
936
937 /*
938 * Control for ISP continuous mode
939 *
940 * When enabled, capture processing is possible without
941 * stopping the preview pipeline. When disabled, ISP needs
942 * to be restarted between preview and capture.
943 */
944 static const struct v4l2_ctrl_config ctrl_continuous_mode = {
945 .ops = &ctrl_ops,
946 .id = V4L2_CID_ATOMISP_CONTINUOUS_MODE,
947 .type = V4L2_CTRL_TYPE_BOOLEAN,
948 .name = "Continuous mode",
949 .min = 0,
950 .max = 1,
951 .step = 1,
952 .def = 0,
953 };
954
955 /*
956 * Control for continuous mode raw buffer size
957 *
958 * The size of the RAW ringbuffer sets limit on how much
959 * back in time application can go when requesting capture
960 * frames to be rendered, and how many frames can be rendered
961 * in a burst at full sensor rate.
962 *
963 * Note: this setting has a big impact on memory consumption of
964 * the CSS subsystem.
965 */
966 static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
967 .ops = &ctrl_ops,
968 .id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
969 .type = V4L2_CTRL_TYPE_INTEGER,
970 .name = "Continuous raw ringbuffer size",
971 .min = 1,
972 .max = 100, /* depends on CSS version, runtime checked */
973 .step = 1,
974 .def = 3,
975 };
976
977 /*
978 * Control for enabling continuous viewfinder
979 *
980 * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ),
981 * preview pipeline continues concurrently with capture
982 * processing. When disabled, and continuous mode is used,
983 * preview is paused while captures are processed, but
984 * full pipeline restart is not needed.
985 *
986 * By setting this to disabled, capture processing is
987 * essentially given priority over preview, and the effective
988 * capture output rate may be higher than with continuous
989 * viewfinder enabled.
990 */
991 static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
992 .id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
993 .type = V4L2_CTRL_TYPE_BOOLEAN,
994 .name = "Continuous viewfinder",
995 .min = 0,
996 .max = 1,
997 .step = 1,
998 .def = 0,
999 };
1000
1001 /*
1002 * Control for enabling Lock&Unlock Raw Buffer mechanism
1003 *
1004 * When enabled, Raw Buffer can be locked and unlocked.
1005 * Application can hold the exp_id of Raw Buffer
1006 * and unlock it when no longer needed.
1007 * Note: Make sure set this configuration before creating stream.
1008 */
1009 static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
1010 .id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
1011 .type = V4L2_CTRL_TYPE_BOOLEAN,
1012 .name = "Lock Unlock Raw Buffer",
1013 .min = 0,
1014 .max = 1,
1015 .step = 1,
1016 .def = 0,
1017 };
1018
1019 /*
1020 * Control to disable digital zoom of the whole stream
1021 *
1022 * When it is true, pipe configuration enable_dz will be set to false.
1023 * This can help get a better performance by disabling pp binary.
1024 *
1025 * Note: Make sure set this configuration before creating stream.
1026 */
1027 static const struct v4l2_ctrl_config ctrl_disable_dz = {
1028 .id = V4L2_CID_DISABLE_DZ,
1029 .type = V4L2_CTRL_TYPE_BOOLEAN,
1030 .name = "Disable digital zoom",
1031 .min = 0,
1032 .max = 1,
1033 .step = 1,
1034 .def = 0,
1035 };
1036
1037 /*
1038 * Control for ISP depth mode
1039 *
1040 * When enabled, that means ISP will deal with dual streams and sensors will be
1041 * in slave/master mode.
1042 * slave sensor will have no output until master sensor is streamed on.
1043 */
1044 static const struct v4l2_ctrl_config ctrl_depth_mode = {
1045 .ops = &ctrl_ops,
1046 .id = V4L2_CID_DEPTH_MODE,
1047 .type = V4L2_CTRL_TYPE_BOOLEAN,
1048 .name = "Depth mode",
1049 .min = 0,
1050 .max = 1,
1051 .step = 1,
1052 .def = 0,
1053 };
1054
1055 /*
1056 * Control for selectting ISP version
1057 *
1058 * When enabled, that means ISP version will be used ISP2.7. when disable, the
1059 * isp will default to use ISP2.2.
1060 * Note: Make sure set this configuration before creating stream.
1061 */
1062 static const struct v4l2_ctrl_config ctrl_select_isp_version = {
1063 .ops = &ctrl_ops,
1064 .id = V4L2_CID_ATOMISP_SELECT_ISP_VERSION,
1065 .type = V4L2_CTRL_TYPE_BOOLEAN,
1066 .name = "Select Isp version",
1067 .min = 0,
1068 .max = 1,
1069 .step = 1,
1070 .def = 0,
1071 };
1072
1073 #if 0 /* #ifdef CONFIG_ION */
1074 /*
1075 * Control for ISP ion device fd
1076 *
1077 * userspace will open ion device and pass the fd to kernel.
1078 * this fd will be used to map shared fd to buffer.
1079 */
1080 /* V4L2_CID_ATOMISP_ION_DEVICE_FD is not defined */
1081 static const struct v4l2_ctrl_config ctrl_ion_dev_fd = {
1082 .ops = &ctrl_ops,
1083 .id = V4L2_CID_ATOMISP_ION_DEVICE_FD,
1084 .type = V4L2_CTRL_TYPE_INTEGER,
1085 .name = "Ion Device Fd",
1086 .min = -1,
1087 .max = 1024,
1088 .step = 1,
1089 .def = ION_FD_UNSET
1090 };
1091 #endif
1092
atomisp_init_subdev_pipe(struct atomisp_sub_device * asd,struct atomisp_video_pipe * pipe,enum v4l2_buf_type buf_type)1093 static void atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
1094 struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
1095 {
1096 pipe->type = buf_type;
1097 pipe->asd = asd;
1098 pipe->isp = asd->isp;
1099 spin_lock_init(&pipe->irq_lock);
1100 INIT_LIST_HEAD(&pipe->activeq);
1101 INIT_LIST_HEAD(&pipe->activeq_out);
1102 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
1103 INIT_LIST_HEAD(&pipe->per_frame_params);
1104 memset(pipe->frame_request_config_id,
1105 0, VIDEO_MAX_FRAME * sizeof(unsigned int));
1106 memset(pipe->frame_params,
1107 0, VIDEO_MAX_FRAME *
1108 sizeof(struct atomisp_css_params_with_list *));
1109 }
1110
atomisp_init_acc_pipe(struct atomisp_sub_device * asd,struct atomisp_acc_pipe * pipe)1111 static void atomisp_init_acc_pipe(struct atomisp_sub_device *asd,
1112 struct atomisp_acc_pipe *pipe)
1113 {
1114 pipe->asd = asd;
1115 pipe->isp = asd->isp;
1116 INIT_LIST_HEAD(&asd->acc.fw);
1117 INIT_LIST_HEAD(&asd->acc.memory_maps);
1118 ida_init(&asd->acc.ida);
1119 }
1120
1121 /*
1122 * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
1123 * @asd: ISP CCDC module
1124 *
1125 * Return 0 on success and a negative error code on failure.
1126 */
isp_subdev_init_entities(struct atomisp_sub_device * asd)1127 static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
1128 {
1129 struct v4l2_subdev *sd = &asd->subdev;
1130 struct media_pad *pads = asd->pads;
1131 struct media_entity *me = &sd->entity;
1132 int ret;
1133
1134 asd->input = ATOMISP_SUBDEV_INPUT_NONE;
1135
1136 v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
1137 sprintf(sd->name, "ATOMISP_SUBDEV_%d", asd->index);
1138 v4l2_set_subdevdata(sd, asd);
1139 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1140
1141 pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1142 pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
1143 pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
1144 pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
1145 pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
1146
1147 asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
1148 MEDIA_BUS_FMT_SBGGR10_1X10;
1149 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
1150 MEDIA_BUS_FMT_SBGGR10_1X10;
1151 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
1152 MEDIA_BUS_FMT_SBGGR10_1X10;
1153 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
1154 MEDIA_BUS_FMT_SBGGR10_1X10;
1155 asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
1156 MEDIA_BUS_FMT_SBGGR10_1X10;
1157
1158 me->ops = &isp_subdev_media_ops;
1159 me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
1160 ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
1161 if (ret < 0)
1162 return ret;
1163
1164 atomisp_init_subdev_pipe(asd, &asd->video_in,
1165 V4L2_BUF_TYPE_VIDEO_OUTPUT);
1166
1167 atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
1168 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1169
1170 atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
1171 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1172
1173 atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
1174 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1175
1176 atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
1177 V4L2_BUF_TYPE_VIDEO_CAPTURE);
1178
1179 atomisp_init_acc_pipe(asd, &asd->video_acc);
1180
1181 ret = atomisp_video_init(&asd->video_in, "MEMORY",
1182 ATOMISP_RUN_MODE_SDV);
1183 if (ret < 0)
1184 return ret;
1185
1186 ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE",
1187 ATOMISP_RUN_MODE_STILL_CAPTURE);
1188 if (ret < 0)
1189 return ret;
1190
1191 ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER",
1192 ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE);
1193 if (ret < 0)
1194 return ret;
1195
1196 ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW",
1197 ATOMISP_RUN_MODE_PREVIEW);
1198 if (ret < 0)
1199 return ret;
1200
1201 ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO",
1202 ATOMISP_RUN_MODE_VIDEO);
1203 if (ret < 0)
1204 return ret;
1205
1206 atomisp_acc_init(&asd->video_acc, "ACC");
1207
1208 ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
1209 if (ret)
1210 return ret;
1211
1212 asd->fmt_auto = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1213 &ctrl_fmt_auto, NULL);
1214 asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1215 &ctrl_run_mode, NULL);
1216 asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1217 &ctrl_vfpp, NULL);
1218 asd->continuous_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1219 &ctrl_continuous_mode, NULL);
1220 asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1221 &ctrl_continuous_viewfinder,
1222 NULL);
1223 asd->continuous_raw_buffer_size =
1224 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1225 &ctrl_continuous_raw_buffer_size,
1226 NULL);
1227
1228 asd->enable_raw_buffer_lock =
1229 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1230 &ctrl_enable_raw_buffer_lock,
1231 NULL);
1232 asd->depth_mode =
1233 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1234 &ctrl_depth_mode,
1235 NULL);
1236 asd->disable_dz =
1237 v4l2_ctrl_new_custom(&asd->ctrl_handler,
1238 &ctrl_disable_dz,
1239 NULL);
1240 if (IS_ISP2401) {
1241 asd->select_isp_version = v4l2_ctrl_new_custom(&asd->ctrl_handler,
1242 &ctrl_select_isp_version,
1243 NULL);
1244 }
1245
1246 /* Make controls visible on subdev as well. */
1247 asd->subdev.ctrl_handler = &asd->ctrl_handler;
1248 spin_lock_init(&asd->raw_buffer_bitmap_lock);
1249 return asd->ctrl_handler.error;
1250 }
1251
atomisp_create_pads_links(struct atomisp_device * isp)1252 int atomisp_create_pads_links(struct atomisp_device *isp)
1253 {
1254 struct atomisp_sub_device *asd;
1255 int i, j, ret = 0;
1256
1257 isp->num_of_streams = 2;
1258 for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
1259 for (j = 0; j < isp->num_of_streams; j++) {
1260 ret =
1261 media_create_pad_link(&isp->csi2_port[i].subdev.
1262 entity, CSI2_PAD_SOURCE,
1263 &isp->asd[j].subdev.entity,
1264 ATOMISP_SUBDEV_PAD_SINK, 0);
1265 if (ret < 0)
1266 return ret;
1267 }
1268 }
1269 for (i = 0; i < isp->input_cnt - 2; i++) {
1270 ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
1271 &isp->csi2_port[isp->inputs[i].
1272 port].subdev.entity,
1273 CSI2_PAD_SINK,
1274 MEDIA_LNK_FL_ENABLED |
1275 MEDIA_LNK_FL_IMMUTABLE);
1276 if (ret < 0)
1277 return ret;
1278 }
1279 for (i = 0; i < isp->num_of_streams; i++) {
1280 asd = &isp->asd[i];
1281 ret = media_create_pad_link(&asd->subdev.entity,
1282 ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
1283 &asd->video_out_preview.vdev.entity,
1284 0, 0);
1285 if (ret < 0)
1286 return ret;
1287 ret = media_create_pad_link(&asd->subdev.entity,
1288 ATOMISP_SUBDEV_PAD_SOURCE_VF,
1289 &asd->video_out_vf.vdev.entity, 0,
1290 0);
1291 if (ret < 0)
1292 return ret;
1293 ret = media_create_pad_link(&asd->subdev.entity,
1294 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
1295 &asd->video_out_capture.vdev.entity,
1296 0, 0);
1297 if (ret < 0)
1298 return ret;
1299 ret = media_create_pad_link(&asd->subdev.entity,
1300 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
1301 &asd->video_out_video_capture.vdev.
1302 entity, 0, 0);
1303 if (ret < 0)
1304 return ret;
1305 /*
1306 * file input only supported on subdev0
1307 * so do not create pad link for subdevs other then subdev0
1308 */
1309 if (asd->index)
1310 return 0;
1311 ret = media_create_pad_link(&asd->video_in.vdev.entity,
1312 0, &asd->subdev.entity,
1313 ATOMISP_SUBDEV_PAD_SINK, 0);
1314 if (ret < 0)
1315 return ret;
1316 }
1317 return 0;
1318 }
1319
atomisp_subdev_cleanup_entities(struct atomisp_sub_device * asd)1320 static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
1321 {
1322 v4l2_ctrl_handler_free(&asd->ctrl_handler);
1323
1324 media_entity_cleanup(&asd->subdev.entity);
1325 }
1326
atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device * asd)1327 void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
1328 {
1329 struct v4l2_fh *fh, *fh_tmp;
1330 struct v4l2_event event;
1331 unsigned int i, pending_event;
1332
1333 list_for_each_entry_safe(fh, fh_tmp,
1334 &asd->subdev.devnode->fh_list, list) {
1335 pending_event = v4l2_event_pending(fh);
1336 for (i = 0; i < pending_event; i++)
1337 v4l2_event_dequeue(fh, &event, 1);
1338 }
1339 }
1340
atomisp_subdev_unregister_entities(struct atomisp_sub_device * asd)1341 void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
1342 {
1343 atomisp_subdev_cleanup_entities(asd);
1344 v4l2_device_unregister_subdev(&asd->subdev);
1345 atomisp_video_unregister(&asd->video_in);
1346 atomisp_video_unregister(&asd->video_out_preview);
1347 atomisp_video_unregister(&asd->video_out_vf);
1348 atomisp_video_unregister(&asd->video_out_capture);
1349 atomisp_video_unregister(&asd->video_out_video_capture);
1350 atomisp_acc_unregister(&asd->video_acc);
1351 }
1352
atomisp_subdev_register_entities(struct atomisp_sub_device * asd,struct v4l2_device * vdev)1353 int atomisp_subdev_register_entities(struct atomisp_sub_device *asd,
1354 struct v4l2_device *vdev)
1355 {
1356 int ret;
1357 u32 device_caps;
1358
1359 /*
1360 * FIXME: check if all device caps are properly initialized.
1361 * Should any of those use V4L2_CAP_META_OUTPUT? Probably yes.
1362 */
1363
1364 device_caps = V4L2_CAP_VIDEO_CAPTURE |
1365 V4L2_CAP_STREAMING;
1366
1367 /* Register the subdev and video node. */
1368
1369 ret = v4l2_device_register_subdev(vdev, &asd->subdev);
1370 if (ret < 0)
1371 goto error;
1372
1373 asd->video_out_capture.vdev.v4l2_dev = vdev;
1374 asd->video_out_capture.vdev.device_caps = device_caps |
1375 V4L2_CAP_VIDEO_OUTPUT;
1376 ret = video_register_device(&asd->video_out_capture.vdev,
1377 VFL_TYPE_VIDEO, -1);
1378 if (ret < 0)
1379 goto error;
1380
1381 asd->video_out_vf.vdev.v4l2_dev = vdev;
1382 asd->video_out_vf.vdev.device_caps = device_caps |
1383 V4L2_CAP_VIDEO_OUTPUT;
1384 ret = video_register_device(&asd->video_out_vf.vdev,
1385 VFL_TYPE_VIDEO, -1);
1386 if (ret < 0)
1387 goto error;
1388 asd->video_out_preview.vdev.v4l2_dev = vdev;
1389 asd->video_out_preview.vdev.device_caps = device_caps |
1390 V4L2_CAP_VIDEO_OUTPUT;
1391 ret = video_register_device(&asd->video_out_preview.vdev,
1392 VFL_TYPE_VIDEO, -1);
1393 if (ret < 0)
1394 goto error;
1395 asd->video_out_video_capture.vdev.v4l2_dev = vdev;
1396 asd->video_out_video_capture.vdev.device_caps = device_caps |
1397 V4L2_CAP_VIDEO_OUTPUT;
1398 ret = video_register_device(&asd->video_out_video_capture.vdev,
1399 VFL_TYPE_VIDEO, -1);
1400 if (ret < 0)
1401 goto error;
1402 asd->video_acc.vdev.v4l2_dev = vdev;
1403 asd->video_acc.vdev.device_caps = device_caps |
1404 V4L2_CAP_VIDEO_OUTPUT;
1405 ret = video_register_device(&asd->video_acc.vdev,
1406 VFL_TYPE_VIDEO, -1);
1407 if (ret < 0)
1408 goto error;
1409
1410 /*
1411 * file input only supported on subdev0
1412 * so do not create video node for subdevs other then subdev0
1413 */
1414 if (asd->index)
1415 return 0;
1416
1417 asd->video_in.vdev.v4l2_dev = vdev;
1418 asd->video_in.vdev.device_caps = device_caps |
1419 V4L2_CAP_VIDEO_CAPTURE;
1420 ret = video_register_device(&asd->video_in.vdev,
1421 VFL_TYPE_VIDEO, -1);
1422 if (ret < 0)
1423 goto error;
1424
1425 return 0;
1426
1427 error:
1428 atomisp_subdev_unregister_entities(asd);
1429 return ret;
1430 }
1431
1432 /*
1433 * atomisp_subdev_init - ISP Subdevice initialization.
1434 * @dev: Device pointer specific to the ATOM ISP.
1435 *
1436 * TODO: Get the initialisation values from platform data.
1437 *
1438 * Return 0 on success or a negative error code otherwise.
1439 */
atomisp_subdev_init(struct atomisp_device * isp)1440 int atomisp_subdev_init(struct atomisp_device *isp)
1441 {
1442 struct atomisp_sub_device *asd;
1443 int i, ret = 0;
1444
1445 /*
1446 * CSS2.0 running ISP2400 support
1447 * multiple streams
1448 */
1449 isp->num_of_streams = 2;
1450 isp->asd = devm_kzalloc(isp->dev, sizeof(struct atomisp_sub_device) *
1451 isp->num_of_streams, GFP_KERNEL);
1452 if (!isp->asd)
1453 return -ENOMEM;
1454 for (i = 0; i < isp->num_of_streams; i++) {
1455 asd = &isp->asd[i];
1456 spin_lock_init(&asd->lock);
1457 asd->isp = isp;
1458 isp_subdev_init_params(asd);
1459 asd->index = i;
1460 ret = isp_subdev_init_entities(asd);
1461 if (ret < 0) {
1462 atomisp_subdev_cleanup_entities(asd);
1463 break;
1464 }
1465 }
1466
1467 return ret;
1468 }
1469