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