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