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