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 <media/videobuf2-vmalloc.h>
29 #include "atomisp_cmd.h"
30 #include "atomisp_common.h"
31 #include "atomisp_compat.h"
32 #include "atomisp_fops.h"
33 #include "atomisp_internal.h"
34 
35 const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
36 	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR },
37 	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GBRG },
38 	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GRBG },
39 	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_RGGB },
40 	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_BGGR },
41 	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GBRG },
42 	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GRBG },
43 	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_RGGB },
44 	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_BGGR },
45 	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GBRG },
46 	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GRBG },
47 	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_RGGB },
48 	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
49 	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
50 #if 0 // disabled due to clang warnings
51 	{ MEDIA_BUS_FMT_JPEG_1X8, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
52 	{ V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, IA_CSS_FRAME_FORMAT_NV12, 0 },
53 	{ V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, IA_CSS_FRAME_FORMAT_NV21, 0 },
54 #endif
55 	{ V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0 },
56 #if 0
57 	{ V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
58 #endif
59 	/* no valid V4L2 MBUS code for metadata format, so leave it 0. */
60 	{ 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 },
61 	{}
62 };
63 
64 static const struct {
65 	u32 code;
66 	u32 compressed;
67 } compressed_codes[] = {
68 	{ MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
69 	{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
70 	{ MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
71 	{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
72 };
73 
74 u32 atomisp_subdev_uncompressed_code(u32 code)
75 {
76 	unsigned int i;
77 
78 	for (i = 0; i < ARRAY_SIZE(compressed_codes); i++)
79 		if (code == compressed_codes[i].compressed)
80 			return compressed_codes[i].code;
81 
82 	return code;
83 }
84 
85 bool atomisp_subdev_is_compressed(u32 code)
86 {
87 	int i;
88 
89 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
90 		if (code == atomisp_in_fmt_conv[i].code)
91 			return atomisp_in_fmt_conv[i].bpp !=
92 			       atomisp_in_fmt_conv[i].depth;
93 
94 	return false;
95 }
96 
97 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
98 {
99 	int i;
100 
101 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
102 		if (code == atomisp_in_fmt_conv[i].code)
103 			return atomisp_in_fmt_conv + i;
104 
105 	return NULL;
106 }
107 
108 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
109     enum atomisp_input_format atomisp_in_fmt)
110 {
111 	int i;
112 
113 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
114 		if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt)
115 			return atomisp_in_fmt_conv + i;
116 
117 	return NULL;
118 }
119 
120 bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd,
121 				      unsigned int source_pad)
122 {
123 	struct v4l2_mbus_framefmt *sink, *src;
124 
125 	sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
126 				       V4L2_SUBDEV_FORMAT_ACTIVE,
127 				       ATOMISP_SUBDEV_PAD_SINK);
128 	src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
129 				      V4L2_SUBDEV_FORMAT_ACTIVE, source_pad);
130 
131 	return atomisp_is_mbuscode_raw(sink->code)
132 	       && !atomisp_is_mbuscode_raw(src->code);
133 }
134 
135 uint16_t atomisp_subdev_source_pad(struct video_device *vdev)
136 {
137 	struct media_link *link;
138 	u16 ret = 0;
139 
140 	list_for_each_entry(link, &vdev->entity.links, list) {
141 		if (link->source) {
142 			ret = link->source->index;
143 			break;
144 		}
145 	}
146 	return ret;
147 }
148 
149 /*
150  * V4L2 subdev operations
151  */
152 
153 /*
154  * isp_subdev_ioctl - CCDC module private ioctl's
155  * @sd: ISP V4L2 subdevice
156  * @cmd: ioctl command
157  * @arg: ioctl argument
158  *
159  * Return 0 on success or a negative error code otherwise.
160  */
161 static long isp_subdev_ioctl(struct v4l2_subdev *sd,
162 			     unsigned int cmd, void *arg)
163 {
164 	return 0;
165 }
166 
167 /*
168  * isp_subdev_set_power - Power on/off the CCDC module
169  * @sd: ISP V4L2 subdevice
170  * @on: power on/off
171  *
172  * Return 0 on success or a negative error code otherwise.
173  */
174 static int isp_subdev_set_power(struct v4l2_subdev *sd, int on)
175 {
176 	return 0;
177 }
178 
179 static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
180 				      struct v4l2_fh *fh,
181 				      struct v4l2_event_subscription *sub)
182 {
183 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
184 	struct atomisp_device *isp = isp_sd->isp;
185 
186 	if (sub->type != V4L2_EVENT_FRAME_SYNC &&
187 	    sub->type != V4L2_EVENT_FRAME_END &&
188 	    sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY &&
189 	    sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
190 	    sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
191 	    sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
192 	    sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
193 		return -EINVAL;
194 
195 	if (sub->type == V4L2_EVENT_FRAME_SYNC &&
196 	    !atomisp_css_valid_sof(isp))
197 		return -EINVAL;
198 
199 	return v4l2_event_subscribe(fh, sub, 16, NULL);
200 }
201 
202 static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
203 					struct v4l2_fh *fh,
204 					struct v4l2_event_subscription *sub)
205 {
206 	return v4l2_event_unsubscribe(fh, sub);
207 }
208 
209 /*
210  * isp_subdev_enum_mbus_code - Handle pixel format enumeration
211  * @sd: pointer to v4l2 subdev structure
212  * @fh : V4L2 subdev file handle
213  * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
214  * return -EINVAL or zero on success
215  */
216 static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
217 				     struct v4l2_subdev_state *sd_state,
218 				     struct v4l2_subdev_mbus_code_enum *code)
219 {
220 	if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
221 		return -EINVAL;
222 
223 	code->code = atomisp_in_fmt_conv[code->index].code;
224 
225 	return 0;
226 }
227 
228 static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
229 				    uint32_t target)
230 {
231 	switch (pad) {
232 	case ATOMISP_SUBDEV_PAD_SINK:
233 		switch (target) {
234 		case V4L2_SEL_TGT_CROP:
235 			return 0;
236 		}
237 		break;
238 	default:
239 		switch (target) {
240 		case V4L2_SEL_TGT_COMPOSE:
241 			return 0;
242 		}
243 		break;
244 	}
245 
246 	return -EINVAL;
247 }
248 
249 struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
250 	struct v4l2_subdev_state *sd_state,
251 	u32 which, uint32_t pad,
252 	uint32_t target)
253 {
254 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
255 
256 	if (which == V4L2_SUBDEV_FORMAT_TRY) {
257 		switch (target) {
258 		case V4L2_SEL_TGT_CROP:
259 			return v4l2_subdev_get_try_crop(sd, sd_state, pad);
260 		case V4L2_SEL_TGT_COMPOSE:
261 			return v4l2_subdev_get_try_compose(sd, sd_state, pad);
262 		}
263 	}
264 
265 	switch (target) {
266 	case V4L2_SEL_TGT_CROP:
267 		return &isp_sd->fmt[pad].crop;
268 	case V4L2_SEL_TGT_COMPOSE:
269 		return &isp_sd->fmt[pad].compose;
270 	}
271 
272 	return NULL;
273 }
274 
275 struct v4l2_mbus_framefmt
276 *atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
277 			 struct v4l2_subdev_state *sd_state, uint32_t which,
278 			 uint32_t pad)
279 {
280 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
281 
282 	if (which == V4L2_SUBDEV_FORMAT_TRY)
283 		return v4l2_subdev_get_try_format(sd, sd_state, pad);
284 
285 	return &isp_sd->fmt[pad].fmt;
286 }
287 
288 static void isp_get_fmt_rect(struct v4l2_subdev *sd,
289 			     struct v4l2_subdev_state *sd_state,
290 			     uint32_t which,
291 			     struct v4l2_mbus_framefmt **ffmt,
292 			     struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
293 			     struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
294 {
295 	unsigned int i;
296 
297 	for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
298 		ffmt[i] = atomisp_subdev_get_ffmt(sd, sd_state, which, i);
299 		crop[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
300 						  V4L2_SEL_TGT_CROP);
301 		comp[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
302 						  V4L2_SEL_TGT_COMPOSE);
303 	}
304 }
305 
306 static void isp_subdev_propagate(struct v4l2_subdev *sd,
307 				 struct v4l2_subdev_state *sd_state,
308 				 u32 which, uint32_t pad, uint32_t target,
309 				 uint32_t flags)
310 {
311 	struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
312 	struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
313 		       *comp[ATOMISP_SUBDEV_PADS_NUM];
314 
315 	if (flags & V4L2_SEL_FLAG_KEEP_CONFIG)
316 		return;
317 
318 	isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
319 
320 	switch (pad) {
321 	case ATOMISP_SUBDEV_PAD_SINK: {
322 		struct v4l2_rect r = {0};
323 
324 		/* Only crop target supported on sink pad. */
325 		r.width = ffmt[pad]->width;
326 		r.height = ffmt[pad]->height;
327 
328 		atomisp_subdev_set_selection(sd, sd_state, which, pad,
329 					     target, flags, &r);
330 		break;
331 	}
332 	}
333 }
334 
335 static int isp_subdev_get_selection(struct v4l2_subdev *sd,
336 				    struct v4l2_subdev_state *sd_state,
337 				    struct v4l2_subdev_selection *sel)
338 {
339 	struct v4l2_rect *rec;
340 	int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
341 
342 	if (rval)
343 		return rval;
344 
345 	rec = atomisp_subdev_get_rect(sd, sd_state, sel->which, sel->pad,
346 				      sel->target);
347 	if (!rec)
348 		return -EINVAL;
349 
350 	sel->r = *rec;
351 	return 0;
352 }
353 
354 static const char *atomisp_pad_str(unsigned int pad)
355 {
356 	static const char *const pad_str[] = {
357 		"ATOMISP_SUBDEV_PAD_SINK",
358 		"ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE",
359 		"ATOMISP_SUBDEV_PAD_SOURCE_VF",
360 		"ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW",
361 		"ATOMISP_SUBDEV_PAD_SOURCE_VIDEO",
362 	};
363 
364 	if (pad >= ARRAY_SIZE(pad_str))
365 		return "ATOMISP_INVALID_PAD";
366 	return pad_str[pad];
367 }
368 
369 int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
370 				 struct v4l2_subdev_state *sd_state,
371 				 u32 which, uint32_t pad, uint32_t target,
372 				 u32 flags, struct v4l2_rect *r)
373 {
374 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
375 	struct atomisp_device *isp = isp_sd->isp;
376 	struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
377 	struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
378 		       *comp[ATOMISP_SUBDEV_PADS_NUM];
379 	unsigned int i;
380 	unsigned int padding_w = pad_w;
381 	unsigned int padding_h = pad_h;
382 
383 	isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
384 
385 	dev_dbg(isp->dev,
386 		"sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
387 		atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP
388 		? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
389 		r->left, r->top, r->width, r->height,
390 		which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
391 		: "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
392 
393 	r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
394 	r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
395 
396 	switch (pad) {
397 	case ATOMISP_SUBDEV_PAD_SINK: {
398 		/* Only crop target supported on sink pad. */
399 		unsigned int dvs_w, dvs_h;
400 
401 		crop[pad]->width = ffmt[pad]->width;
402 		crop[pad]->height = ffmt[pad]->height;
403 
404 		/* Workaround for BYT 1080p perfectshot since the maxinum resolution of
405 		 * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/
406 		if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name,
407 			     "ov2722", 6) && crop[pad]->height == 1092) {
408 			padding_w = 12;
409 			padding_h = 12;
410 		}
411 
412 		if (atomisp_subdev_format_conversion(isp_sd,
413 						     isp_sd->capture_pad)
414 		    && crop[pad]->width && crop[pad]->height) {
415 			crop[pad]->width -= padding_w;
416 			crop[pad]->height -= padding_h;
417 		}
418 
419 		if (isp_sd->params.video_dis_en &&
420 		    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
421 			/* This resolution contains 20 % of DVS slack
422 			 * (of the desired captured image before
423 			 * scaling, or 1 / 6 of what we get from the
424 			 * sensor) in both width and height. Remove
425 			 * it. */
426 			crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
427 						   ATOM_ISP_STEP_WIDTH);
428 			crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
429 						    ATOM_ISP_STEP_HEIGHT);
430 		}
431 
432 		crop[pad]->width = min(crop[pad]->width, r->width);
433 		crop[pad]->height = min(crop[pad]->height, r->height);
434 
435 		if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
436 			for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE;
437 			     i < ATOMISP_SUBDEV_PADS_NUM; i++) {
438 				struct v4l2_rect tmp = *crop[pad];
439 
440 				atomisp_subdev_set_selection(
441 				    sd, sd_state, which, i,
442 				    V4L2_SEL_TGT_COMPOSE,
443 				    flags, &tmp);
444 			}
445 		}
446 
447 		if (which == V4L2_SUBDEV_FORMAT_TRY)
448 			break;
449 
450 		if (isp_sd->params.video_dis_en &&
451 		    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
452 			dvs_w = rounddown(crop[pad]->width / 5,
453 					  ATOM_ISP_STEP_WIDTH);
454 			dvs_h = rounddown(crop[pad]->height / 5,
455 					  ATOM_ISP_STEP_HEIGHT);
456 		} else if (!isp_sd->params.video_dis_en &&
457 			   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
458 			/*
459 			 * For CSS2.0, digital zoom needs to set dvs envelope to 12
460 			 * when dvs is disabled.
461 			 */
462 			dvs_w = dvs_h = 12;
463 		} else {
464 			dvs_w = dvs_h = 0;
465 		}
466 		atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
467 		atomisp_css_input_set_effective_resolution(isp_sd,
468 							   ATOMISP_INPUT_STREAM_GENERAL,
469 							   crop[pad]->width,
470 							   crop[pad]->height);
471 		break;
472 	}
473 	case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
474 	case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: {
475 		/* Only compose target is supported on source pads. */
476 
477 		if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
478 			/* Scaling is disabled in this mode */
479 			r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
480 			r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
481 		}
482 
483 		if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
484 		    && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
485 			isp_sd->params.yuv_ds_en = false;
486 		else
487 			isp_sd->params.yuv_ds_en = true;
488 
489 		comp[pad]->width = r->width;
490 		comp[pad]->height = r->height;
491 
492 		if (r->width == 0 || r->height == 0 ||
493 		    crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
494 		    crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
495 			break;
496 		/*
497 		 * do cropping on sensor input if ratio of required resolution
498 		 * is different with sensor output resolution ratio:
499 		 *
500 		 * ratio = width / height
501 		 *
502 		 * if ratio_output < ratio_sensor:
503 		 *	effect_width = sensor_height * out_width / out_height;
504 		 *	effect_height = sensor_height;
505 		 * else
506 		 *	effect_width = sensor_width;
507 		 *	effect_height = sensor_width * out_height / out_width;
508 		 *
509 		 */
510 		if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
511 		    crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
512 			atomisp_css_input_set_effective_resolution(isp_sd,
513 				ATOMISP_INPUT_STREAM_GENERAL,
514 				rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
515 					  height * r->width / r->height,
516 					  ATOM_ISP_STEP_WIDTH),
517 				crop[ATOMISP_SUBDEV_PAD_SINK]->height);
518 		else
519 			atomisp_css_input_set_effective_resolution(isp_sd,
520 				ATOMISP_INPUT_STREAM_GENERAL,
521 				crop[ATOMISP_SUBDEV_PAD_SINK]->width,
522 				rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
523 					  width * r->height / r->width,
524 					  ATOM_ISP_STEP_WIDTH));
525 
526 		break;
527 	}
528 	case ATOMISP_SUBDEV_PAD_SOURCE_VF:
529 	case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
530 		comp[pad]->width = r->width;
531 		comp[pad]->height = r->height;
532 		break;
533 	default:
534 		return -EINVAL;
535 	}
536 
537 	/* Set format dimensions on non-sink pads as well. */
538 	if (pad != ATOMISP_SUBDEV_PAD_SINK) {
539 		ffmt[pad]->width = comp[pad]->width;
540 		ffmt[pad]->height = comp[pad]->height;
541 	}
542 
543 	if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target))
544 		return -EINVAL;
545 	*r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target);
546 
547 	dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
548 		r->left, r->top, r->width, r->height);
549 
550 	return 0;
551 }
552 
553 static int isp_subdev_set_selection(struct v4l2_subdev *sd,
554 				    struct v4l2_subdev_state *sd_state,
555 				    struct v4l2_subdev_selection *sel)
556 {
557 	int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
558 
559 	if (rval)
560 		return rval;
561 
562 	return atomisp_subdev_set_selection(sd, sd_state, sel->which,
563 					    sel->pad,
564 					    sel->target, sel->flags, &sel->r);
565 }
566 
567 void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
568 			     struct v4l2_subdev_state *sd_state,
569 			     uint32_t which,
570 			     u32 pad, struct v4l2_mbus_framefmt *ffmt)
571 {
572 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
573 	struct atomisp_device *isp = isp_sd->isp;
574 	struct v4l2_mbus_framefmt *__ffmt =
575 	    atomisp_subdev_get_ffmt(sd, sd_state, which, pad);
576 
577 	dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
578 		atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code,
579 		which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
580 		: "V4L2_SUBDEV_FORMAT_ACTIVE");
581 
582 	switch (pad) {
583 	case ATOMISP_SUBDEV_PAD_SINK: {
584 		const struct atomisp_in_fmt_conv *fc =
585 		    atomisp_find_in_fmt_conv(ffmt->code);
586 
587 		if (!fc) {
588 			fc = atomisp_in_fmt_conv;
589 			ffmt->code = fc->code;
590 			dev_dbg(isp->dev, "using 0x%8.8x instead\n",
591 				ffmt->code);
592 		}
593 
594 		*__ffmt = *ffmt;
595 
596 		isp_subdev_propagate(sd, sd_state, which, pad,
597 				     V4L2_SEL_TGT_CROP, 0);
598 
599 		if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
600 			atomisp_css_input_set_resolution(isp_sd,
601 							 ATOMISP_INPUT_STREAM_GENERAL, ffmt);
602 			atomisp_css_input_set_binning_factor(isp_sd,
603 							     ATOMISP_INPUT_STREAM_GENERAL,
604 							     0);
605 			atomisp_css_input_set_bayer_order(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
606 							  fc->bayer_order);
607 			atomisp_css_input_set_format(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
608 						     fc->atomisp_in_fmt);
609 			atomisp_css_set_default_isys_config(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
610 							    ffmt);
611 		}
612 
613 		break;
614 	}
615 	case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
616 	case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
617 	case ATOMISP_SUBDEV_PAD_SOURCE_VF:
618 	case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
619 		__ffmt->code = ffmt->code;
620 		break;
621 	}
622 }
623 
624 /*
625  * isp_subdev_get_format - Retrieve the video format on a pad
626  * @sd : ISP V4L2 subdevice
627  * @fh : V4L2 subdev file handle
628  * @pad: Pad number
629  * @fmt: Format
630  *
631  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
632  * to the format type.
633  */
634 static int isp_subdev_get_format(struct v4l2_subdev *sd,
635 				 struct v4l2_subdev_state *sd_state,
636 				 struct v4l2_subdev_format *fmt)
637 {
638 	fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which,
639 					       fmt->pad);
640 
641 	return 0;
642 }
643 
644 /*
645  * isp_subdev_set_format - Set the video format on a pad
646  * @sd : ISP subdev V4L2 subdevice
647  * @fh : V4L2 subdev file handle
648  * @pad: Pad number
649  * @fmt: Format
650  *
651  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
652  * to the format type.
653  */
654 static int isp_subdev_set_format(struct v4l2_subdev *sd,
655 				 struct v4l2_subdev_state *sd_state,
656 				 struct v4l2_subdev_format *fmt)
657 {
658 	atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
659 				&fmt->format);
660 
661 	return 0;
662 }
663 
664 /* V4L2 subdev core operations */
665 static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
666 	.ioctl = isp_subdev_ioctl, .s_power = isp_subdev_set_power,
667 	.subscribe_event = isp_subdev_subscribe_event,
668 	.unsubscribe_event = isp_subdev_unsubscribe_event,
669 };
670 
671 /* V4L2 subdev pad operations */
672 static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
673 	.enum_mbus_code = isp_subdev_enum_mbus_code,
674 	.get_fmt = isp_subdev_get_format,
675 	.set_fmt = isp_subdev_set_format,
676 	.get_selection = isp_subdev_get_selection,
677 	.set_selection = isp_subdev_set_selection,
678 	.link_validate = v4l2_subdev_link_validate_default,
679 };
680 
681 /* V4L2 subdev operations */
682 static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
683 	.core = &isp_subdev_v4l2_core_ops,
684 	.pad = &isp_subdev_v4l2_pad_ops,
685 };
686 
687 static void isp_subdev_init_params(struct atomisp_sub_device *asd)
688 {
689 	unsigned int i;
690 
691 	/* parameters initialization */
692 	INIT_LIST_HEAD(&asd->s3a_stats);
693 	INIT_LIST_HEAD(&asd->s3a_stats_in_css);
694 	INIT_LIST_HEAD(&asd->s3a_stats_ready);
695 	INIT_LIST_HEAD(&asd->dis_stats);
696 	INIT_LIST_HEAD(&asd->dis_stats_in_css);
697 	spin_lock_init(&asd->dis_stats_lock);
698 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
699 		INIT_LIST_HEAD(&asd->metadata[i]);
700 		INIT_LIST_HEAD(&asd->metadata_in_css[i]);
701 		INIT_LIST_HEAD(&asd->metadata_ready[i]);
702 	}
703 }
704 
705 /* media operations */
706 static const struct media_entity_operations isp_subdev_media_ops = {
707 	.link_validate = v4l2_subdev_link_validate,
708 	/*	 .set_power = v4l2_subdev_set_power,	*/
709 };
710 
711 static int __atomisp_update_run_mode(struct atomisp_sub_device *asd)
712 {
713 	struct atomisp_device *isp = asd->isp;
714 	struct v4l2_ctrl *ctrl = asd->run_mode;
715 	struct v4l2_ctrl *c;
716 	s32 mode;
717 
718 	mode = ctrl->val;
719 
720 	c = v4l2_ctrl_find(
721 		isp->inputs[asd->input_curr].camera->ctrl_handler,
722 		V4L2_CID_RUN_MODE);
723 
724 	if (c)
725 		return v4l2_ctrl_s_ctrl(c, mode);
726 
727 	return 0;
728 }
729 
730 int atomisp_update_run_mode(struct atomisp_sub_device *asd)
731 {
732 	int rval;
733 
734 	mutex_lock(asd->ctrl_handler.lock);
735 	rval = __atomisp_update_run_mode(asd);
736 	mutex_unlock(asd->ctrl_handler.lock);
737 
738 	return rval;
739 }
740 
741 static int s_ctrl(struct v4l2_ctrl *ctrl)
742 {
743 	struct atomisp_sub_device *asd = container_of(
744 					     ctrl->handler, struct atomisp_sub_device, ctrl_handler);
745 	switch (ctrl->id) {
746 	case V4L2_CID_RUN_MODE:
747 		return __atomisp_update_run_mode(asd);
748 	}
749 
750 	return 0;
751 }
752 
753 static const struct v4l2_ctrl_ops ctrl_ops = {
754 	.s_ctrl = &s_ctrl,
755 };
756 
757 static const char *const ctrl_run_mode_menu[] = {
758 	NULL,
759 	"Video",
760 	"Still capture",
761 	"Continuous capture",
762 	"Preview",
763 };
764 
765 static const struct v4l2_ctrl_config ctrl_run_mode = {
766 	.ops = &ctrl_ops,
767 	.id = V4L2_CID_RUN_MODE,
768 	.name = "Atomisp run mode",
769 	.type = V4L2_CTRL_TYPE_MENU,
770 	.min = 1,
771 	.def = 1,
772 	.max = 4,
773 	.qmenu = ctrl_run_mode_menu,
774 };
775 
776 static const char *const ctrl_vfpp_mode_menu[] = {
777 	"Enable",			/* vfpp always enabled */
778 	"Disable to scaler mode",	/* CSS into video mode and disable */
779 	"Disable to low latency mode",	/* CSS into still mode and disable */
780 };
781 
782 static const struct v4l2_ctrl_config ctrl_vfpp = {
783 	.id = V4L2_CID_VFPP,
784 	.name = "Atomisp vf postprocess",
785 	.type = V4L2_CTRL_TYPE_MENU,
786 	.min = 0,
787 	.def = 0,
788 	.max = 2,
789 	.qmenu = ctrl_vfpp_mode_menu,
790 };
791 
792 /*
793  * Control for continuous mode raw buffer size
794  *
795  * The size of the RAW ringbuffer sets limit on how much
796  * back in time application can go when requesting capture
797  * frames to be rendered, and how many frames can be rendered
798  * in a burst at full sensor rate.
799  *
800  * Note: this setting has a big impact on memory consumption of
801  * the CSS subsystem.
802  */
803 static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
804 	.ops = &ctrl_ops,
805 	.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
806 	.type = V4L2_CTRL_TYPE_INTEGER,
807 	.name = "Continuous raw ringbuffer size",
808 	.min = 1,
809 	.max = 100, /* depends on CSS version, runtime checked */
810 	.step = 1,
811 	.def = 3,
812 };
813 
814 /*
815  * Control for enabling continuous viewfinder
816  *
817  * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ),
818  * preview pipeline continues concurrently with capture
819  * processing. When disabled, and continuous mode is used,
820  * preview is paused while captures are processed, but
821  * full pipeline restart is not needed.
822  *
823  * By setting this to disabled, capture processing is
824  * essentially given priority over preview, and the effective
825  * capture output rate may be higher than with continuous
826  * viewfinder enabled.
827  */
828 static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
829 	.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
830 	.type = V4L2_CTRL_TYPE_BOOLEAN,
831 	.name = "Continuous viewfinder",
832 	.min = 0,
833 	.max = 1,
834 	.step = 1,
835 	.def = 0,
836 };
837 
838 /*
839  * Control for enabling Lock&Unlock Raw Buffer mechanism
840  *
841  * When enabled, Raw Buffer can be locked and unlocked.
842  * Application can hold the exp_id of Raw Buffer
843  * and unlock it when no longer needed.
844  * Note: Make sure set this configuration before creating stream.
845  */
846 static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
847 	.id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
848 	.type = V4L2_CTRL_TYPE_BOOLEAN,
849 	.name = "Lock Unlock Raw Buffer",
850 	.min = 0,
851 	.max = 1,
852 	.step = 1,
853 	.def = 0,
854 };
855 
856 /*
857  * Control to disable digital zoom of the whole stream
858  *
859  * When it is true, pipe configuration enable_dz will be set to false.
860  * This can help get a better performance by disabling pp binary.
861  *
862  * Note: Make sure set this configuration before creating stream.
863  */
864 static const struct v4l2_ctrl_config ctrl_disable_dz = {
865 	.id = V4L2_CID_DISABLE_DZ,
866 	.type = V4L2_CTRL_TYPE_BOOLEAN,
867 	.name = "Disable digital zoom",
868 	.min = 0,
869 	.max = 1,
870 	.step = 1,
871 	.def = 0,
872 };
873 
874 static int atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
875 				    struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
876 {
877 	int ret;
878 
879 	pipe->type = buf_type;
880 	pipe->asd = asd;
881 	pipe->isp = asd->isp;
882 	spin_lock_init(&pipe->irq_lock);
883 	mutex_init(&pipe->vb_queue_mutex);
884 
885 	/* Init videobuf2 queue structure */
886 	pipe->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
887 	pipe->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR;
888 	pipe->vb_queue.buf_struct_size = sizeof(struct ia_css_frame);
889 	pipe->vb_queue.ops = &atomisp_vb2_ops;
890 	pipe->vb_queue.mem_ops = &vb2_vmalloc_memops;
891 	pipe->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
892 	ret = vb2_queue_init(&pipe->vb_queue);
893 	if (ret)
894 		return ret;
895 
896 	pipe->vdev.queue = &pipe->vb_queue;
897 	pipe->vdev.queue->lock = &pipe->vb_queue_mutex;
898 
899 	INIT_LIST_HEAD(&pipe->buffers_in_css);
900 	INIT_LIST_HEAD(&pipe->activeq);
901 	INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
902 	INIT_LIST_HEAD(&pipe->per_frame_params);
903 
904 	return 0;
905 }
906 
907 /*
908  * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
909  * @asd: ISP CCDC module
910  *
911  * Return 0 on success and a negative error code on failure.
912  */
913 static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
914 {
915 	struct v4l2_subdev *sd = &asd->subdev;
916 	struct media_pad *pads = asd->pads;
917 	struct media_entity *me = &sd->entity;
918 	int ret;
919 
920 	v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
921 	sprintf(sd->name, "ATOMISP_SUBDEV");
922 	v4l2_set_subdevdata(sd, asd);
923 	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
924 
925 	pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
926 	pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE;
927 	pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE;
928 	pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE;
929 	pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE;
930 
931 	asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code =
932 	    MEDIA_BUS_FMT_SBGGR10_1X10;
933 	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code =
934 	    MEDIA_BUS_FMT_SBGGR10_1X10;
935 	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code =
936 	    MEDIA_BUS_FMT_SBGGR10_1X10;
937 	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code =
938 	    MEDIA_BUS_FMT_SBGGR10_1X10;
939 	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code =
940 	    MEDIA_BUS_FMT_SBGGR10_1X10;
941 
942 	me->ops = &isp_subdev_media_ops;
943 	me->function = MEDIA_ENT_F_PROC_VIDEO_ISP;
944 	ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
945 	if (ret < 0)
946 		return ret;
947 
948 	ret = atomisp_init_subdev_pipe(asd, &asd->video_out_preview,
949 				       V4L2_BUF_TYPE_VIDEO_CAPTURE);
950 	if (ret)
951 		return ret;
952 
953 	ret = atomisp_init_subdev_pipe(asd, &asd->video_out_vf,
954 				       V4L2_BUF_TYPE_VIDEO_CAPTURE);
955 	if (ret)
956 		return ret;
957 
958 	ret = atomisp_init_subdev_pipe(asd, &asd->video_out_capture,
959 				       V4L2_BUF_TYPE_VIDEO_CAPTURE);
960 	if (ret)
961 		return ret;
962 
963 	ret = atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture,
964 				       V4L2_BUF_TYPE_VIDEO_CAPTURE);
965 	if (ret)
966 		return ret;
967 
968 	ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE",
969 				 ATOMISP_RUN_MODE_STILL_CAPTURE);
970 	if (ret < 0)
971 		return ret;
972 
973 	ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER",
974 				 ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE);
975 	if (ret < 0)
976 		return ret;
977 
978 	ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW",
979 				 ATOMISP_RUN_MODE_PREVIEW);
980 	if (ret < 0)
981 		return ret;
982 
983 	ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO",
984 				 ATOMISP_RUN_MODE_VIDEO);
985 	if (ret < 0)
986 		return ret;
987 
988 	ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
989 	if (ret)
990 		return ret;
991 
992 	asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
993 					     &ctrl_run_mode, NULL);
994 	asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
995 					 &ctrl_vfpp, NULL);
996 	asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
997 				     &ctrl_continuous_viewfinder,
998 				     NULL);
999 	asd->continuous_raw_buffer_size =
1000 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
1001 				 &ctrl_continuous_raw_buffer_size,
1002 				 NULL);
1003 
1004 	asd->enable_raw_buffer_lock =
1005 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
1006 				 &ctrl_enable_raw_buffer_lock,
1007 				 NULL);
1008 	asd->disable_dz =
1009 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
1010 				 &ctrl_disable_dz,
1011 				 NULL);
1012 
1013 	/* Make controls visible on subdev as well. */
1014 	asd->subdev.ctrl_handler = &asd->ctrl_handler;
1015 	spin_lock_init(&asd->raw_buffer_bitmap_lock);
1016 	return asd->ctrl_handler.error;
1017 }
1018 
1019 int atomisp_create_pads_links(struct atomisp_device *isp)
1020 {
1021 	int i, ret;
1022 
1023 	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
1024 		ret = media_create_pad_link(&isp->csi2_port[i].subdev.entity,
1025 					    CSI2_PAD_SOURCE, &isp->asd.subdev.entity,
1026 					    ATOMISP_SUBDEV_PAD_SINK, 0);
1027 		if (ret < 0)
1028 			return ret;
1029 	}
1030 
1031 	for (i = 0; i < isp->input_cnt; i++) {
1032 		/* Don't create links for the test-pattern-generator */
1033 		if (isp->inputs[i].type == TEST_PATTERN)
1034 			continue;
1035 
1036 		ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0,
1037 					    &isp->csi2_port[isp->inputs[i].
1038 						    port].subdev.entity,
1039 					    CSI2_PAD_SINK,
1040 					    MEDIA_LNK_FL_ENABLED |
1041 					    MEDIA_LNK_FL_IMMUTABLE);
1042 		if (ret < 0)
1043 			return ret;
1044 	}
1045 
1046 	ret = media_create_pad_link(&isp->asd.subdev.entity,
1047 				    ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW,
1048 				    &isp->asd.video_out_preview.vdev.entity, 0, 0);
1049 	if (ret < 0)
1050 		return ret;
1051 	ret = media_create_pad_link(&isp->asd.subdev.entity,
1052 				    ATOMISP_SUBDEV_PAD_SOURCE_VF,
1053 				    &isp->asd.video_out_vf.vdev.entity, 0, 0);
1054 	if (ret < 0)
1055 		return ret;
1056 	ret = media_create_pad_link(&isp->asd.subdev.entity,
1057 				    ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE,
1058 				    &isp->asd.video_out_capture.vdev.entity, 0, 0);
1059 	if (ret < 0)
1060 		return ret;
1061 	ret = media_create_pad_link(&isp->asd.subdev.entity,
1062 				    ATOMISP_SUBDEV_PAD_SOURCE_VIDEO,
1063 				    &isp->asd.video_out_video_capture.vdev.entity, 0, 0);
1064 	if (ret < 0)
1065 		return ret;
1066 
1067 	return 0;
1068 }
1069 
1070 static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
1071 {
1072 	v4l2_ctrl_handler_free(&asd->ctrl_handler);
1073 
1074 	media_entity_cleanup(&asd->subdev.entity);
1075 }
1076 
1077 void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
1078 {
1079 	struct v4l2_fh *fh, *fh_tmp;
1080 	struct v4l2_event event;
1081 	unsigned int i, pending_event;
1082 
1083 	list_for_each_entry_safe(fh, fh_tmp,
1084 				 &asd->subdev.devnode->fh_list, list) {
1085 		pending_event = v4l2_event_pending(fh);
1086 		for (i = 0; i < pending_event; i++)
1087 			v4l2_event_dequeue(fh, &event, 1);
1088 	}
1089 }
1090 
1091 void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
1092 {
1093 	atomisp_subdev_cleanup_entities(asd);
1094 	v4l2_device_unregister_subdev(&asd->subdev);
1095 	atomisp_video_unregister(&asd->video_out_preview);
1096 	atomisp_video_unregister(&asd->video_out_vf);
1097 	atomisp_video_unregister(&asd->video_out_capture);
1098 	atomisp_video_unregister(&asd->video_out_video_capture);
1099 }
1100 
1101 int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd,
1102 				   struct v4l2_device *vdev)
1103 {
1104 	return v4l2_device_register_subdev(vdev, &asd->subdev);
1105 }
1106 
1107 int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd,
1108 					struct v4l2_device *vdev)
1109 {
1110 	int ret;
1111 
1112 	/*
1113 	 * FIXME: check if all device caps are properly initialized.
1114 	 * Should any of those use V4L2_CAP_META_CAPTURE? Probably yes.
1115 	 */
1116 
1117 	asd->video_out_preview.vdev.v4l2_dev = vdev;
1118 	asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1119 	ret = video_register_device(&asd->video_out_preview.vdev,
1120 				    VFL_TYPE_VIDEO, -1);
1121 	if (ret < 0)
1122 		goto error;
1123 
1124 	asd->video_out_capture.vdev.v4l2_dev = vdev;
1125 	asd->video_out_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1126 	ret = video_register_device(&asd->video_out_capture.vdev,
1127 				    VFL_TYPE_VIDEO, -1);
1128 	if (ret < 0)
1129 		goto error;
1130 
1131 	asd->video_out_vf.vdev.v4l2_dev = vdev;
1132 	asd->video_out_vf.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1133 	ret = video_register_device(&asd->video_out_vf.vdev,
1134 				    VFL_TYPE_VIDEO, -1);
1135 	if (ret < 0)
1136 		goto error;
1137 
1138 	asd->video_out_video_capture.vdev.v4l2_dev = vdev;
1139 	asd->video_out_video_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1140 	ret = video_register_device(&asd->video_out_video_capture.vdev,
1141 				    VFL_TYPE_VIDEO, -1);
1142 	if (ret < 0)
1143 		goto error;
1144 
1145 	return 0;
1146 
1147 error:
1148 	atomisp_subdev_unregister_entities(asd);
1149 	return ret;
1150 }
1151 
1152 /*
1153  * atomisp_subdev_init - ISP Subdevice  initialization.
1154  * @dev: Device pointer specific to the ATOM ISP.
1155  *
1156  * TODO: Get the initialisation values from platform data.
1157  *
1158  * Return 0 on success or a negative error code otherwise.
1159  */
1160 int atomisp_subdev_init(struct atomisp_device *isp)
1161 {
1162 	int ret;
1163 
1164 	isp->asd.isp = isp;
1165 	isp_subdev_init_params(&isp->asd);
1166 	ret = isp_subdev_init_entities(&isp->asd);
1167 	if (ret < 0)
1168 		atomisp_subdev_cleanup_entities(&isp->asd);
1169 
1170 	return ret;
1171 }
1172