1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Support for Medifield PNW Camera Imaging ISP subsystem.
4  *
5  * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version
9  * 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  *
17  */
18 #include <linux/module.h>
19 #include <linux/uaccess.h>
20 #include <linux/delay.h>
21 #include <linux/device.h>
22 #include <linux/mm.h>
23 #include <linux/sched.h>
24 #include <linux/slab.h>
25 
26 #include <media/v4l2-event.h>
27 #include <media/v4l2-mediabus.h>
28 #include <media/videobuf2-vmalloc.h>
29 #include "atomisp_cmd.h"
30 #include "atomisp_common.h"
31 #include "atomisp_compat.h"
32 #include "atomisp_fops.h"
33 #include "atomisp_internal.h"
34 #include "atomisp_ioctl.h"
35 
36 const struct atomisp_in_fmt_conv atomisp_in_fmt_conv[] = {
37 	{ MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_BGGR },
38 	{ MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GBRG },
39 	{ MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_GRBG },
40 	{ MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, ATOMISP_INPUT_FORMAT_RAW_8, IA_CSS_BAYER_ORDER_RGGB },
41 	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_BGGR },
42 	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GBRG },
43 	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_GRBG },
44 	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, ATOMISP_INPUT_FORMAT_RAW_10, IA_CSS_BAYER_ORDER_RGGB },
45 	{ MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_BGGR },
46 	{ MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GBRG },
47 	{ MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_GRBG },
48 	{ MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, ATOMISP_INPUT_FORMAT_RAW_12, IA_CSS_BAYER_ORDER_RGGB },
49 	{ MEDIA_BUS_FMT_UYVY8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
50 	{ MEDIA_BUS_FMT_YUYV8_1X16, 8, 8, ATOMISP_INPUT_FORMAT_YUV422_8, 0 },
51 #if 0 // disabled due to clang warnings
52 	{ MEDIA_BUS_FMT_JPEG_1X8, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
53 	{ V4L2_MBUS_FMT_CUSTOM_NV12, 12, 12, IA_CSS_FRAME_FORMAT_NV12, 0 },
54 	{ V4L2_MBUS_FMT_CUSTOM_NV21, 12, 12, IA_CSS_FRAME_FORMAT_NV21, 0 },
55 #endif
56 	{ V4L2_MBUS_FMT_CUSTOM_YUV420, 12, 12, ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY, 0 },
57 #if 0
58 	{ V4L2_MBUS_FMT_CUSTOM_M10MO_RAW, 8, 8, IA_CSS_FRAME_FORMAT_BINARY_8, 0 },
59 #endif
60 	/* no valid V4L2 MBUS code for metadata format, so leave it 0. */
61 	{ 0, 0, 0, ATOMISP_INPUT_FORMAT_EMBEDDED, 0 },
62 	{}
63 };
64 
65 static const struct {
66 	u32 code;
67 	u32 compressed;
68 } compressed_codes[] = {
69 	{ MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 },
70 	{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 },
71 	{ MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 },
72 	{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 },
73 };
74 
atomisp_subdev_uncompressed_code(u32 code)75 u32 atomisp_subdev_uncompressed_code(u32 code)
76 {
77 	unsigned int i;
78 
79 	for (i = 0; i < ARRAY_SIZE(compressed_codes); i++)
80 		if (code == compressed_codes[i].compressed)
81 			return compressed_codes[i].code;
82 
83 	return code;
84 }
85 
atomisp_subdev_is_compressed(u32 code)86 bool atomisp_subdev_is_compressed(u32 code)
87 {
88 	int i;
89 
90 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
91 		if (code == atomisp_in_fmt_conv[i].code)
92 			return atomisp_in_fmt_conv[i].bpp !=
93 			       atomisp_in_fmt_conv[i].depth;
94 
95 	return false;
96 }
97 
atomisp_find_in_fmt_conv(u32 code)98 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv(u32 code)
99 {
100 	int i;
101 
102 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
103 		if (code == atomisp_in_fmt_conv[i].code)
104 			return atomisp_in_fmt_conv + i;
105 
106 	return NULL;
107 }
108 
atomisp_find_in_fmt_conv_by_atomisp_in_fmt(enum atomisp_input_format atomisp_in_fmt)109 const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt(
110     enum atomisp_input_format atomisp_in_fmt)
111 {
112 	int i;
113 
114 	for (i = 0; i < ARRAY_SIZE(atomisp_in_fmt_conv) - 1; i++)
115 		if (atomisp_in_fmt_conv[i].atomisp_in_fmt == atomisp_in_fmt)
116 			return atomisp_in_fmt_conv + i;
117 
118 	return NULL;
119 }
120 
atomisp_subdev_format_conversion(struct atomisp_sub_device * asd)121 bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd)
122 {
123 	struct v4l2_mbus_framefmt *sink, *src;
124 
125 	sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
126 				       V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK);
127 	src = atomisp_subdev_get_ffmt(&asd->subdev, NULL,
128 				      V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE);
129 
130 	return atomisp_is_mbuscode_raw(sink->code)
131 	       && !atomisp_is_mbuscode_raw(src->code);
132 }
133 
134 /*
135  * V4L2 subdev operations
136  */
137 
138 /*
139  * isp_subdev_ioctl - CCDC module private ioctl's
140  * @sd: ISP V4L2 subdevice
141  * @cmd: ioctl command
142  * @arg: ioctl argument
143  *
144  * Return 0 on success or a negative error code otherwise.
145  */
isp_subdev_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)146 static long isp_subdev_ioctl(struct v4l2_subdev *sd,
147 			     unsigned int cmd, void *arg)
148 {
149 	return 0;
150 }
151 
isp_subdev_subscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)152 static int isp_subdev_subscribe_event(struct v4l2_subdev *sd,
153 				      struct v4l2_fh *fh,
154 				      struct v4l2_event_subscription *sub)
155 {
156 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
157 	struct atomisp_device *isp = isp_sd->isp;
158 
159 	if (sub->type != V4L2_EVENT_FRAME_SYNC &&
160 	    sub->type != V4L2_EVENT_FRAME_END &&
161 	    sub->type != V4L2_EVENT_ATOMISP_3A_STATS_READY &&
162 	    sub->type != V4L2_EVENT_ATOMISP_METADATA_READY &&
163 	    sub->type != V4L2_EVENT_ATOMISP_PAUSE_BUFFER &&
164 	    sub->type != V4L2_EVENT_ATOMISP_CSS_RESET &&
165 	    sub->type != V4L2_EVENT_ATOMISP_ACC_COMPLETE)
166 		return -EINVAL;
167 
168 	if (sub->type == V4L2_EVENT_FRAME_SYNC &&
169 	    !atomisp_css_valid_sof(isp))
170 		return -EINVAL;
171 
172 	return v4l2_event_subscribe(fh, sub, 16, NULL);
173 }
174 
isp_subdev_unsubscribe_event(struct v4l2_subdev * sd,struct v4l2_fh * fh,struct v4l2_event_subscription * sub)175 static int isp_subdev_unsubscribe_event(struct v4l2_subdev *sd,
176 					struct v4l2_fh *fh,
177 					struct v4l2_event_subscription *sub)
178 {
179 	return v4l2_event_unsubscribe(fh, sub);
180 }
181 
182 /*
183  * isp_subdev_enum_mbus_code - Handle pixel format enumeration
184  * @sd: pointer to v4l2 subdev structure
185  * @fh : V4L2 subdev file handle
186  * @code: pointer to v4l2_subdev_pad_mbus_code_enum structure
187  * return -EINVAL or zero on success
188  */
isp_subdev_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)189 static int isp_subdev_enum_mbus_code(struct v4l2_subdev *sd,
190 				     struct v4l2_subdev_state *sd_state,
191 				     struct v4l2_subdev_mbus_code_enum *code)
192 {
193 	if (code->index >= ARRAY_SIZE(atomisp_in_fmt_conv) - 1)
194 		return -EINVAL;
195 
196 	code->code = atomisp_in_fmt_conv[code->index].code;
197 
198 	return 0;
199 }
200 
isp_subdev_validate_rect(struct v4l2_subdev * sd,uint32_t pad,uint32_t target)201 static int isp_subdev_validate_rect(struct v4l2_subdev *sd, uint32_t pad,
202 				    uint32_t target)
203 {
204 	switch (pad) {
205 	case ATOMISP_SUBDEV_PAD_SINK:
206 		switch (target) {
207 		case V4L2_SEL_TGT_CROP:
208 			return 0;
209 		}
210 		break;
211 	default:
212 		switch (target) {
213 		case V4L2_SEL_TGT_COMPOSE:
214 			return 0;
215 		}
216 		break;
217 	}
218 
219 	return -EINVAL;
220 }
221 
atomisp_subdev_get_rect(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,u32 which,uint32_t pad,uint32_t target)222 struct v4l2_rect *atomisp_subdev_get_rect(struct v4l2_subdev *sd,
223 	struct v4l2_subdev_state *sd_state,
224 	u32 which, uint32_t pad,
225 	uint32_t target)
226 {
227 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
228 
229 	if (which == V4L2_SUBDEV_FORMAT_TRY) {
230 		switch (target) {
231 		case V4L2_SEL_TGT_CROP:
232 			return v4l2_subdev_state_get_crop(sd_state, pad);
233 		case V4L2_SEL_TGT_COMPOSE:
234 			return v4l2_subdev_state_get_compose(sd_state, pad);
235 		}
236 	}
237 
238 	switch (target) {
239 	case V4L2_SEL_TGT_CROP:
240 		return &isp_sd->fmt[pad].crop;
241 	case V4L2_SEL_TGT_COMPOSE:
242 		return &isp_sd->fmt[pad].compose;
243 	}
244 
245 	return NULL;
246 }
247 
248 struct v4l2_mbus_framefmt
atomisp_subdev_get_ffmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,uint32_t which,uint32_t pad)249 *atomisp_subdev_get_ffmt(struct v4l2_subdev *sd,
250 			 struct v4l2_subdev_state *sd_state, uint32_t which,
251 			 uint32_t pad)
252 {
253 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
254 
255 	if (which == V4L2_SUBDEV_FORMAT_TRY)
256 		return v4l2_subdev_state_get_format(sd_state, pad);
257 
258 	return &isp_sd->fmt[pad].fmt;
259 }
260 
isp_get_fmt_rect(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,uint32_t which,struct v4l2_mbus_framefmt ** ffmt,struct v4l2_rect * crop[ATOMISP_SUBDEV_PADS_NUM],struct v4l2_rect * comp[ATOMISP_SUBDEV_PADS_NUM])261 static void isp_get_fmt_rect(struct v4l2_subdev *sd,
262 			     struct v4l2_subdev_state *sd_state,
263 			     uint32_t which,
264 			     struct v4l2_mbus_framefmt **ffmt,
265 			     struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
266 			     struct v4l2_rect *comp[ATOMISP_SUBDEV_PADS_NUM])
267 {
268 	unsigned int i;
269 
270 	for (i = 0; i < ATOMISP_SUBDEV_PADS_NUM; i++) {
271 		ffmt[i] = atomisp_subdev_get_ffmt(sd, sd_state, which, i);
272 		crop[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
273 						  V4L2_SEL_TGT_CROP);
274 		comp[i] = atomisp_subdev_get_rect(sd, sd_state, which, i,
275 						  V4L2_SEL_TGT_COMPOSE);
276 	}
277 }
278 
isp_subdev_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)279 static int isp_subdev_get_selection(struct v4l2_subdev *sd,
280 				    struct v4l2_subdev_state *sd_state,
281 				    struct v4l2_subdev_selection *sel)
282 {
283 	struct v4l2_rect *rec;
284 	int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
285 
286 	if (rval)
287 		return rval;
288 
289 	rec = atomisp_subdev_get_rect(sd, sd_state, sel->which, sel->pad,
290 				      sel->target);
291 	if (!rec)
292 		return -EINVAL;
293 
294 	sel->r = *rec;
295 	return 0;
296 }
297 
atomisp_pad_str(unsigned int pad)298 static const char *atomisp_pad_str(unsigned int pad)
299 {
300 	static const char *const pad_str[] = {
301 		"ATOMISP_SUBDEV_PAD_SINK",
302 		"ATOMISP_SUBDEV_PAD_SOURCE",
303 	};
304 
305 	if (pad >= ARRAY_SIZE(pad_str))
306 		return "ATOMISP_INVALID_PAD";
307 	return pad_str[pad];
308 }
309 
atomisp_subdev_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,u32 which,uint32_t pad,uint32_t target,u32 flags,struct v4l2_rect * r)310 int atomisp_subdev_set_selection(struct v4l2_subdev *sd,
311 				 struct v4l2_subdev_state *sd_state,
312 				 u32 which, uint32_t pad, uint32_t target,
313 				 u32 flags, struct v4l2_rect *r)
314 {
315 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
316 	struct atomisp_device *isp = isp_sd->isp;
317 	struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM];
318 	struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM],
319 		       *comp[ATOMISP_SUBDEV_PADS_NUM];
320 
321 	if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) ||
322 	    (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE))
323 		return -EINVAL;
324 
325 	isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp);
326 
327 	dev_dbg(isp->dev,
328 		"sel: pad %s tgt %s l %d t %d w %d h %d which %s f 0x%8.8x\n",
329 		atomisp_pad_str(pad), target == V4L2_SEL_TGT_CROP
330 		? "V4L2_SEL_TGT_CROP" : "V4L2_SEL_TGT_COMPOSE",
331 		r->left, r->top, r->width, r->height,
332 		which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
333 		: "V4L2_SUBDEV_FORMAT_ACTIVE", flags);
334 
335 	r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH);
336 	r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT);
337 
338 	if (pad == ATOMISP_SUBDEV_PAD_SINK) {
339 		/* Only crop target supported on sink pad. */
340 		unsigned int dvs_w, dvs_h;
341 
342 		crop[pad]->width = ffmt[pad]->width;
343 		crop[pad]->height = ffmt[pad]->height;
344 
345 		if (atomisp_subdev_format_conversion(isp_sd)
346 		    && crop[pad]->width && crop[pad]->height) {
347 			crop[pad]->width -= isp_sd->sink_pad_padding_w;
348 			crop[pad]->height -= isp_sd->sink_pad_padding_h;
349 		}
350 
351 		if (isp_sd->params.video_dis_en &&
352 		    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
353 			/*
354 			 * This resolution contains 20 % of DVS slack
355 			 * (of the desired captured image before
356 			 * scaling, or 1 / 6 of what we get from the
357 			 * sensor) in both width and height. Remove it.
358 			 */
359 			crop[pad]->width = roundup(crop[pad]->width * 5 / 6,
360 						   ATOM_ISP_STEP_WIDTH);
361 			crop[pad]->height = roundup(crop[pad]->height * 5 / 6,
362 						    ATOM_ISP_STEP_HEIGHT);
363 		}
364 
365 		crop[pad]->width = min(crop[pad]->width, r->width);
366 		crop[pad]->height = min(crop[pad]->height, r->height);
367 
368 		if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) {
369 			struct v4l2_rect tmp = *crop[pad];
370 
371 			atomisp_subdev_set_selection(sd, sd_state, which,
372 						     ATOMISP_SUBDEV_PAD_SOURCE,
373 						     V4L2_SEL_TGT_COMPOSE, flags, &tmp);
374 		}
375 
376 		if (which == V4L2_SUBDEV_FORMAT_TRY)
377 			goto get_rect;
378 
379 		if (isp_sd->params.video_dis_en &&
380 		    isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
381 			dvs_w = rounddown(crop[pad]->width / 5,
382 					  ATOM_ISP_STEP_WIDTH);
383 			dvs_h = rounddown(crop[pad]->height / 5,
384 					  ATOM_ISP_STEP_HEIGHT);
385 		} else if (!isp_sd->params.video_dis_en &&
386 			   isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
387 			/*
388 			 * For CSS2.0, digital zoom needs to set dvs envelope to 12
389 			 * when dvs is disabled.
390 			 */
391 			dvs_w = dvs_h = 12;
392 		} else {
393 			dvs_w = dvs_h = 0;
394 		}
395 		atomisp_css_video_set_dis_envelope(isp_sd, dvs_w, dvs_h);
396 		atomisp_css_input_set_effective_resolution(isp_sd,
397 							   ATOMISP_INPUT_STREAM_GENERAL,
398 							   crop[pad]->width,
399 							   crop[pad]->height);
400 	} else if (isp_sd->run_mode->val != ATOMISP_RUN_MODE_PREVIEW) {
401 		/* Only compose target is supported on source pads. */
402 		if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
403 			/* Scaling is disabled in this mode */
404 			r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width;
405 			r->height = crop[ATOMISP_SUBDEV_PAD_SINK]->height;
406 		}
407 
408 		if (crop[ATOMISP_SUBDEV_PAD_SINK]->width == r->width
409 		    && crop[ATOMISP_SUBDEV_PAD_SINK]->height == r->height)
410 			isp_sd->params.yuv_ds_en = false;
411 		else
412 			isp_sd->params.yuv_ds_en = true;
413 
414 		comp[pad]->width = r->width;
415 		comp[pad]->height = r->height;
416 
417 		if (r->width == 0 || r->height == 0 ||
418 		    crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 ||
419 		    crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0)
420 			goto get_rect;
421 		/*
422 		 * do cropping on sensor input if ratio of required resolution
423 		 * is different with sensor output resolution ratio:
424 		 *
425 		 * ratio = width / height
426 		 *
427 		 * if ratio_output < ratio_sensor:
428 		 *	effect_width = sensor_height * out_width / out_height;
429 		 *	effect_height = sensor_height;
430 		 * else
431 		 *	effect_width = sensor_width;
432 		 *	effect_height = sensor_width * out_height / out_width;
433 		 *
434 		 */
435 		if (r->width * crop[ATOMISP_SUBDEV_PAD_SINK]->height <
436 		    crop[ATOMISP_SUBDEV_PAD_SINK]->width * r->height)
437 			atomisp_css_input_set_effective_resolution(isp_sd,
438 				ATOMISP_INPUT_STREAM_GENERAL,
439 				rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
440 					  height * r->width / r->height,
441 					  ATOM_ISP_STEP_WIDTH),
442 				crop[ATOMISP_SUBDEV_PAD_SINK]->height);
443 		else
444 			atomisp_css_input_set_effective_resolution(isp_sd,
445 				ATOMISP_INPUT_STREAM_GENERAL,
446 				crop[ATOMISP_SUBDEV_PAD_SINK]->width,
447 				rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]->
448 					  width * r->height / r->width,
449 					  ATOM_ISP_STEP_WIDTH));
450 	} else {
451 		comp[pad]->width = r->width;
452 		comp[pad]->height = r->height;
453 	}
454 
455 get_rect:
456 	/* Set format dimensions on non-sink pads as well. */
457 	if (pad != ATOMISP_SUBDEV_PAD_SINK) {
458 		ffmt[pad]->width = comp[pad]->width;
459 		ffmt[pad]->height = comp[pad]->height;
460 	}
461 
462 	if (!atomisp_subdev_get_rect(sd, sd_state, which, pad, target))
463 		return -EINVAL;
464 	*r = *atomisp_subdev_get_rect(sd, sd_state, which, pad, target);
465 
466 	dev_dbg(isp->dev, "sel actual: l %d t %d w %d h %d\n",
467 		r->left, r->top, r->width, r->height);
468 
469 	return 0;
470 }
471 
isp_subdev_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_selection * sel)472 static int isp_subdev_set_selection(struct v4l2_subdev *sd,
473 				    struct v4l2_subdev_state *sd_state,
474 				    struct v4l2_subdev_selection *sel)
475 {
476 	int rval = isp_subdev_validate_rect(sd, sel->pad, sel->target);
477 
478 	if (rval)
479 		return rval;
480 
481 	return atomisp_subdev_set_selection(sd, sd_state, sel->which,
482 					    sel->pad,
483 					    sel->target, sel->flags, &sel->r);
484 }
485 
atomisp_subdev_set_ffmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,uint32_t which,u32 pad,struct v4l2_mbus_framefmt * ffmt)486 void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd,
487 			     struct v4l2_subdev_state *sd_state,
488 			     uint32_t which,
489 			     u32 pad, struct v4l2_mbus_framefmt *ffmt)
490 {
491 	struct atomisp_sub_device *isp_sd = v4l2_get_subdevdata(sd);
492 	struct atomisp_device *isp = isp_sd->isp;
493 	struct v4l2_mbus_framefmt *__ffmt =
494 	    atomisp_subdev_get_ffmt(sd, sd_state, which, pad);
495 
496 	dev_dbg(isp->dev, "ffmt: pad %s w %d h %d code 0x%8.8x which %s\n",
497 		atomisp_pad_str(pad), ffmt->width, ffmt->height, ffmt->code,
498 		which == V4L2_SUBDEV_FORMAT_TRY ? "V4L2_SUBDEV_FORMAT_TRY"
499 		: "V4L2_SUBDEV_FORMAT_ACTIVE");
500 
501 	switch (pad) {
502 	case ATOMISP_SUBDEV_PAD_SINK: {
503 		const struct atomisp_in_fmt_conv *fc =
504 		    atomisp_find_in_fmt_conv(ffmt->code);
505 		struct v4l2_rect r = {};
506 
507 		if (!fc) {
508 			fc = atomisp_in_fmt_conv;
509 			ffmt->code = fc->code;
510 			dev_dbg(isp->dev, "using 0x%8.8x instead\n",
511 				ffmt->code);
512 		}
513 
514 		*__ffmt = *ffmt;
515 
516 		/* Propagate new ffmt to selection */
517 		r.width = ffmt->width;
518 		r.height = ffmt->height;
519 		/* Only crop target supported on sink pad. */
520 		atomisp_subdev_set_selection(sd, sd_state, which, pad,
521 					     V4L2_SEL_TGT_CROP, 0, &r);
522 
523 		if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
524 			atomisp_css_input_set_resolution(isp_sd,
525 							 ATOMISP_INPUT_STREAM_GENERAL, ffmt);
526 			atomisp_css_input_set_binning_factor(isp_sd,
527 							     ATOMISP_INPUT_STREAM_GENERAL,
528 							     0);
529 			atomisp_css_input_set_bayer_order(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
530 							  fc->bayer_order);
531 			atomisp_css_input_set_format(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
532 						     fc->atomisp_in_fmt);
533 			atomisp_css_set_default_isys_config(isp_sd, ATOMISP_INPUT_STREAM_GENERAL,
534 							    ffmt);
535 		}
536 
537 		break;
538 	}
539 	case ATOMISP_SUBDEV_PAD_SOURCE:
540 		__ffmt->code = ffmt->code;
541 		break;
542 	}
543 }
544 
545 /*
546  * isp_subdev_get_format - Retrieve the video format on a pad
547  * @sd : ISP V4L2 subdevice
548  * @fh : V4L2 subdev file handle
549  * @pad: Pad number
550  * @fmt: Format
551  *
552  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
553  * to the format type.
554  */
isp_subdev_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)555 static int isp_subdev_get_format(struct v4l2_subdev *sd,
556 				 struct v4l2_subdev_state *sd_state,
557 				 struct v4l2_subdev_format *fmt)
558 {
559 	fmt->format = *atomisp_subdev_get_ffmt(sd, sd_state, fmt->which,
560 					       fmt->pad);
561 
562 	return 0;
563 }
564 
565 /*
566  * isp_subdev_set_format - Set the video format on a pad
567  * @sd : ISP subdev V4L2 subdevice
568  * @fh : V4L2 subdev file handle
569  * @pad: Pad number
570  * @fmt: Format
571  *
572  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
573  * to the format type.
574  */
isp_subdev_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)575 static int isp_subdev_set_format(struct v4l2_subdev *sd,
576 				 struct v4l2_subdev_state *sd_state,
577 				 struct v4l2_subdev_format *fmt)
578 {
579 	atomisp_subdev_set_ffmt(sd, sd_state, fmt->which, fmt->pad,
580 				&fmt->format);
581 
582 	return 0;
583 }
584 
585 /* V4L2 subdev core operations */
586 static const struct v4l2_subdev_core_ops isp_subdev_v4l2_core_ops = {
587 	.ioctl = isp_subdev_ioctl,
588 	.subscribe_event = isp_subdev_subscribe_event,
589 	.unsubscribe_event = isp_subdev_unsubscribe_event,
590 };
591 
592 /* V4L2 subdev pad operations */
593 static const struct v4l2_subdev_pad_ops isp_subdev_v4l2_pad_ops = {
594 	.enum_mbus_code = isp_subdev_enum_mbus_code,
595 	.get_fmt = isp_subdev_get_format,
596 	.set_fmt = isp_subdev_set_format,
597 	.get_selection = isp_subdev_get_selection,
598 	.set_selection = isp_subdev_set_selection,
599 	.link_validate = v4l2_subdev_link_validate_default,
600 };
601 
602 /* V4L2 subdev operations */
603 static const struct v4l2_subdev_ops isp_subdev_v4l2_ops = {
604 	.core = &isp_subdev_v4l2_core_ops,
605 	.pad = &isp_subdev_v4l2_pad_ops,
606 };
607 
isp_subdev_init_params(struct atomisp_sub_device * asd)608 static void isp_subdev_init_params(struct atomisp_sub_device *asd)
609 {
610 	unsigned int i;
611 
612 	/* parameters initialization */
613 	INIT_LIST_HEAD(&asd->s3a_stats);
614 	INIT_LIST_HEAD(&asd->s3a_stats_in_css);
615 	INIT_LIST_HEAD(&asd->s3a_stats_ready);
616 	INIT_LIST_HEAD(&asd->dis_stats);
617 	INIT_LIST_HEAD(&asd->dis_stats_in_css);
618 	spin_lock_init(&asd->dis_stats_lock);
619 	for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
620 		INIT_LIST_HEAD(&asd->metadata[i]);
621 		INIT_LIST_HEAD(&asd->metadata_in_css[i]);
622 		INIT_LIST_HEAD(&asd->metadata_ready[i]);
623 	}
624 }
625 
626 /* media operations */
atomisp_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)627 static int atomisp_link_setup(struct media_entity *entity,
628 			      const struct media_pad *local,
629 			      const struct media_pad *remote, u32 flags)
630 {
631 	struct v4l2_subdev *sd = container_of(entity, struct v4l2_subdev,
632 					      entity);
633 	struct atomisp_sub_device *asd = v4l2_get_subdevdata(sd);
634 	struct atomisp_device *isp = asd->isp;
635 	int i;
636 
637 	/* ISP's source is immutable */
638 	if (local != &asd->pads[ATOMISP_SUBDEV_PAD_SINK]) {
639 		v4l2_err(sd, "Error pad %d does not support changing flags\n",
640 			 local->index);
641 		return -EINVAL;
642 	}
643 
644 	for (i = 0; i < isp->input_cnt; i++) {
645 		if (&isp->inputs[i].csi_port->entity.pads[CSI2_PAD_SOURCE] == remote)
646 			break;
647 	}
648 
649 	if (i == isp->input_cnt) {
650 		v4l2_err(sd, "Error no sensor for selected CSI receiver\n");
651 		return -EINVAL;
652 	}
653 
654 	/* Turn off the sensor on link disable */
655 	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
656 		atomisp_s_sensor_power(isp, i, 0);
657 		return 0;
658 	}
659 
660 	return atomisp_select_input(isp, i);
661 }
662 
663 static const struct media_entity_operations isp_subdev_media_ops = {
664 	.link_validate = v4l2_subdev_link_validate,
665 	.link_setup = atomisp_link_setup,
666 	/*	 .set_power = v4l2_subdev_set_power,	*/
667 };
668 
669 static const char *const ctrl_run_mode_menu[] = {
670 	[ATOMISP_RUN_MODE_VIDEO]		= "Video",
671 	[ATOMISP_RUN_MODE_STILL_CAPTURE]	= "Still capture",
672 	[ATOMISP_RUN_MODE_PREVIEW]		= "Preview",
673 };
674 
675 static const struct v4l2_ctrl_config ctrl_run_mode = {
676 	.id = V4L2_CID_RUN_MODE,
677 	.name = "Atomisp run mode",
678 	.type = V4L2_CTRL_TYPE_MENU,
679 	.min = ATOMISP_RUN_MODE_MIN,
680 	.def = ATOMISP_RUN_MODE_PREVIEW,
681 	.max = ATOMISP_RUN_MODE_MAX,
682 	.qmenu = ctrl_run_mode_menu,
683 };
684 
685 static const char *const ctrl_vfpp_mode_menu[] = {
686 	"Enable",			/* vfpp always enabled */
687 	"Disable to scaler mode",	/* CSS into video mode and disable */
688 	"Disable to low latency mode",	/* CSS into still mode and disable */
689 };
690 
691 static const struct v4l2_ctrl_config ctrl_vfpp = {
692 	.id = V4L2_CID_VFPP,
693 	.name = "Atomisp vf postprocess",
694 	.type = V4L2_CTRL_TYPE_MENU,
695 	.min = 0,
696 	.def = 0,
697 	.max = 2,
698 	.qmenu = ctrl_vfpp_mode_menu,
699 };
700 
701 /*
702  * Control for continuous mode raw buffer size
703  *
704  * The size of the RAW ringbuffer sets limit on how much
705  * back in time application can go when requesting capture
706  * frames to be rendered, and how many frames can be rendered
707  * in a burst at full sensor rate.
708  *
709  * Note: this setting has a big impact on memory consumption of
710  * the CSS subsystem.
711  */
712 static const struct v4l2_ctrl_config ctrl_continuous_raw_buffer_size = {
713 	.id = V4L2_CID_ATOMISP_CONTINUOUS_RAW_BUFFER_SIZE,
714 	.type = V4L2_CTRL_TYPE_INTEGER,
715 	.name = "Continuous raw ringbuffer size",
716 	.min = 1,
717 	.max = 100, /* depends on CSS version, runtime checked */
718 	.step = 1,
719 	.def = 3,
720 };
721 
722 /*
723  * Control for enabling continuous viewfinder
724  *
725  * When enabled, and ISP is in continuous mode (see ctrl_continuous_mode ),
726  * preview pipeline continues concurrently with capture
727  * processing. When disabled, and continuous mode is used,
728  * preview is paused while captures are processed, but
729  * full pipeline restart is not needed.
730  *
731  * By setting this to disabled, capture processing is
732  * essentially given priority over preview, and the effective
733  * capture output rate may be higher than with continuous
734  * viewfinder enabled.
735  */
736 static const struct v4l2_ctrl_config ctrl_continuous_viewfinder = {
737 	.id = V4L2_CID_ATOMISP_CONTINUOUS_VIEWFINDER,
738 	.type = V4L2_CTRL_TYPE_BOOLEAN,
739 	.name = "Continuous viewfinder",
740 	.min = 0,
741 	.max = 1,
742 	.step = 1,
743 	.def = 0,
744 };
745 
746 /*
747  * Control for enabling Lock&Unlock Raw Buffer mechanism
748  *
749  * When enabled, Raw Buffer can be locked and unlocked.
750  * Application can hold the exp_id of Raw Buffer
751  * and unlock it when no longer needed.
752  * Note: Make sure set this configuration before creating stream.
753  */
754 static const struct v4l2_ctrl_config ctrl_enable_raw_buffer_lock = {
755 	.id = V4L2_CID_ENABLE_RAW_BUFFER_LOCK,
756 	.type = V4L2_CTRL_TYPE_BOOLEAN,
757 	.name = "Lock Unlock Raw Buffer",
758 	.min = 0,
759 	.max = 1,
760 	.step = 1,
761 	.def = 0,
762 };
763 
764 /*
765  * Control to disable digital zoom of the whole stream
766  *
767  * When it is true, pipe configuration enable_dz will be set to false.
768  * This can help get a better performance by disabling pp binary.
769  *
770  * Note: Make sure set this configuration before creating stream.
771  */
772 static const struct v4l2_ctrl_config ctrl_disable_dz = {
773 	.id = V4L2_CID_DISABLE_DZ,
774 	.type = V4L2_CTRL_TYPE_BOOLEAN,
775 	.name = "Disable digital zoom",
776 	.min = 0,
777 	.max = 1,
778 	.step = 1,
779 	.def = 0,
780 };
781 
atomisp_init_subdev_pipe(struct atomisp_sub_device * asd,struct atomisp_video_pipe * pipe,enum v4l2_buf_type buf_type)782 static int atomisp_init_subdev_pipe(struct atomisp_sub_device *asd,
783 				    struct atomisp_video_pipe *pipe, enum v4l2_buf_type buf_type)
784 {
785 	int ret;
786 
787 	pipe->type = buf_type;
788 	pipe->asd = asd;
789 	pipe->isp = asd->isp;
790 	spin_lock_init(&pipe->irq_lock);
791 	mutex_init(&pipe->vb_queue_mutex);
792 
793 	/* Init videobuf2 queue structure */
794 	pipe->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
795 	pipe->vb_queue.io_modes = VB2_MMAP | VB2_DMABUF;
796 	pipe->vb_queue.buf_struct_size = sizeof(struct ia_css_frame);
797 	pipe->vb_queue.ops = &atomisp_vb2_ops;
798 	pipe->vb_queue.mem_ops = &vb2_vmalloc_memops;
799 	pipe->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
800 	pipe->vb_queue.lock = &pipe->vb_queue_mutex;
801 	ret = vb2_queue_init(&pipe->vb_queue);
802 	if (ret)
803 		return ret;
804 
805 	pipe->vdev.queue = &pipe->vb_queue;
806 
807 	INIT_LIST_HEAD(&pipe->buffers_in_css);
808 	INIT_LIST_HEAD(&pipe->activeq);
809 	INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
810 	INIT_LIST_HEAD(&pipe->per_frame_params);
811 
812 	return 0;
813 }
814 
815 /*
816  * isp_subdev_init_entities - Initialize V4L2 subdev and media entity
817  * @asd: ISP CCDC module
818  *
819  * Return 0 on success and a negative error code on failure.
820  */
isp_subdev_init_entities(struct atomisp_sub_device * asd)821 static int isp_subdev_init_entities(struct atomisp_sub_device *asd)
822 {
823 	struct v4l2_subdev *sd = &asd->subdev;
824 	struct media_pad *pads = asd->pads;
825 	struct media_entity *me = &sd->entity;
826 	int ret;
827 
828 	v4l2_subdev_init(sd, &isp_subdev_v4l2_ops);
829 	sprintf(sd->name, "Atom ISP");
830 	v4l2_set_subdevdata(sd, asd);
831 	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
832 
833 	pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
834 	pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
835 
836 	asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
837 	asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10;
838 
839 	me->ops = &isp_subdev_media_ops;
840 	me->function = MEDIA_ENT_F_PROC_VIDEO_ISP;
841 	ret = media_entity_pads_init(me, ATOMISP_SUBDEV_PADS_NUM, pads);
842 	if (ret < 0)
843 		return ret;
844 
845 	ret = atomisp_init_subdev_pipe(asd, &asd->video_out, V4L2_BUF_TYPE_VIDEO_CAPTURE);
846 	if (ret)
847 		return ret;
848 
849 	ret = atomisp_video_init(&asd->video_out);
850 	if (ret < 0)
851 		return ret;
852 
853 	ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1);
854 	if (ret)
855 		return ret;
856 
857 	asd->run_mode = v4l2_ctrl_new_custom(&asd->ctrl_handler,
858 					     &ctrl_run_mode, NULL);
859 	asd->vfpp = v4l2_ctrl_new_custom(&asd->ctrl_handler,
860 					 &ctrl_vfpp, NULL);
861 	asd->continuous_viewfinder = v4l2_ctrl_new_custom(&asd->ctrl_handler,
862 				     &ctrl_continuous_viewfinder,
863 				     NULL);
864 	asd->continuous_raw_buffer_size =
865 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
866 				 &ctrl_continuous_raw_buffer_size,
867 				 NULL);
868 
869 	asd->enable_raw_buffer_lock =
870 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
871 				 &ctrl_enable_raw_buffer_lock,
872 				 NULL);
873 	asd->disable_dz =
874 	    v4l2_ctrl_new_custom(&asd->ctrl_handler,
875 				 &ctrl_disable_dz,
876 				 NULL);
877 
878 	/* Make controls visible on subdev as well. */
879 	asd->subdev.ctrl_handler = &asd->ctrl_handler;
880 	spin_lock_init(&asd->raw_buffer_bitmap_lock);
881 	return asd->ctrl_handler.error;
882 }
883 
atomisp_subdev_cleanup_entities(struct atomisp_sub_device * asd)884 static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd)
885 {
886 	v4l2_ctrl_handler_free(&asd->ctrl_handler);
887 
888 	media_entity_cleanup(&asd->subdev.entity);
889 }
890 
atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device * asd)891 void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd)
892 {
893 	struct v4l2_fh *fh, *fh_tmp;
894 	struct v4l2_event event;
895 	unsigned int i, pending_event;
896 
897 	list_for_each_entry_safe(fh, fh_tmp,
898 				 &asd->subdev.devnode->fh_list, list) {
899 		pending_event = v4l2_event_pending(fh);
900 		for (i = 0; i < pending_event; i++)
901 			v4l2_event_dequeue(fh, &event, 1);
902 	}
903 }
904 
atomisp_subdev_unregister_entities(struct atomisp_sub_device * asd)905 void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd)
906 {
907 	atomisp_subdev_cleanup_entities(asd);
908 	v4l2_device_unregister_subdev(&asd->subdev);
909 	atomisp_video_unregister(&asd->video_out);
910 }
911 
atomisp_subdev_register_subdev(struct atomisp_sub_device * asd,struct v4l2_device * vdev)912 int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd,
913 				   struct v4l2_device *vdev)
914 {
915 	return v4l2_device_register_subdev(vdev, &asd->subdev);
916 }
917 
918 /*
919  * atomisp_subdev_init - ISP Subdevice  initialization.
920  * @dev: Device pointer specific to the ATOM ISP.
921  *
922  * TODO: Get the initialisation values from platform data.
923  *
924  * Return 0 on success or a negative error code otherwise.
925  */
atomisp_subdev_init(struct atomisp_device * isp)926 int atomisp_subdev_init(struct atomisp_device *isp)
927 {
928 	int ret;
929 
930 	isp->asd.isp = isp;
931 	isp_subdev_init_params(&isp->asd);
932 	ret = isp_subdev_init_entities(&isp->asd);
933 	if (ret < 0)
934 		atomisp_subdev_cleanup_entities(&isp->asd);
935 
936 	return ret;
937 }
938