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  * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version
11  * 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  *
19  */
20 
21 #include <linux/module.h>
22 #include <linux/pm_runtime.h>
23 
24 #include <media/v4l2-ioctl.h>
25 #include <media/videobuf2-vmalloc.h>
26 
27 #include "atomisp_cmd.h"
28 #include "atomisp_common.h"
29 #include "atomisp_fops.h"
30 #include "atomisp_internal.h"
31 #include "atomisp_ioctl.h"
32 #include "atomisp_compat.h"
33 #include "atomisp_subdev.h"
34 #include "atomisp_v4l2.h"
35 #include "atomisp-regs.h"
36 #include "hmm/hmm.h"
37 
38 #include "ia_css_frame.h"
39 #include "type_support.h"
40 #include "device_access/device_access.h"
41 
42 /*
43  * Videobuf2 ops
44  */
atomisp_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])45 static int atomisp_queue_setup(struct vb2_queue *vq,
46 			       unsigned int *nbuffers, unsigned int *nplanes,
47 			       unsigned int sizes[], struct device *alloc_devs[])
48 {
49 	struct atomisp_video_pipe *pipe = container_of(vq, struct atomisp_video_pipe, vb_queue);
50 	u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev);
51 	int ret;
52 
53 	mutex_lock(&pipe->asd->isp->mutex); /* for get_css_frame_info() / set_fmt() */
54 
55 	/*
56 	 * When VIDIOC_S_FMT has not been called before VIDIOC_REQBUFS, then
57 	 * this will fail. Call atomisp_set_fmt() ourselves and try again.
58 	 */
59 	ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info);
60 	if (ret) {
61 		struct v4l2_format f = {
62 			.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420,
63 			.fmt.pix.width = 10000,
64 			.fmt.pix.height = 10000,
65 		};
66 
67 		ret = atomisp_set_fmt(&pipe->vdev, &f);
68 		if (ret)
69 			goto out;
70 
71 		ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info);
72 		if (ret)
73 			goto out;
74 	}
75 
76 	atomisp_alloc_css_stat_bufs(pipe->asd, ATOMISP_INPUT_STREAM_GENERAL);
77 
78 	*nplanes = 1;
79 	sizes[0] = PAGE_ALIGN(pipe->pix.sizeimage);
80 
81 out:
82 	mutex_unlock(&pipe->asd->isp->mutex);
83 	return ret;
84 }
85 
atomisp_buf_init(struct vb2_buffer * vb)86 static int atomisp_buf_init(struct vb2_buffer *vb)
87 {
88 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
89 	struct ia_css_frame *frame = vb_to_frame(vb);
90 	int ret;
91 
92 	ret = ia_css_frame_init_from_info(frame, &pipe->frame_info);
93 	if (ret)
94 		return ret;
95 
96 	if (frame->data_bytes > vb2_plane_size(vb, 0)) {
97 		dev_err(pipe->asd->isp->dev, "Internal error frame.data_bytes(%u) > vb.length(%lu)\n",
98 			frame->data_bytes, vb2_plane_size(vb, 0));
99 		return -EIO;
100 	}
101 
102 	frame->data = hmm_create_from_vmalloc_buf(vb2_plane_size(vb, 0),
103 						  vb2_plane_vaddr(vb, 0));
104 	if (frame->data == mmgr_NULL)
105 		return -ENOMEM;
106 
107 	return 0;
108 }
109 
atomisp_q_one_metadata_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)110 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd,
111 	enum atomisp_input_stream_id stream_id,
112 	enum ia_css_pipe_id css_pipe_id)
113 {
114 	struct atomisp_metadata_buf *metadata_buf;
115 	enum atomisp_metadata_type md_type =
116 	    atomisp_get_metadata_type(asd, css_pipe_id);
117 	struct list_head *metadata_list;
118 
119 	if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
120 	    ATOMISP_CSS_Q_DEPTH)
121 		return 0; /* we have reached CSS queue depth */
122 
123 	if (!list_empty(&asd->metadata[md_type])) {
124 		metadata_list = &asd->metadata[md_type];
125 	} else if (!list_empty(&asd->metadata_ready[md_type])) {
126 		metadata_list = &asd->metadata_ready[md_type];
127 	} else {
128 		dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n",
129 			 __func__, md_type);
130 		return -EINVAL;
131 	}
132 
133 	metadata_buf = list_entry(metadata_list->next,
134 				  struct atomisp_metadata_buf, list);
135 	list_del_init(&metadata_buf->list);
136 
137 	if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf,
138 					     stream_id, css_pipe_id)) {
139 		list_add(&metadata_buf->list, metadata_list);
140 		return -EINVAL;
141 	} else {
142 		list_add_tail(&metadata_buf->list,
143 			      &asd->metadata_in_css[md_type]);
144 	}
145 	asd->metadata_bufs_in_css[stream_id][css_pipe_id]++;
146 
147 	return 0;
148 }
149 
atomisp_q_one_s3a_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)150 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd,
151 				    enum atomisp_input_stream_id stream_id,
152 				    enum ia_css_pipe_id css_pipe_id)
153 {
154 	struct atomisp_s3a_buf *s3a_buf;
155 	struct list_head *s3a_list;
156 	unsigned int exp_id;
157 
158 	if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH)
159 		return 0; /* we have reached CSS queue depth */
160 
161 	if (!list_empty(&asd->s3a_stats)) {
162 		s3a_list = &asd->s3a_stats;
163 	} else if (!list_empty(&asd->s3a_stats_ready)) {
164 		s3a_list = &asd->s3a_stats_ready;
165 	} else {
166 		dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n",
167 			 __func__);
168 		return -EINVAL;
169 	}
170 
171 	s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list);
172 	list_del_init(&s3a_buf->list);
173 	exp_id = s3a_buf->s3a_data->exp_id;
174 
175 	hmm_flush_vmap(s3a_buf->s3a_data->data_ptr);
176 	if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf,
177 					stream_id, css_pipe_id)) {
178 		/* got from head, so return back to the head */
179 		list_add(&s3a_buf->list, s3a_list);
180 		return -EINVAL;
181 	} else {
182 		list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css);
183 		if (s3a_list == &asd->s3a_stats_ready)
184 			dev_dbg(asd->isp->dev, "drop one s3a stat with exp_id %d\n", exp_id);
185 	}
186 
187 	asd->s3a_bufs_in_css[css_pipe_id]++;
188 	return 0;
189 }
190 
atomisp_q_one_dis_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)191 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd,
192 				    enum atomisp_input_stream_id stream_id,
193 				    enum ia_css_pipe_id css_pipe_id)
194 {
195 	struct atomisp_dis_buf *dis_buf;
196 	unsigned long irqflags;
197 
198 	if (asd->dis_bufs_in_css >=  ATOMISP_CSS_Q_DEPTH)
199 		return 0; /* we have reached CSS queue depth */
200 
201 	spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
202 	if (list_empty(&asd->dis_stats)) {
203 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
204 		dev_warn(asd->isp->dev, "%s: No dis buffers available!\n",
205 			 __func__);
206 		return -EINVAL;
207 	}
208 
209 	dis_buf = list_entry(asd->dis_stats.prev,
210 			     struct atomisp_dis_buf, list);
211 	list_del_init(&dis_buf->list);
212 	spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
213 
214 	hmm_flush_vmap(dis_buf->dis_data->data_ptr);
215 	if (atomisp_q_dis_buffer_to_css(asd, dis_buf,
216 					stream_id, css_pipe_id)) {
217 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
218 		/* got from tail, so return back to the tail */
219 		list_add_tail(&dis_buf->list, &asd->dis_stats);
220 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
221 		return -EINVAL;
222 	} else {
223 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
224 		list_add_tail(&dis_buf->list, &asd->dis_stats_in_css);
225 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
226 	}
227 
228 	asd->dis_bufs_in_css++;
229 
230 	return 0;
231 }
232 
atomisp_q_video_buffers_to_css(struct atomisp_sub_device * asd,struct atomisp_video_pipe * pipe,enum atomisp_input_stream_id stream_id,enum ia_css_buffer_type css_buf_type,enum ia_css_pipe_id css_pipe_id)233 static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
234 					  struct atomisp_video_pipe *pipe,
235 					  enum atomisp_input_stream_id stream_id,
236 					  enum ia_css_buffer_type css_buf_type,
237 					  enum ia_css_pipe_id css_pipe_id)
238 {
239 	struct atomisp_css_params_with_list *param;
240 	struct ia_css_dvs_grid_info *dvs_grid =
241 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
242 	unsigned long irqflags;
243 	int space, err = 0;
244 
245 	lockdep_assert_held(&asd->isp->mutex);
246 
247 	if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM))
248 		return -EINVAL;
249 
250 	if (pipe->stopping)
251 		return -EINVAL;
252 
253 	space = ATOMISP_CSS_Q_DEPTH - atomisp_buffers_in_css(pipe);
254 	while (space--) {
255 		struct ia_css_frame *frame;
256 
257 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
258 		frame = list_first_entry_or_null(&pipe->activeq, struct ia_css_frame, queue);
259 		if (frame)
260 			list_move_tail(&frame->queue, &pipe->buffers_in_css);
261 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
262 
263 		if (!frame)
264 			return -EINVAL;
265 
266 		/*
267 		 * If there is a per_frame setting to apply on the buffer,
268 		 * do it before buffer en-queueing.
269 		 */
270 		param = pipe->frame_params[frame->vb.vb2_buf.index];
271 		if (param) {
272 			atomisp_makeup_css_parameters(asd,
273 						      &asd->params.css_param.update_flag,
274 						      &param->params);
275 			atomisp_apply_css_parameters(asd, &param->params);
276 
277 			if (param->params.update_flag.dz_config &&
278 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
279 				err = atomisp_calculate_real_zoom_region(asd,
280 					&param->params.dz_config, css_pipe_id);
281 				if (!err)
282 					asd->params.config.dz_config = &param->params.dz_config;
283 			}
284 			atomisp_css_set_isp_config_applied_frame(asd, frame);
285 			atomisp_css_update_isp_params_on_pipe(asd,
286 							      asd->stream_env[stream_id].pipes[css_pipe_id]);
287 			asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *)
288 						param->params.dvs_6axis;
289 
290 			/*
291 			 * WORKAROUND:
292 			 * Because the camera halv3 can't ensure to set zoom
293 			 * region to per_frame setting and global setting at
294 			 * same time and only set zoom region to pre_frame
295 			 * setting now.so when the pre_frame setting include
296 			 * zoom region,I will set it to global setting.
297 			 */
298 			if (param->params.update_flag.dz_config &&
299 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
300 			    && !err) {
301 				memcpy(&asd->params.css_param.dz_config,
302 				       &param->params.dz_config,
303 				       sizeof(struct ia_css_dz_config));
304 				asd->params.css_param.update_flag.dz_config =
305 				    (struct atomisp_dz_config *)
306 				    &asd->params.css_param.dz_config;
307 				asd->params.css_update_params_needed = true;
308 			}
309 			pipe->frame_params[frame->vb.vb2_buf.index] = NULL;
310 		}
311 		/* Enqueue buffer */
312 		err = atomisp_q_video_buffer_to_css(asd, frame, stream_id,
313 						    css_buf_type, css_pipe_id);
314 		if (err) {
315 			spin_lock_irqsave(&pipe->irq_lock, irqflags);
316 			list_move_tail(&frame->queue, &pipe->activeq);
317 			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
318 			dev_err(asd->isp->dev, "%s, css q fails: %d\n",
319 				__func__, err);
320 			return -EINVAL;
321 		}
322 
323 		/* enqueue 3A/DIS/metadata buffers */
324 		if (asd->params.curr_grid_info.s3a_grid.enable &&
325 		    css_pipe_id == asd->params.s3a_enabled_pipe &&
326 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
327 			atomisp_q_one_s3a_buffer(asd, stream_id,
328 						 css_pipe_id);
329 
330 		if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
331 		    metadata_info.size &&
332 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
333 			atomisp_q_one_metadata_buffer(asd, stream_id,
334 						      css_pipe_id);
335 
336 		if (dvs_grid && dvs_grid->enable &&
337 		    css_pipe_id == IA_CSS_PIPE_ID_VIDEO &&
338 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
339 			atomisp_q_one_dis_buffer(asd, stream_id,
340 						 css_pipe_id);
341 	}
342 
343 	return 0;
344 }
345 
atomisp_get_css_buf_type(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id,uint16_t source_pad)346 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
347 				    enum ia_css_pipe_id pipe_id,
348 				    uint16_t source_pad)
349 {
350 	if (ATOMISP_USE_YUVPP(asd)) {
351 		/* when run ZSL case */
352 		if (asd->continuous_mode->val &&
353 		    asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
354 			if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
355 				return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
356 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
357 				return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
358 			else
359 				return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
360 		}
361 
362 		/*when run SDV case*/
363 		if (asd->continuous_mode->val &&
364 		    asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
365 			if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
366 				return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
367 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
368 				return IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME;
369 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
370 				return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
371 			else
372 				return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
373 		}
374 
375 		/*other case: default setting*/
376 		if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
377 		    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
378 		    (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
379 		     asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
380 			return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
381 		else
382 			return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
383 	}
384 
385 	if (pipe_id == IA_CSS_PIPE_ID_COPY ||
386 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
387 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
388 	    (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
389 	     asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
390 		return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
391 	else
392 		return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
393 }
394 
395 /* queue all available buffers to css */
atomisp_qbuffers_to_css(struct atomisp_sub_device * asd)396 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
397 {
398 	enum ia_css_buffer_type buf_type;
399 	enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM;
400 	enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM;
401 	enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM;
402 	enum atomisp_input_stream_id input_stream_id;
403 	struct atomisp_video_pipe *capture_pipe = NULL;
404 	struct atomisp_video_pipe *vf_pipe = NULL;
405 	struct atomisp_video_pipe *preview_pipe = NULL;
406 	struct atomisp_video_pipe *video_pipe = NULL;
407 	bool raw_mode = atomisp_is_mbuscode_raw(
408 			    asd->fmt[asd->capture_pad].fmt.code);
409 
410 	if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
411 		video_pipe = &asd->video_out_video_capture;
412 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
413 	} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
414 		preview_pipe = &asd->video_out_capture;
415 		css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
416 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
417 		if (asd->continuous_mode->val) {
418 			capture_pipe = &asd->video_out_capture;
419 			vf_pipe = &asd->video_out_vf;
420 			css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
421 		}
422 		video_pipe = &asd->video_out_video_capture;
423 		preview_pipe = &asd->video_out_preview;
424 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
425 		css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
426 	} else if (asd->continuous_mode->val) {
427 		capture_pipe = &asd->video_out_capture;
428 		vf_pipe = &asd->video_out_vf;
429 		preview_pipe = &asd->video_out_preview;
430 
431 		css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
432 		css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
433 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
434 		preview_pipe = &asd->video_out_preview;
435 		css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
436 	} else {
437 		/* ATOMISP_RUN_MODE_STILL_CAPTURE */
438 		capture_pipe = &asd->video_out_capture;
439 		if (!raw_mode)
440 			vf_pipe = &asd->video_out_vf;
441 		css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
442 	}
443 
444 	if (IS_ISP2401 && asd->copy_mode) {
445 		css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
446 		css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
447 		css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
448 	}
449 
450 	if (asd->yuvpp_mode) {
451 		capture_pipe = &asd->video_out_capture;
452 		video_pipe   = &asd->video_out_video_capture;
453 		preview_pipe = &asd->video_out_preview;
454 		css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
455 		css_video_pipe_id   = IA_CSS_PIPE_ID_YUVPP;
456 		css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
457 	}
458 
459 	if (capture_pipe) {
460 		buf_type = atomisp_get_css_buf_type(
461 			       asd, css_capture_pipe_id,
462 			       atomisp_subdev_source_pad(&capture_pipe->vdev));
463 		input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
464 
465 		/*
466 		 * use yuvpp pipe for SOC camera.
467 		 */
468 		if (ATOMISP_USE_YUVPP(asd))
469 			css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
470 
471 		atomisp_q_video_buffers_to_css(asd, capture_pipe,
472 					       input_stream_id,
473 					       buf_type, css_capture_pipe_id);
474 	}
475 
476 	if (vf_pipe) {
477 		buf_type = atomisp_get_css_buf_type(
478 			       asd, css_capture_pipe_id,
479 			       atomisp_subdev_source_pad(&vf_pipe->vdev));
480 		if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
481 			input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
482 		else
483 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
484 
485 		/*
486 		 * use yuvpp pipe for SOC camera.
487 		 */
488 		if (ATOMISP_USE_YUVPP(asd))
489 			css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
490 		atomisp_q_video_buffers_to_css(asd, vf_pipe,
491 					       input_stream_id,
492 					       buf_type, css_capture_pipe_id);
493 	}
494 
495 	if (preview_pipe) {
496 		buf_type = atomisp_get_css_buf_type(
497 			       asd, css_preview_pipe_id,
498 			       atomisp_subdev_source_pad(&preview_pipe->vdev));
499 		if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
500 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
501 		/* else for ext isp use case */
502 		else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
503 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
504 		else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
505 			input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
506 		else
507 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
508 
509 		/*
510 		 * use yuvpp pipe for SOC camera.
511 		 */
512 		if (ATOMISP_USE_YUVPP(asd))
513 			css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
514 
515 		atomisp_q_video_buffers_to_css(asd, preview_pipe,
516 					       input_stream_id,
517 					       buf_type, css_preview_pipe_id);
518 	}
519 
520 	if (video_pipe) {
521 		buf_type = atomisp_get_css_buf_type(
522 			       asd, css_video_pipe_id,
523 			       atomisp_subdev_source_pad(&video_pipe->vdev));
524 		if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
525 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
526 		else
527 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
528 
529 		/*
530 		 * use yuvpp pipe for SOC camera.
531 		 */
532 		if (ATOMISP_USE_YUVPP(asd))
533 			css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
534 
535 		atomisp_q_video_buffers_to_css(asd, video_pipe,
536 					       input_stream_id,
537 					       buf_type, css_video_pipe_id);
538 	}
539 
540 	return 0;
541 }
542 
atomisp_buf_queue(struct vb2_buffer * vb)543 static void atomisp_buf_queue(struct vb2_buffer *vb)
544 {
545 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
546 	struct ia_css_frame *frame = vb_to_frame(vb);
547 	struct atomisp_sub_device *asd = pipe->asd;
548 	u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev);
549 	unsigned long irqflags;
550 	int ret;
551 
552 	mutex_lock(&asd->isp->mutex);
553 
554 	ret = atomisp_pipe_check(pipe, false);
555 	if (ret || pipe->stopping) {
556 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
557 		atomisp_buffer_done(frame, VB2_BUF_STATE_ERROR);
558 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
559 		goto out_unlock;
560 	}
561 
562 	/* FIXME this ugliness comes from the original atomisp buffer handling */
563 	if (!(vb->skip_cache_sync_on_finish && vb->skip_cache_sync_on_prepare))
564 		wbinvd();
565 
566 	pipe->frame_params[vb->index] = NULL;
567 
568 	spin_lock_irqsave(&pipe->irq_lock, irqflags);
569 	/*
570 	 * when a frame buffer meets following conditions, it should be put into
571 	 * the waiting list:
572 	 * 1.  It is not a main output frame, and it has a per-frame parameter
573 	 *     to go with it.
574 	 * 2.  It is not a main output frame, and the waiting buffer list is not
575 	 *     empty, to keep the FIFO sequence of frame buffer processing, it
576 	 *     is put to waiting list until previous per-frame parameter buffers
577 	 *     get enqueued.
578 	 */
579 	if (!atomisp_is_vf_pipe(pipe) &&
580 	    (pipe->frame_request_config_id[vb->index] ||
581 	     !list_empty(&pipe->buffers_waiting_for_param)))
582 		list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param);
583 	else
584 		list_add_tail(&frame->queue, &pipe->activeq);
585 
586 	spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
587 
588 	/* TODO: do this better, not best way to queue to css */
589 	if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
590 		if (!list_empty(&pipe->buffers_waiting_for_param))
591 			atomisp_handle_parameter_and_buffer(pipe);
592 		else
593 			atomisp_qbuffers_to_css(asd);
594 	}
595 
596 	/*
597 	 * Workaround: Due to the design of HALv3,
598 	 * sometimes in ZSL or SDV mode HAL needs to
599 	 * capture multiple images within one streaming cycle.
600 	 * But the capture number cannot be determined by HAL.
601 	 * So HAL only sets the capture number to be 1 and queue multiple
602 	 * buffers. Atomisp driver needs to check this case and re-trigger
603 	 * CSS to do capture when new buffer is queued.
604 	 */
605 	if (asd->continuous_mode->val && source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
606 	    !asd->enable_raw_buffer_lock->val && asd->params.offline_parm.num_captures == 1) {
607 		asd->pending_capture_request++;
608 		dev_dbg(asd->isp->dev, "Add one pending capture request.\n");
609 	}
610 
611 out_unlock:
612 	mutex_unlock(&asd->isp->mutex);
613 }
614 
atomisp_buf_cleanup(struct vb2_buffer * vb)615 static void atomisp_buf_cleanup(struct vb2_buffer *vb)
616 {
617 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
618 	struct ia_css_frame *frame = vb_to_frame(vb);
619 	int index = frame->vb.vb2_buf.index;
620 
621 	pipe->frame_request_config_id[index] = 0;
622 	pipe->frame_params[index] = NULL;
623 
624 	hmm_free(frame->data);
625 }
626 
627 const struct vb2_ops atomisp_vb2_ops = {
628 	.queue_setup		= atomisp_queue_setup,
629 	.buf_init		= atomisp_buf_init,
630 	.buf_cleanup		= atomisp_buf_cleanup,
631 	.buf_queue		= atomisp_buf_queue,
632 	.start_streaming	= atomisp_start_streaming,
633 	.stop_streaming		= atomisp_stop_streaming,
634 };
635 
atomisp_dev_init_struct(struct atomisp_device * isp)636 static void atomisp_dev_init_struct(struct atomisp_device *isp)
637 {
638 	unsigned int i;
639 
640 	isp->need_gfx_throttle = true;
641 	isp->isp_fatal_error = false;
642 	isp->mipi_frame_size = 0;
643 
644 	for (i = 0; i < isp->input_cnt; i++)
645 		isp->inputs[i].asd = NULL;
646 	/*
647 	 * For Merrifield, frequency is scalable.
648 	 * After boot-up, the default frequency is 200MHz.
649 	 */
650 	isp->running_freq = ISP_FREQ_200MHZ;
651 }
652 
atomisp_subdev_init_struct(struct atomisp_sub_device * asd)653 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
654 {
655 	v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
656 	memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
657 	asd->params.color_effect = V4L2_COLORFX_NONE;
658 	asd->params.bad_pixel_en = true;
659 	asd->params.gdc_cac_en = false;
660 	asd->params.video_dis_en = false;
661 	asd->params.sc_en = false;
662 	asd->params.fpn_en = false;
663 	asd->params.xnr_en = false;
664 	asd->params.false_color = 0;
665 	asd->params.online_process = 1;
666 	asd->params.yuv_ds_en = 0;
667 	/* s3a grid not enabled for any pipe */
668 	asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
669 
670 	asd->params.offline_parm.num_captures = 1;
671 	asd->params.offline_parm.skip_frames = 0;
672 	asd->params.offline_parm.offset = 0;
673 	asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
674 	/* Add for channel */
675 	asd->input_curr = 0;
676 
677 	asd->mipi_frame_size = 0;
678 	asd->copy_mode = false;
679 	asd->yuvpp_mode = false;
680 
681 	asd->stream_prepared = false;
682 	asd->high_speed_mode = false;
683 	asd->sensor_array_res.height = 0;
684 	asd->sensor_array_res.width = 0;
685 	atomisp_css_init_struct(asd);
686 }
687 
688 /*
689  * file operation functions
690  */
atomisp_subdev_users(struct atomisp_sub_device * asd)691 static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
692 {
693 	return asd->video_out_preview.users +
694 	       asd->video_out_vf.users +
695 	       asd->video_out_capture.users +
696 	       asd->video_out_video_capture.users;
697 }
698 
atomisp_dev_users(struct atomisp_device * isp)699 unsigned int atomisp_dev_users(struct atomisp_device *isp)
700 {
701 	unsigned int i, sum;
702 
703 	for (i = 0, sum = 0; i < isp->num_of_streams; i++)
704 		sum += atomisp_subdev_users(&isp->asd[i]);
705 
706 	return sum;
707 }
708 
atomisp_open(struct file * file)709 static int atomisp_open(struct file *file)
710 {
711 	struct video_device *vdev = video_devdata(file);
712 	struct atomisp_device *isp = video_get_drvdata(vdev);
713 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
714 	struct atomisp_sub_device *asd = pipe->asd;
715 	int ret;
716 
717 	dev_dbg(isp->dev, "open device %s\n", vdev->name);
718 
719 	ret = v4l2_fh_open(file);
720 	if (ret)
721 		return ret;
722 
723 	mutex_lock(&isp->mutex);
724 
725 	asd->subdev.devnode = vdev;
726 
727 	if (!isp->input_cnt) {
728 		dev_err(isp->dev, "no camera attached\n");
729 		ret = -EINVAL;
730 		goto error;
731 	}
732 
733 	/*
734 	 * atomisp does not allow multiple open
735 	 */
736 	if (pipe->users) {
737 		dev_dbg(isp->dev, "video node already opened\n");
738 		mutex_unlock(&isp->mutex);
739 		return -EBUSY;
740 	}
741 
742 	if (atomisp_dev_users(isp)) {
743 		dev_dbg(isp->dev, "skip init isp in open\n");
744 		goto init_subdev;
745 	}
746 
747 	/* runtime power management, turn on ISP */
748 	ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
749 	if (ret < 0) {
750 		dev_err(isp->dev, "Failed to power on device\n");
751 		goto error;
752 	}
753 
754 	atomisp_dev_init_struct(isp);
755 
756 	ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
757 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
758 		dev_err(isp->dev, "Failed to power-on flash\n");
759 		goto css_error;
760 	}
761 
762 init_subdev:
763 	if (atomisp_subdev_users(asd))
764 		goto done;
765 
766 	atomisp_subdev_init_struct(asd);
767 	/* Ensure that a mode is set */
768 	v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode);
769 
770 done:
771 	pipe->users++;
772 	mutex_unlock(&isp->mutex);
773 
774 
775 	return 0;
776 
777 css_error:
778 	pm_runtime_put(vdev->v4l2_dev->dev);
779 error:
780 	mutex_unlock(&isp->mutex);
781 	v4l2_fh_release(file);
782 	return ret;
783 }
784 
atomisp_release(struct file * file)785 static int atomisp_release(struct file *file)
786 {
787 	struct video_device *vdev = video_devdata(file);
788 	struct atomisp_device *isp = video_get_drvdata(vdev);
789 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
790 	struct atomisp_sub_device *asd = pipe->asd;
791 	struct v4l2_subdev_fh fh;
792 	struct v4l2_rect clear_compose = {0};
793 	unsigned long flags;
794 	int ret;
795 
796 	v4l2_fh_init(&fh.vfh, vdev);
797 
798 	dev_dbg(isp->dev, "release device %s\n", vdev->name);
799 
800 	asd->subdev.devnode = vdev;
801 
802 	/* Note file must not be used after this! */
803 	vb2_fop_release(file);
804 
805 	mutex_lock(&isp->mutex);
806 
807 	pipe->users--;
808 	if (pipe->users)
809 		goto done;
810 
811 	/*
812 	 * A little trick here:
813 	 * file injection input resolution is recorded in the sink pad,
814 	 * therefore can not be cleared when releaseing one device node.
815 	 * The sink pad setting can only be cleared when all device nodes
816 	 * get released.
817 	 */
818 	if (asd->fmt_auto->val) {
819 		struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
820 
821 		atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
822 					V4L2_SUBDEV_FORMAT_ACTIVE,
823 					ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
824 	}
825 
826 	if (atomisp_subdev_users(asd))
827 		goto done;
828 
829 	atomisp_css_free_stat_buffers(asd);
830 	atomisp_free_internal_buffers(asd);
831 
832 	if (isp->inputs[asd->input_curr].asd == asd) {
833 		ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
834 				       core, s_power, 0);
835 		if (ret && ret != -ENOIOCTLCMD)
836 			dev_warn(isp->dev, "Failed to power-off sensor\n");
837 
838 		/* clear the asd field to show this camera is not used */
839 		isp->inputs[asd->input_curr].asd = NULL;
840 	}
841 
842 	spin_lock_irqsave(&isp->lock, flags);
843 	asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
844 	spin_unlock_irqrestore(&isp->lock, flags);
845 
846 	if (atomisp_dev_users(isp))
847 		goto done;
848 
849 	atomisp_destroy_pipes_stream_force(asd);
850 
851 	ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
852 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
853 		dev_warn(isp->dev, "Failed to power-off flash\n");
854 
855 	if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
856 		dev_err(isp->dev, "Failed to power off device\n");
857 
858 done:
859 	atomisp_subdev_set_selection(&asd->subdev, fh.state,
860 				     V4L2_SUBDEV_FORMAT_ACTIVE,
861 				     atomisp_subdev_source_pad(vdev),
862 				     V4L2_SEL_TGT_COMPOSE, 0,
863 				     &clear_compose);
864 	mutex_unlock(&isp->mutex);
865 	return 0;
866 }
867 
868 const struct v4l2_file_operations atomisp_fops = {
869 	.owner = THIS_MODULE,
870 	.open = atomisp_open,
871 	.release = atomisp_release,
872 	.mmap = vb2_fop_mmap,
873 	.poll = vb2_fop_poll,
874 	.unlocked_ioctl = video_ioctl2,
875 #ifdef CONFIG_COMPAT
876 	/*
877 	 * this was removed because of bugs, the interface
878 	 * needs to be made safe for compat tasks instead.
879 	.compat_ioctl32 = atomisp_compat_ioctl32,
880 	 */
881 #endif
882 };
883