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