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