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 	int ret;
51 
52 	mutex_lock(&pipe->asd->isp->mutex); /* for get_css_frame_info() / set_fmt() */
53 
54 	/*
55 	 * When VIDIOC_S_FMT has not been called before VIDIOC_REQBUFS, then
56 	 * this will fail. Call atomisp_set_fmt() ourselves and try again.
57 	 */
58 	ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info);
59 	if (ret) {
60 		struct v4l2_format f = {
61 			.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420,
62 			.fmt.pix.width = 10000,
63 			.fmt.pix.height = 10000,
64 		};
65 
66 		ret = atomisp_set_fmt(&pipe->vdev, &f);
67 		if (ret)
68 			goto out;
69 
70 		ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info);
71 		if (ret)
72 			goto out;
73 	}
74 
75 	atomisp_alloc_css_stat_bufs(pipe->asd, ATOMISP_INPUT_STREAM_GENERAL);
76 
77 	*nplanes = 1;
78 	sizes[0] = PAGE_ALIGN(pipe->pix.sizeimage);
79 
80 out:
81 	mutex_unlock(&pipe->asd->isp->mutex);
82 	return ret;
83 }
84 
atomisp_buf_init(struct vb2_buffer * vb)85 static int atomisp_buf_init(struct vb2_buffer *vb)
86 {
87 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
88 	struct ia_css_frame *frame = vb_to_frame(vb);
89 	int ret;
90 
91 	ret = ia_css_frame_init_from_info(frame, &pipe->frame_info);
92 	if (ret)
93 		return ret;
94 
95 	if (frame->data_bytes > vb2_plane_size(vb, 0)) {
96 		dev_err(pipe->asd->isp->dev, "Internal error frame.data_bytes(%u) > vb.length(%lu)\n",
97 			frame->data_bytes, vb2_plane_size(vb, 0));
98 		return -EIO;
99 	}
100 
101 	frame->data = hmm_create_from_vmalloc_buf(vb2_plane_size(vb, 0),
102 						  vb2_plane_vaddr(vb, 0));
103 	if (frame->data == mmgr_NULL)
104 		return -ENOMEM;
105 
106 	return 0;
107 }
108 
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)109 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd,
110 	enum atomisp_input_stream_id stream_id,
111 	enum ia_css_pipe_id css_pipe_id)
112 {
113 	struct atomisp_metadata_buf *metadata_buf;
114 	enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA;
115 	struct list_head *metadata_list;
116 
117 	if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
118 	    ATOMISP_CSS_Q_DEPTH)
119 		return 0; /* we have reached CSS queue depth */
120 
121 	if (!list_empty(&asd->metadata[md_type])) {
122 		metadata_list = &asd->metadata[md_type];
123 	} else if (!list_empty(&asd->metadata_ready[md_type])) {
124 		metadata_list = &asd->metadata_ready[md_type];
125 	} else {
126 		dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n",
127 			 __func__, md_type);
128 		return -EINVAL;
129 	}
130 
131 	metadata_buf = list_entry(metadata_list->next,
132 				  struct atomisp_metadata_buf, list);
133 	list_del_init(&metadata_buf->list);
134 
135 	if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf,
136 					     stream_id, css_pipe_id)) {
137 		list_add(&metadata_buf->list, metadata_list);
138 		return -EINVAL;
139 	} else {
140 		list_add_tail(&metadata_buf->list,
141 			      &asd->metadata_in_css[md_type]);
142 	}
143 	asd->metadata_bufs_in_css[stream_id][css_pipe_id]++;
144 
145 	return 0;
146 }
147 
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)148 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd,
149 				    enum atomisp_input_stream_id stream_id,
150 				    enum ia_css_pipe_id css_pipe_id)
151 {
152 	struct atomisp_s3a_buf *s3a_buf;
153 	struct list_head *s3a_list;
154 	unsigned int exp_id;
155 
156 	if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH)
157 		return 0; /* we have reached CSS queue depth */
158 
159 	if (!list_empty(&asd->s3a_stats)) {
160 		s3a_list = &asd->s3a_stats;
161 	} else if (!list_empty(&asd->s3a_stats_ready)) {
162 		s3a_list = &asd->s3a_stats_ready;
163 	} else {
164 		dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n",
165 			 __func__);
166 		return -EINVAL;
167 	}
168 
169 	s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list);
170 	list_del_init(&s3a_buf->list);
171 	exp_id = s3a_buf->s3a_data->exp_id;
172 
173 	hmm_flush_vmap(s3a_buf->s3a_data->data_ptr);
174 	if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf,
175 					stream_id, css_pipe_id)) {
176 		/* got from head, so return back to the head */
177 		list_add(&s3a_buf->list, s3a_list);
178 		return -EINVAL;
179 	} else {
180 		list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css);
181 		if (s3a_list == &asd->s3a_stats_ready)
182 			dev_dbg(asd->isp->dev, "drop one s3a stat with exp_id %d\n", exp_id);
183 	}
184 
185 	asd->s3a_bufs_in_css[css_pipe_id]++;
186 	return 0;
187 }
188 
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)189 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd,
190 				    enum atomisp_input_stream_id stream_id,
191 				    enum ia_css_pipe_id css_pipe_id)
192 {
193 	struct atomisp_dis_buf *dis_buf;
194 	unsigned long irqflags;
195 
196 	if (asd->dis_bufs_in_css >=  ATOMISP_CSS_Q_DEPTH)
197 		return 0; /* we have reached CSS queue depth */
198 
199 	spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
200 	if (list_empty(&asd->dis_stats)) {
201 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
202 		dev_warn(asd->isp->dev, "%s: No dis buffers available!\n",
203 			 __func__);
204 		return -EINVAL;
205 	}
206 
207 	dis_buf = list_entry(asd->dis_stats.prev,
208 			     struct atomisp_dis_buf, list);
209 	list_del_init(&dis_buf->list);
210 	spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
211 
212 	hmm_flush_vmap(dis_buf->dis_data->data_ptr);
213 	if (atomisp_q_dis_buffer_to_css(asd, dis_buf,
214 					stream_id, css_pipe_id)) {
215 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
216 		/* got from tail, so return back to the tail */
217 		list_add_tail(&dis_buf->list, &asd->dis_stats);
218 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
219 		return -EINVAL;
220 	} else {
221 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
222 		list_add_tail(&dis_buf->list, &asd->dis_stats_in_css);
223 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
224 	}
225 
226 	asd->dis_bufs_in_css++;
227 
228 	return 0;
229 }
230 
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)231 static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
232 					  struct atomisp_video_pipe *pipe,
233 					  enum atomisp_input_stream_id stream_id,
234 					  enum ia_css_buffer_type css_buf_type,
235 					  enum ia_css_pipe_id css_pipe_id)
236 {
237 	struct atomisp_css_params_with_list *param;
238 	struct ia_css_dvs_grid_info *dvs_grid =
239 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
240 	unsigned long irqflags;
241 	int space, err = 0;
242 
243 	lockdep_assert_held(&asd->isp->mutex);
244 
245 	if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM))
246 		return -EINVAL;
247 
248 	if (pipe->stopping)
249 		return -EINVAL;
250 
251 	space = ATOMISP_CSS_Q_DEPTH - atomisp_buffers_in_css(pipe);
252 	while (space--) {
253 		struct ia_css_frame *frame;
254 
255 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
256 		frame = list_first_entry_or_null(&pipe->activeq, struct ia_css_frame, queue);
257 		if (frame)
258 			list_move_tail(&frame->queue, &pipe->buffers_in_css);
259 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
260 
261 		if (!frame)
262 			return -EINVAL;
263 
264 		/*
265 		 * If there is a per_frame setting to apply on the buffer,
266 		 * do it before buffer en-queueing.
267 		 */
268 		param = pipe->frame_params[frame->vb.vb2_buf.index];
269 		if (param) {
270 			atomisp_makeup_css_parameters(asd,
271 						      &asd->params.css_param.update_flag,
272 						      &param->params);
273 			atomisp_apply_css_parameters(asd, &param->params);
274 
275 			if (param->params.update_flag.dz_config &&
276 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
277 				err = atomisp_calculate_real_zoom_region(asd,
278 					&param->params.dz_config, css_pipe_id);
279 				if (!err)
280 					asd->params.config.dz_config = &param->params.dz_config;
281 			}
282 			atomisp_css_set_isp_config_applied_frame(asd, frame);
283 			atomisp_css_update_isp_params_on_pipe(asd,
284 							      asd->stream_env[stream_id].pipes[css_pipe_id]);
285 			asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *)
286 						param->params.dvs_6axis;
287 
288 			/*
289 			 * WORKAROUND:
290 			 * Because the camera halv3 can't ensure to set zoom
291 			 * region to per_frame setting and global setting at
292 			 * same time and only set zoom region to pre_frame
293 			 * setting now.so when the pre_frame setting include
294 			 * zoom region,I will set it to global setting.
295 			 */
296 			if (param->params.update_flag.dz_config &&
297 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
298 			    && !err) {
299 				memcpy(&asd->params.css_param.dz_config,
300 				       &param->params.dz_config,
301 				       sizeof(struct ia_css_dz_config));
302 				asd->params.css_param.update_flag.dz_config =
303 				    (struct atomisp_dz_config *)
304 				    &asd->params.css_param.dz_config;
305 				asd->params.css_update_params_needed = true;
306 			}
307 			pipe->frame_params[frame->vb.vb2_buf.index] = NULL;
308 		}
309 		/* Enqueue buffer */
310 		err = atomisp_q_video_buffer_to_css(asd, frame, stream_id,
311 						    css_buf_type, css_pipe_id);
312 		if (err) {
313 			spin_lock_irqsave(&pipe->irq_lock, irqflags);
314 			list_move_tail(&frame->queue, &pipe->activeq);
315 			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
316 			dev_err(asd->isp->dev, "%s, css q fails: %d\n",
317 				__func__, err);
318 			return -EINVAL;
319 		}
320 
321 		/* enqueue 3A/DIS/metadata buffers */
322 		if (asd->params.curr_grid_info.s3a_grid.enable &&
323 		    css_pipe_id == asd->params.s3a_enabled_pipe &&
324 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
325 			atomisp_q_one_s3a_buffer(asd, stream_id,
326 						 css_pipe_id);
327 
328 		if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
329 		    metadata_info.size &&
330 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
331 			atomisp_q_one_metadata_buffer(asd, stream_id,
332 						      css_pipe_id);
333 
334 		if (dvs_grid && dvs_grid->enable &&
335 		    css_pipe_id == IA_CSS_PIPE_ID_VIDEO &&
336 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
337 			atomisp_q_one_dis_buffer(asd, stream_id,
338 						 css_pipe_id);
339 	}
340 
341 	return 0;
342 }
343 
344 /* queue all available buffers to css */
atomisp_qbuffers_to_css(struct atomisp_sub_device * asd)345 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
346 {
347 	enum ia_css_pipe_id pipe_id;
348 
349 	if (asd->copy_mode) {
350 		pipe_id = IA_CSS_PIPE_ID_COPY;
351 	} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
352 		pipe_id = IA_CSS_PIPE_ID_VIDEO;
353 	} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
354 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
355 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
356 		pipe_id = IA_CSS_PIPE_ID_VIDEO;
357 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
358 		pipe_id = IA_CSS_PIPE_ID_PREVIEW;
359 	} else {
360 		/* ATOMISP_RUN_MODE_STILL_CAPTURE */
361 		pipe_id = IA_CSS_PIPE_ID_CAPTURE;
362 	}
363 
364 	atomisp_q_video_buffers_to_css(asd, &asd->video_out,
365 				       ATOMISP_INPUT_STREAM_GENERAL,
366 				       IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, pipe_id);
367 	return 0;
368 }
369 
atomisp_buf_queue(struct vb2_buffer * vb)370 static void atomisp_buf_queue(struct vb2_buffer *vb)
371 {
372 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
373 	struct ia_css_frame *frame = vb_to_frame(vb);
374 	struct atomisp_sub_device *asd = pipe->asd;
375 	unsigned long irqflags;
376 	int ret;
377 
378 	mutex_lock(&asd->isp->mutex);
379 
380 	ret = atomisp_pipe_check(pipe, false);
381 	if (ret || pipe->stopping) {
382 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
383 		atomisp_buffer_done(frame, VB2_BUF_STATE_ERROR);
384 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
385 		goto out_unlock;
386 	}
387 
388 	/* FIXME this ugliness comes from the original atomisp buffer handling */
389 	if (!(vb->skip_cache_sync_on_finish && vb->skip_cache_sync_on_prepare))
390 		wbinvd();
391 
392 	pipe->frame_params[vb->index] = NULL;
393 
394 	spin_lock_irqsave(&pipe->irq_lock, irqflags);
395 	/*
396 	 * when a frame buffer meets following conditions, it should be put into
397 	 * the waiting list:
398 	 * 1.  It is not a main output frame, and it has a per-frame parameter
399 	 *     to go with it.
400 	 * 2.  It is not a main output frame, and the waiting buffer list is not
401 	 *     empty, to keep the FIFO sequence of frame buffer processing, it
402 	 *     is put to waiting list until previous per-frame parameter buffers
403 	 *     get enqueued.
404 	 */
405 	if (pipe->frame_request_config_id[vb->index] ||
406 	    !list_empty(&pipe->buffers_waiting_for_param))
407 		list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param);
408 	else
409 		list_add_tail(&frame->queue, &pipe->activeq);
410 
411 	spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
412 
413 	/* TODO: do this better, not best way to queue to css */
414 	if (asd->streaming) {
415 		if (!list_empty(&pipe->buffers_waiting_for_param))
416 			atomisp_handle_parameter_and_buffer(pipe);
417 		else
418 			atomisp_qbuffers_to_css(asd);
419 	}
420 
421 out_unlock:
422 	mutex_unlock(&asd->isp->mutex);
423 }
424 
atomisp_buf_cleanup(struct vb2_buffer * vb)425 static void atomisp_buf_cleanup(struct vb2_buffer *vb)
426 {
427 	struct atomisp_video_pipe *pipe = vb_to_pipe(vb);
428 	struct ia_css_frame *frame = vb_to_frame(vb);
429 	int index = frame->vb.vb2_buf.index;
430 
431 	pipe->frame_request_config_id[index] = 0;
432 	pipe->frame_params[index] = NULL;
433 
434 	hmm_free(frame->data);
435 }
436 
437 const struct vb2_ops atomisp_vb2_ops = {
438 	.queue_setup		= atomisp_queue_setup,
439 	.buf_init		= atomisp_buf_init,
440 	.buf_cleanup		= atomisp_buf_cleanup,
441 	.buf_queue		= atomisp_buf_queue,
442 	.start_streaming	= atomisp_start_streaming,
443 	.stop_streaming		= atomisp_stop_streaming,
444 };
445 
atomisp_dev_init_struct(struct atomisp_device * isp)446 static void atomisp_dev_init_struct(struct atomisp_device *isp)
447 {
448 	unsigned int i;
449 
450 	isp->isp_fatal_error = false;
451 
452 	for (i = 0; i < isp->input_cnt; i++)
453 		isp->inputs[i].asd = NULL;
454 	/*
455 	 * For Merrifield, frequency is scalable.
456 	 * After boot-up, the default frequency is 200MHz.
457 	 */
458 	isp->running_freq = ISP_FREQ_200MHZ;
459 }
460 
atomisp_subdev_init_struct(struct atomisp_sub_device * asd)461 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
462 {
463 	v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
464 	memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
465 	asd->params.color_effect = V4L2_COLORFX_NONE;
466 	asd->params.bad_pixel_en = true;
467 	asd->params.gdc_cac_en = false;
468 	asd->params.video_dis_en = false;
469 	asd->params.sc_en = false;
470 	asd->params.fpn_en = false;
471 	asd->params.xnr_en = false;
472 	asd->params.false_color = 0;
473 	asd->params.yuv_ds_en = 0;
474 	/* s3a grid not enabled for any pipe */
475 	asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
476 
477 	asd->copy_mode = false;
478 
479 	asd->stream_prepared = false;
480 	asd->high_speed_mode = false;
481 	asd->sensor_array_res.height = 0;
482 	asd->sensor_array_res.width = 0;
483 	atomisp_css_init_struct(asd);
484 }
485 
486 /*
487  * file operation functions
488  */
atomisp_open(struct file * file)489 static int atomisp_open(struct file *file)
490 {
491 	struct video_device *vdev = video_devdata(file);
492 	struct atomisp_device *isp = video_get_drvdata(vdev);
493 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
494 	struct atomisp_sub_device *asd = pipe->asd;
495 	int ret;
496 
497 	dev_dbg(isp->dev, "open device %s\n", vdev->name);
498 
499 	ret = v4l2_fh_open(file);
500 	if (ret)
501 		return ret;
502 
503 	mutex_lock(&isp->mutex);
504 
505 	if (!isp->input_cnt) {
506 		dev_err(isp->dev, "no camera attached\n");
507 		ret = -EINVAL;
508 		goto error;
509 	}
510 
511 	/*
512 	 * atomisp does not allow multiple open
513 	 */
514 	if (pipe->users) {
515 		dev_dbg(isp->dev, "video node already opened\n");
516 		mutex_unlock(&isp->mutex);
517 		return -EBUSY;
518 	}
519 
520 	/* runtime power management, turn on ISP */
521 	ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
522 	if (ret < 0) {
523 		dev_err(isp->dev, "Failed to power on device\n");
524 		goto error;
525 	}
526 
527 	atomisp_dev_init_struct(isp);
528 
529 	ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
530 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
531 		dev_err(isp->dev, "Failed to power-on flash\n");
532 		goto css_error;
533 	}
534 
535 	atomisp_subdev_init_struct(asd);
536 	/* Ensure that a mode is set */
537 	v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_PREVIEW);
538 
539 	pipe->users++;
540 	mutex_unlock(&isp->mutex);
541 	return 0;
542 
543 css_error:
544 	pm_runtime_put(vdev->v4l2_dev->dev);
545 error:
546 	mutex_unlock(&isp->mutex);
547 	v4l2_fh_release(file);
548 	return ret;
549 }
550 
atomisp_release(struct file * file)551 static int atomisp_release(struct file *file)
552 {
553 	struct video_device *vdev = video_devdata(file);
554 	struct atomisp_device *isp = video_get_drvdata(vdev);
555 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
556 	struct atomisp_sub_device *asd = pipe->asd;
557 	struct v4l2_subdev_fh fh;
558 	struct v4l2_rect clear_compose = {0};
559 	int ret;
560 
561 	v4l2_fh_init(&fh.vfh, vdev);
562 
563 	dev_dbg(isp->dev, "release device %s\n", vdev->name);
564 
565 	/* Note file must not be used after this! */
566 	vb2_fop_release(file);
567 
568 	mutex_lock(&isp->mutex);
569 
570 	pipe->users--;
571 
572 	/*
573 	 * A little trick here:
574 	 * file injection input resolution is recorded in the sink pad,
575 	 * therefore can not be cleared when releaseing one device node.
576 	 * The sink pad setting can only be cleared when all device nodes
577 	 * get released.
578 	 */
579 	{
580 		struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
581 
582 		atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
583 					V4L2_SUBDEV_FORMAT_ACTIVE,
584 					ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
585 	}
586 
587 	atomisp_css_free_stat_buffers(asd);
588 	atomisp_free_internal_buffers(asd);
589 
590 	if (isp->inputs[asd->input_curr].asd == asd) {
591 		ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
592 				       core, s_power, 0);
593 		if (ret && ret != -ENOIOCTLCMD)
594 			dev_warn(isp->dev, "Failed to power-off sensor\n");
595 
596 		/* clear the asd field to show this camera is not used */
597 		isp->inputs[asd->input_curr].asd = NULL;
598 	}
599 
600 	atomisp_destroy_pipes_stream(asd);
601 
602 	ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
603 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
604 		dev_warn(isp->dev, "Failed to power-off flash\n");
605 
606 	if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
607 		dev_err(isp->dev, "Failed to power off device\n");
608 
609 	atomisp_subdev_set_selection(&asd->subdev, fh.state,
610 				     V4L2_SUBDEV_FORMAT_ACTIVE,
611 				     ATOMISP_SUBDEV_PAD_SOURCE,
612 				     V4L2_SEL_TGT_COMPOSE, 0,
613 				     &clear_compose);
614 	mutex_unlock(&isp->mutex);
615 	return 0;
616 }
617 
618 const struct v4l2_file_operations atomisp_fops = {
619 	.owner = THIS_MODULE,
620 	.open = atomisp_open,
621 	.release = atomisp_release,
622 	.mmap = vb2_fop_mmap,
623 	.poll = vb2_fop_poll,
624 	.unlocked_ioctl = video_ioctl2,
625 #ifdef CONFIG_COMPAT
626 	/*
627 	 * this was removed because of bugs, the interface
628 	 * needs to be made safe for compat tasks instead.
629 	.compat_ioctl32 = atomisp_compat_ioctl32,
630 	 */
631 #endif
632 };
633