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