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  */
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 
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 
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 = ATOMISP_MAIN_METADATA;
116 	struct list_head *metadata_list;
117 
118 	if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
119 	    ATOMISP_CSS_Q_DEPTH)
120 		return 0; /* we have reached CSS queue depth */
121 
122 	if (!list_empty(&asd->metadata[md_type])) {
123 		metadata_list = &asd->metadata[md_type];
124 	} else if (!list_empty(&asd->metadata_ready[md_type])) {
125 		metadata_list = &asd->metadata_ready[md_type];
126 	} else {
127 		dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n",
128 			 __func__, md_type);
129 		return -EINVAL;
130 	}
131 
132 	metadata_buf = list_entry(metadata_list->next,
133 				  struct atomisp_metadata_buf, list);
134 	list_del_init(&metadata_buf->list);
135 
136 	if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf,
137 					     stream_id, css_pipe_id)) {
138 		list_add(&metadata_buf->list, metadata_list);
139 		return -EINVAL;
140 	} else {
141 		list_add_tail(&metadata_buf->list,
142 			      &asd->metadata_in_css[md_type]);
143 	}
144 	asd->metadata_bufs_in_css[stream_id][css_pipe_id]++;
145 
146 	return 0;
147 }
148 
149 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd,
150 				    enum atomisp_input_stream_id stream_id,
151 				    enum ia_css_pipe_id css_pipe_id)
152 {
153 	struct atomisp_s3a_buf *s3a_buf;
154 	struct list_head *s3a_list;
155 	unsigned int exp_id;
156 
157 	if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH)
158 		return 0; /* we have reached CSS queue depth */
159 
160 	if (!list_empty(&asd->s3a_stats)) {
161 		s3a_list = &asd->s3a_stats;
162 	} else if (!list_empty(&asd->s3a_stats_ready)) {
163 		s3a_list = &asd->s3a_stats_ready;
164 	} else {
165 		dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n",
166 			 __func__);
167 		return -EINVAL;
168 	}
169 
170 	s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list);
171 	list_del_init(&s3a_buf->list);
172 	exp_id = s3a_buf->s3a_data->exp_id;
173 
174 	hmm_flush_vmap(s3a_buf->s3a_data->data_ptr);
175 	if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf,
176 					stream_id, css_pipe_id)) {
177 		/* got from head, so return back to the head */
178 		list_add(&s3a_buf->list, s3a_list);
179 		return -EINVAL;
180 	} else {
181 		list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css);
182 		if (s3a_list == &asd->s3a_stats_ready)
183 			dev_dbg(asd->isp->dev, "drop one s3a stat with exp_id %d\n", exp_id);
184 	}
185 
186 	asd->s3a_bufs_in_css[css_pipe_id]++;
187 	return 0;
188 }
189 
190 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd,
191 				    enum atomisp_input_stream_id stream_id,
192 				    enum ia_css_pipe_id css_pipe_id)
193 {
194 	struct atomisp_dis_buf *dis_buf;
195 	unsigned long irqflags;
196 
197 	if (asd->dis_bufs_in_css >=  ATOMISP_CSS_Q_DEPTH)
198 		return 0; /* we have reached CSS queue depth */
199 
200 	spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
201 	if (list_empty(&asd->dis_stats)) {
202 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
203 		dev_warn(asd->isp->dev, "%s: No dis buffers available!\n",
204 			 __func__);
205 		return -EINVAL;
206 	}
207 
208 	dis_buf = list_entry(asd->dis_stats.prev,
209 			     struct atomisp_dis_buf, list);
210 	list_del_init(&dis_buf->list);
211 	spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
212 
213 	hmm_flush_vmap(dis_buf->dis_data->data_ptr);
214 	if (atomisp_q_dis_buffer_to_css(asd, dis_buf,
215 					stream_id, css_pipe_id)) {
216 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
217 		/* got from tail, so return back to the tail */
218 		list_add_tail(&dis_buf->list, &asd->dis_stats);
219 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
220 		return -EINVAL;
221 	} else {
222 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
223 		list_add_tail(&dis_buf->list, &asd->dis_stats_in_css);
224 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
225 	}
226 
227 	asd->dis_bufs_in_css++;
228 
229 	return 0;
230 }
231 
232 static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
233 					  struct atomisp_video_pipe *pipe,
234 					  enum atomisp_input_stream_id stream_id,
235 					  enum ia_css_buffer_type css_buf_type,
236 					  enum ia_css_pipe_id css_pipe_id)
237 {
238 	struct atomisp_css_params_with_list *param;
239 	struct ia_css_dvs_grid_info *dvs_grid =
240 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
241 	unsigned long irqflags;
242 	int space, err = 0;
243 
244 	lockdep_assert_held(&asd->isp->mutex);
245 
246 	if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM))
247 		return -EINVAL;
248 
249 	if (pipe->stopping)
250 		return -EINVAL;
251 
252 	space = ATOMISP_CSS_Q_DEPTH - atomisp_buffers_in_css(pipe);
253 	while (space--) {
254 		struct ia_css_frame *frame;
255 
256 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
257 		frame = list_first_entry_or_null(&pipe->activeq, struct ia_css_frame, queue);
258 		if (frame)
259 			list_move_tail(&frame->queue, &pipe->buffers_in_css);
260 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
261 
262 		if (!frame)
263 			return -EINVAL;
264 
265 		/*
266 		 * If there is a per_frame setting to apply on the buffer,
267 		 * do it before buffer en-queueing.
268 		 */
269 		param = pipe->frame_params[frame->vb.vb2_buf.index];
270 		if (param) {
271 			atomisp_makeup_css_parameters(asd,
272 						      &asd->params.css_param.update_flag,
273 						      &param->params);
274 			atomisp_apply_css_parameters(asd, &param->params);
275 
276 			if (param->params.update_flag.dz_config &&
277 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
278 				err = atomisp_calculate_real_zoom_region(asd,
279 					&param->params.dz_config, css_pipe_id);
280 				if (!err)
281 					asd->params.config.dz_config = &param->params.dz_config;
282 			}
283 			atomisp_css_set_isp_config_applied_frame(asd, frame);
284 			atomisp_css_update_isp_params_on_pipe(asd,
285 							      asd->stream_env[stream_id].pipes[css_pipe_id]);
286 			asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *)
287 						param->params.dvs_6axis;
288 
289 			/*
290 			 * WORKAROUND:
291 			 * Because the camera halv3 can't ensure to set zoom
292 			 * region to per_frame setting and global setting at
293 			 * same time and only set zoom region to pre_frame
294 			 * setting now.so when the pre_frame setting include
295 			 * zoom region,I will set it to global setting.
296 			 */
297 			if (param->params.update_flag.dz_config &&
298 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
299 			    && !err) {
300 				memcpy(&asd->params.css_param.dz_config,
301 				       &param->params.dz_config,
302 				       sizeof(struct ia_css_dz_config));
303 				asd->params.css_param.update_flag.dz_config =
304 				    (struct atomisp_dz_config *)
305 				    &asd->params.css_param.dz_config;
306 				asd->params.css_update_params_needed = true;
307 			}
308 			pipe->frame_params[frame->vb.vb2_buf.index] = NULL;
309 		}
310 		/* Enqueue buffer */
311 		err = atomisp_q_video_buffer_to_css(asd, frame, stream_id,
312 						    css_buf_type, css_pipe_id);
313 		if (err) {
314 			spin_lock_irqsave(&pipe->irq_lock, irqflags);
315 			list_move_tail(&frame->queue, &pipe->activeq);
316 			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
317 			dev_err(asd->isp->dev, "%s, css q fails: %d\n",
318 				__func__, err);
319 			return -EINVAL;
320 		}
321 
322 		/* enqueue 3A/DIS/metadata buffers */
323 		if (asd->params.curr_grid_info.s3a_grid.enable &&
324 		    css_pipe_id == asd->params.s3a_enabled_pipe &&
325 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
326 			atomisp_q_one_s3a_buffer(asd, stream_id,
327 						 css_pipe_id);
328 
329 		if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
330 		    metadata_info.size &&
331 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
332 			atomisp_q_one_metadata_buffer(asd, stream_id,
333 						      css_pipe_id);
334 
335 		if (dvs_grid && dvs_grid->enable &&
336 		    css_pipe_id == IA_CSS_PIPE_ID_VIDEO &&
337 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
338 			atomisp_q_one_dis_buffer(asd, stream_id,
339 						 css_pipe_id);
340 	}
341 
342 	return 0;
343 }
344 
345 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
346 				    enum ia_css_pipe_id pipe_id,
347 				    uint16_t source_pad)
348 {
349 	if (pipe_id == IA_CSS_PIPE_ID_COPY ||
350 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
351 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
352 	    (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
353 	     asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
354 		return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
355 	else
356 		return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
357 }
358 
359 /* queue all available buffers to css */
360 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
361 {
362 	enum ia_css_buffer_type buf_type;
363 	enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM;
364 	enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM;
365 	enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM;
366 	enum atomisp_input_stream_id input_stream_id;
367 	struct atomisp_video_pipe *capture_pipe = NULL;
368 	struct atomisp_video_pipe *vf_pipe = NULL;
369 	struct atomisp_video_pipe *preview_pipe = NULL;
370 	struct atomisp_video_pipe *video_pipe = NULL;
371 	bool raw_mode = atomisp_is_mbuscode_raw(
372 			    asd->fmt[asd->capture_pad].fmt.code);
373 
374 	if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
375 		video_pipe = &asd->video_out_video_capture;
376 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
377 	} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
378 		preview_pipe = &asd->video_out_capture;
379 		css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
380 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
381 		video_pipe = &asd->video_out_video_capture;
382 		preview_pipe = &asd->video_out_preview;
383 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
384 		css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
385 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
386 		preview_pipe = &asd->video_out_preview;
387 		css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
388 	} else {
389 		/* ATOMISP_RUN_MODE_STILL_CAPTURE */
390 		capture_pipe = &asd->video_out_capture;
391 		if (!raw_mode)
392 			vf_pipe = &asd->video_out_vf;
393 		css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
394 	}
395 
396 	if (IS_ISP2401 && asd->copy_mode) {
397 		css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
398 		css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
399 		css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
400 	}
401 
402 	if (capture_pipe) {
403 		buf_type = atomisp_get_css_buf_type(
404 			       asd, css_capture_pipe_id,
405 			       atomisp_subdev_source_pad(&capture_pipe->vdev));
406 		input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
407 
408 		atomisp_q_video_buffers_to_css(asd, capture_pipe,
409 					       input_stream_id,
410 					       buf_type, css_capture_pipe_id);
411 	}
412 
413 	if (vf_pipe) {
414 		buf_type = atomisp_get_css_buf_type(
415 			       asd, css_capture_pipe_id,
416 			       atomisp_subdev_source_pad(&vf_pipe->vdev));
417 		if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
418 			input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
419 		else
420 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
421 
422 		atomisp_q_video_buffers_to_css(asd, vf_pipe,
423 					       input_stream_id,
424 					       buf_type, css_capture_pipe_id);
425 	}
426 
427 	if (preview_pipe) {
428 		buf_type = atomisp_get_css_buf_type(
429 			       asd, css_preview_pipe_id,
430 			       atomisp_subdev_source_pad(&preview_pipe->vdev));
431 
432 		if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
433 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
434 		else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
435 			input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
436 		else
437 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
438 
439 		atomisp_q_video_buffers_to_css(asd, preview_pipe,
440 					       input_stream_id,
441 					       buf_type, css_preview_pipe_id);
442 	}
443 
444 	if (video_pipe) {
445 		buf_type = atomisp_get_css_buf_type(
446 			       asd, css_video_pipe_id,
447 			       atomisp_subdev_source_pad(&video_pipe->vdev));
448 		if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
449 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
450 		else
451 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
452 
453 		atomisp_q_video_buffers_to_css(asd, video_pipe,
454 					       input_stream_id,
455 					       buf_type, css_video_pipe_id);
456 	}
457 
458 	return 0;
459 }
460 
461 static void atomisp_buf_queue(struct vb2_buffer *vb)
462 {
463 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
464 	struct ia_css_frame *frame = vb_to_frame(vb);
465 	struct atomisp_sub_device *asd = pipe->asd;
466 	unsigned long irqflags;
467 	int ret;
468 
469 	mutex_lock(&asd->isp->mutex);
470 
471 	ret = atomisp_pipe_check(pipe, false);
472 	if (ret || pipe->stopping) {
473 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
474 		atomisp_buffer_done(frame, VB2_BUF_STATE_ERROR);
475 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
476 		goto out_unlock;
477 	}
478 
479 	/* FIXME this ugliness comes from the original atomisp buffer handling */
480 	if (!(vb->skip_cache_sync_on_finish && vb->skip_cache_sync_on_prepare))
481 		wbinvd();
482 
483 	pipe->frame_params[vb->index] = NULL;
484 
485 	spin_lock_irqsave(&pipe->irq_lock, irqflags);
486 	/*
487 	 * when a frame buffer meets following conditions, it should be put into
488 	 * the waiting list:
489 	 * 1.  It is not a main output frame, and it has a per-frame parameter
490 	 *     to go with it.
491 	 * 2.  It is not a main output frame, and the waiting buffer list is not
492 	 *     empty, to keep the FIFO sequence of frame buffer processing, it
493 	 *     is put to waiting list until previous per-frame parameter buffers
494 	 *     get enqueued.
495 	 */
496 	if (!atomisp_is_vf_pipe(pipe) &&
497 	    (pipe->frame_request_config_id[vb->index] ||
498 	     !list_empty(&pipe->buffers_waiting_for_param)))
499 		list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param);
500 	else
501 		list_add_tail(&frame->queue, &pipe->activeq);
502 
503 	spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
504 
505 	/* TODO: do this better, not best way to queue to css */
506 	if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
507 		if (!list_empty(&pipe->buffers_waiting_for_param))
508 			atomisp_handle_parameter_and_buffer(pipe);
509 		else
510 			atomisp_qbuffers_to_css(asd);
511 	}
512 
513 out_unlock:
514 	mutex_unlock(&asd->isp->mutex);
515 }
516 
517 static void atomisp_buf_cleanup(struct vb2_buffer *vb)
518 {
519 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
520 	struct ia_css_frame *frame = vb_to_frame(vb);
521 	int index = frame->vb.vb2_buf.index;
522 
523 	pipe->frame_request_config_id[index] = 0;
524 	pipe->frame_params[index] = NULL;
525 
526 	hmm_free(frame->data);
527 }
528 
529 const struct vb2_ops atomisp_vb2_ops = {
530 	.queue_setup		= atomisp_queue_setup,
531 	.buf_init		= atomisp_buf_init,
532 	.buf_cleanup		= atomisp_buf_cleanup,
533 	.buf_queue		= atomisp_buf_queue,
534 	.start_streaming	= atomisp_start_streaming,
535 	.stop_streaming		= atomisp_stop_streaming,
536 };
537 
538 static void atomisp_dev_init_struct(struct atomisp_device *isp)
539 {
540 	unsigned int i;
541 
542 	isp->need_gfx_throttle = true;
543 	isp->isp_fatal_error = false;
544 	isp->mipi_frame_size = 0;
545 
546 	for (i = 0; i < isp->input_cnt; i++)
547 		isp->inputs[i].asd = NULL;
548 	/*
549 	 * For Merrifield, frequency is scalable.
550 	 * After boot-up, the default frequency is 200MHz.
551 	 */
552 	isp->running_freq = ISP_FREQ_200MHZ;
553 }
554 
555 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
556 {
557 	v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
558 	memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
559 	asd->params.color_effect = V4L2_COLORFX_NONE;
560 	asd->params.bad_pixel_en = true;
561 	asd->params.gdc_cac_en = false;
562 	asd->params.video_dis_en = false;
563 	asd->params.sc_en = false;
564 	asd->params.fpn_en = false;
565 	asd->params.xnr_en = false;
566 	asd->params.false_color = 0;
567 	asd->params.yuv_ds_en = 0;
568 	/* s3a grid not enabled for any pipe */
569 	asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
570 
571 	/* Add for channel */
572 	asd->input_curr = 0;
573 
574 	asd->mipi_frame_size = 0;
575 	asd->copy_mode = false;
576 
577 	asd->stream_prepared = false;
578 	asd->high_speed_mode = false;
579 	asd->sensor_array_res.height = 0;
580 	asd->sensor_array_res.width = 0;
581 	atomisp_css_init_struct(asd);
582 }
583 
584 /*
585  * file operation functions
586  */
587 static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
588 {
589 	return asd->video_out_preview.users +
590 	       asd->video_out_vf.users +
591 	       asd->video_out_capture.users +
592 	       asd->video_out_video_capture.users;
593 }
594 
595 unsigned int atomisp_dev_users(struct atomisp_device *isp)
596 {
597 	return atomisp_subdev_users(&isp->asd);
598 }
599 
600 static int atomisp_open(struct file *file)
601 {
602 	struct video_device *vdev = video_devdata(file);
603 	struct atomisp_device *isp = video_get_drvdata(vdev);
604 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
605 	struct atomisp_sub_device *asd = pipe->asd;
606 	int ret;
607 
608 	dev_dbg(isp->dev, "open device %s\n", vdev->name);
609 
610 	ret = v4l2_fh_open(file);
611 	if (ret)
612 		return ret;
613 
614 	mutex_lock(&isp->mutex);
615 
616 	asd->subdev.devnode = vdev;
617 
618 	if (!isp->input_cnt) {
619 		dev_err(isp->dev, "no camera attached\n");
620 		ret = -EINVAL;
621 		goto error;
622 	}
623 
624 	/*
625 	 * atomisp does not allow multiple open
626 	 */
627 	if (pipe->users) {
628 		dev_dbg(isp->dev, "video node already opened\n");
629 		mutex_unlock(&isp->mutex);
630 		return -EBUSY;
631 	}
632 
633 	if (atomisp_dev_users(isp)) {
634 		dev_dbg(isp->dev, "skip init isp in open\n");
635 		goto init_subdev;
636 	}
637 
638 	/* runtime power management, turn on ISP */
639 	ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
640 	if (ret < 0) {
641 		dev_err(isp->dev, "Failed to power on device\n");
642 		goto error;
643 	}
644 
645 	atomisp_dev_init_struct(isp);
646 
647 	ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
648 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
649 		dev_err(isp->dev, "Failed to power-on flash\n");
650 		goto css_error;
651 	}
652 
653 init_subdev:
654 	if (atomisp_subdev_users(asd))
655 		goto done;
656 
657 	atomisp_subdev_init_struct(asd);
658 	/* Ensure that a mode is set */
659 	v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode);
660 
661 done:
662 	pipe->users++;
663 	mutex_unlock(&isp->mutex);
664 
665 
666 	return 0;
667 
668 css_error:
669 	pm_runtime_put(vdev->v4l2_dev->dev);
670 error:
671 	mutex_unlock(&isp->mutex);
672 	v4l2_fh_release(file);
673 	return ret;
674 }
675 
676 static int atomisp_release(struct file *file)
677 {
678 	struct video_device *vdev = video_devdata(file);
679 	struct atomisp_device *isp = video_get_drvdata(vdev);
680 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
681 	struct atomisp_sub_device *asd = pipe->asd;
682 	struct v4l2_subdev_fh fh;
683 	struct v4l2_rect clear_compose = {0};
684 	unsigned long flags;
685 	int ret;
686 
687 	v4l2_fh_init(&fh.vfh, vdev);
688 
689 	dev_dbg(isp->dev, "release device %s\n", vdev->name);
690 
691 	asd->subdev.devnode = vdev;
692 
693 	/* Note file must not be used after this! */
694 	vb2_fop_release(file);
695 
696 	mutex_lock(&isp->mutex);
697 
698 	pipe->users--;
699 	if (pipe->users)
700 		goto done;
701 
702 	/*
703 	 * A little trick here:
704 	 * file injection input resolution is recorded in the sink pad,
705 	 * therefore can not be cleared when releaseing one device node.
706 	 * The sink pad setting can only be cleared when all device nodes
707 	 * get released.
708 	 */
709 	{
710 		struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
711 
712 		atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
713 					V4L2_SUBDEV_FORMAT_ACTIVE,
714 					ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
715 	}
716 
717 	if (atomisp_subdev_users(asd))
718 		goto done;
719 
720 	atomisp_css_free_stat_buffers(asd);
721 	atomisp_free_internal_buffers(asd);
722 
723 	if (isp->inputs[asd->input_curr].asd == asd) {
724 		ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
725 				       core, s_power, 0);
726 		if (ret && ret != -ENOIOCTLCMD)
727 			dev_warn(isp->dev, "Failed to power-off sensor\n");
728 
729 		/* clear the asd field to show this camera is not used */
730 		isp->inputs[asd->input_curr].asd = NULL;
731 	}
732 
733 	spin_lock_irqsave(&isp->lock, flags);
734 	asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
735 	spin_unlock_irqrestore(&isp->lock, flags);
736 
737 	if (atomisp_dev_users(isp))
738 		goto done;
739 
740 	atomisp_destroy_pipes_stream_force(asd);
741 
742 	ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
743 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
744 		dev_warn(isp->dev, "Failed to power-off flash\n");
745 
746 	if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
747 		dev_err(isp->dev, "Failed to power off device\n");
748 
749 done:
750 	atomisp_subdev_set_selection(&asd->subdev, fh.state,
751 				     V4L2_SUBDEV_FORMAT_ACTIVE,
752 				     atomisp_subdev_source_pad(vdev),
753 				     V4L2_SEL_TGT_COMPOSE, 0,
754 				     &clear_compose);
755 	mutex_unlock(&isp->mutex);
756 	return 0;
757 }
758 
759 const struct v4l2_file_operations atomisp_fops = {
760 	.owner = THIS_MODULE,
761 	.open = atomisp_open,
762 	.release = atomisp_release,
763 	.mmap = vb2_fop_mmap,
764 	.poll = vb2_fop_poll,
765 	.unlocked_ioctl = video_ioctl2,
766 #ifdef CONFIG_COMPAT
767 	/*
768 	 * this was removed because of bugs, the interface
769 	 * needs to be made safe for compat tasks instead.
770 	.compat_ioctl32 = atomisp_compat_ioctl32,
771 	 */
772 #endif
773 };
774