1 /*
2  * Support for Medifield PNW Camera Imaging ISP subsystem.
3  *
4  * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
5  *
6  * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version
10  * 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  *
18  */
19 
20 #include <linux/module.h>
21 #include <linux/pm_runtime.h>
22 
23 #include <media/v4l2-ioctl.h>
24 #include <media/videobuf-vmalloc.h>
25 
26 #include "atomisp_cmd.h"
27 #include "atomisp_common.h"
28 #include "atomisp_fops.h"
29 #include "atomisp_internal.h"
30 #include "atomisp_ioctl.h"
31 #include "atomisp_compat.h"
32 #include "atomisp_subdev.h"
33 #include "atomisp_v4l2.h"
34 #include "atomisp-regs.h"
35 #include "hmm/hmm.h"
36 
37 #include "type_support.h"
38 #include "device_access/device_access.h"
39 #include "memory_access/memory_access.h"
40 
41 #include "atomisp_acc.h"
42 
43 #define ISP_LEFT_PAD			128	/* equal to 2*NWAY */
44 
45 /*
46  * input image data, and current frame resolution for test
47  */
48 #define	ISP_PARAM_MMAP_OFFSET	0xfffff000
49 
50 #define MAGIC_CHECK(is, should)	\
51 	do { \
52 		if (unlikely((is) != (should))) { \
53 			pr_err("magic mismatch: %x (expected %x)\n", \
54 				is, should); \
55 			BUG(); \
56 		} \
57 	} while (0)
58 
59 /*
60  * Videobuf ops
61  */
62 static int atomisp_buf_setup(struct videobuf_queue *vq, unsigned int *count,
63 			     unsigned int *size)
64 {
65 	struct atomisp_video_pipe *pipe = vq->priv_data;
66 
67 	*size = pipe->pix.sizeimage;
68 
69 	return 0;
70 }
71 
72 static int atomisp_buf_prepare(struct videobuf_queue *vq,
73 			       struct videobuf_buffer *vb,
74 			       enum v4l2_field field)
75 {
76 	struct atomisp_video_pipe *pipe = vq->priv_data;
77 
78 	vb->size = pipe->pix.sizeimage;
79 	vb->width = pipe->pix.width;
80 	vb->height = pipe->pix.height;
81 	vb->field = field;
82 	vb->state = VIDEOBUF_PREPARED;
83 
84 	return 0;
85 }
86 
87 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd,
88 	enum atomisp_input_stream_id stream_id,
89 	enum ia_css_pipe_id css_pipe_id)
90 {
91 	struct atomisp_metadata_buf *metadata_buf;
92 	enum atomisp_metadata_type md_type =
93 	    atomisp_get_metadata_type(asd, css_pipe_id);
94 	struct list_head *metadata_list;
95 
96 	if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
97 	    ATOMISP_CSS_Q_DEPTH)
98 		return 0; /* we have reached CSS queue depth */
99 
100 	if (!list_empty(&asd->metadata[md_type])) {
101 		metadata_list = &asd->metadata[md_type];
102 	} else if (!list_empty(&asd->metadata_ready[md_type])) {
103 		metadata_list = &asd->metadata_ready[md_type];
104 	} else {
105 		dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n",
106 			 __func__, md_type);
107 		return -EINVAL;
108 	}
109 
110 	metadata_buf = list_entry(metadata_list->next,
111 				  struct atomisp_metadata_buf, list);
112 	list_del_init(&metadata_buf->list);
113 
114 	if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf,
115 					     stream_id, css_pipe_id)) {
116 		list_add(&metadata_buf->list, metadata_list);
117 		return -EINVAL;
118 	} else {
119 		list_add_tail(&metadata_buf->list,
120 			      &asd->metadata_in_css[md_type]);
121 	}
122 	asd->metadata_bufs_in_css[stream_id][css_pipe_id]++;
123 
124 	return 0;
125 }
126 
127 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd,
128 				    enum atomisp_input_stream_id stream_id,
129 				    enum ia_css_pipe_id css_pipe_id)
130 {
131 	struct atomisp_s3a_buf *s3a_buf;
132 	struct list_head *s3a_list;
133 	unsigned int exp_id;
134 
135 	if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH)
136 		return 0; /* we have reached CSS queue depth */
137 
138 	if (!list_empty(&asd->s3a_stats)) {
139 		s3a_list = &asd->s3a_stats;
140 	} else if (!list_empty(&asd->s3a_stats_ready)) {
141 		s3a_list = &asd->s3a_stats_ready;
142 	} else {
143 		dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n",
144 			 __func__);
145 		return -EINVAL;
146 	}
147 
148 	s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list);
149 	list_del_init(&s3a_buf->list);
150 	exp_id = s3a_buf->s3a_data->exp_id;
151 
152 	hmm_flush_vmap(s3a_buf->s3a_data->data_ptr);
153 	if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf,
154 					stream_id, css_pipe_id)) {
155 		/* got from head, so return back to the head */
156 		list_add(&s3a_buf->list, s3a_list);
157 		return -EINVAL;
158 	} else {
159 		list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css);
160 		if (s3a_list == &asd->s3a_stats_ready)
161 			dev_warn(asd->isp->dev, "%s: drop one s3a stat which has exp_id %d!\n",
162 				 __func__, exp_id);
163 	}
164 
165 	asd->s3a_bufs_in_css[css_pipe_id]++;
166 	return 0;
167 }
168 
169 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd,
170 				    enum atomisp_input_stream_id stream_id,
171 				    enum ia_css_pipe_id css_pipe_id)
172 {
173 	struct atomisp_dis_buf *dis_buf;
174 	unsigned long irqflags;
175 
176 	if (asd->dis_bufs_in_css >=  ATOMISP_CSS_Q_DEPTH)
177 		return 0; /* we have reached CSS queue depth */
178 
179 	spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
180 	if (list_empty(&asd->dis_stats)) {
181 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
182 		dev_warn(asd->isp->dev, "%s: No dis buffers available!\n",
183 			 __func__);
184 		return -EINVAL;
185 	}
186 
187 	dis_buf = list_entry(asd->dis_stats.prev,
188 			     struct atomisp_dis_buf, list);
189 	list_del_init(&dis_buf->list);
190 	spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
191 
192 	hmm_flush_vmap(dis_buf->dis_data->data_ptr);
193 	if (atomisp_q_dis_buffer_to_css(asd, dis_buf,
194 					stream_id, css_pipe_id)) {
195 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
196 		/* got from tail, so return back to the tail */
197 		list_add_tail(&dis_buf->list, &asd->dis_stats);
198 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
199 		return -EINVAL;
200 	} else {
201 		spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
202 		list_add_tail(&dis_buf->list, &asd->dis_stats_in_css);
203 		spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
204 	}
205 
206 	asd->dis_bufs_in_css++;
207 
208 	return 0;
209 }
210 
211 int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
212 				   struct atomisp_video_pipe *pipe,
213 				   enum atomisp_input_stream_id stream_id,
214 				   enum ia_css_buffer_type css_buf_type,
215 				   enum ia_css_pipe_id css_pipe_id)
216 {
217 	struct videobuf_vmalloc_memory *vm_mem;
218 	struct atomisp_css_params_with_list *param;
219 	struct ia_css_dvs_grid_info *dvs_grid =
220 	    atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
221 	unsigned long irqflags;
222 	int err = 0;
223 
224 	while (pipe->buffers_in_css < ATOMISP_CSS_Q_DEPTH) {
225 		struct videobuf_buffer *vb;
226 
227 		spin_lock_irqsave(&pipe->irq_lock, irqflags);
228 		if (list_empty(&pipe->activeq)) {
229 			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
230 			return -EINVAL;
231 		}
232 		vb = list_entry(pipe->activeq.next,
233 				struct videobuf_buffer, queue);
234 		list_del_init(&vb->queue);
235 		vb->state = VIDEOBUF_ACTIVE;
236 		spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
237 
238 		/*
239 		 * If there is a per_frame setting to apply on the buffer,
240 		 * do it before buffer en-queueing.
241 		 */
242 		vm_mem = vb->priv;
243 
244 		param = pipe->frame_params[vb->i];
245 		if (param) {
246 			atomisp_makeup_css_parameters(asd,
247 						      &asd->params.css_param.update_flag,
248 						      &param->params);
249 			atomisp_apply_css_parameters(asd, &param->params);
250 
251 			if (param->params.update_flag.dz_config &&
252 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
253 				err = atomisp_calculate_real_zoom_region(asd,
254 					&param->params.dz_config, css_pipe_id);
255 				if (!err)
256 					atomisp_css_set_dz_config(asd,
257 								  &param->params.dz_config);
258 			}
259 			atomisp_css_set_isp_config_applied_frame(asd,
260 				vm_mem->vaddr);
261 			atomisp_css_update_isp_params_on_pipe(asd,
262 							      asd->stream_env[stream_id].pipes[css_pipe_id]);
263 			asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *)
264 						param->params.dvs_6axis;
265 
266 			/*
267 			 * WORKAROUND:
268 			 * Because the camera halv3 can't ensure to set zoom
269 			 * region to per_frame setting and global setting at
270 			 * same time and only set zoom region to pre_frame
271 			 * setting now.so when the pre_frame setting include
272 			 * zoom region,I will set it to global setting.
273 			 */
274 			if (param->params.update_flag.dz_config &&
275 			    asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
276 			    && !err) {
277 				memcpy(&asd->params.css_param.dz_config,
278 				       &param->params.dz_config,
279 				       sizeof(struct ia_css_dz_config));
280 				asd->params.css_param.update_flag.dz_config =
281 				    (struct atomisp_dz_config *)
282 				    &asd->params.css_param.dz_config;
283 				asd->params.css_update_params_needed = true;
284 			}
285 		}
286 		/* Enqueue buffer */
287 		err = atomisp_q_video_buffer_to_css(asd, vm_mem, stream_id,
288 						    css_buf_type, css_pipe_id);
289 		if (err) {
290 			spin_lock_irqsave(&pipe->irq_lock, irqflags);
291 			list_add_tail(&vb->queue, &pipe->activeq);
292 			vb->state = VIDEOBUF_QUEUED;
293 			spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
294 			dev_err(asd->isp->dev, "%s, css q fails: %d\n",
295 				__func__, err);
296 			return -EINVAL;
297 		}
298 		pipe->buffers_in_css++;
299 
300 		/* enqueue 3A/DIS/metadata buffers */
301 		if (asd->params.curr_grid_info.s3a_grid.enable &&
302 		    css_pipe_id == asd->params.s3a_enabled_pipe &&
303 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
304 			atomisp_q_one_s3a_buffer(asd, stream_id,
305 						 css_pipe_id);
306 
307 		if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
308 		    metadata_info.size &&
309 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
310 			atomisp_q_one_metadata_buffer(asd, stream_id,
311 						      css_pipe_id);
312 
313 		if (dvs_grid && dvs_grid->enable &&
314 		    css_pipe_id == IA_CSS_PIPE_ID_VIDEO &&
315 		    css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
316 			atomisp_q_one_dis_buffer(asd, stream_id,
317 						 css_pipe_id);
318 	}
319 
320 	return 0;
321 }
322 
323 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
324 				    enum ia_css_pipe_id pipe_id,
325 				    uint16_t source_pad)
326 {
327 	if (ATOMISP_USE_YUVPP(asd)) {
328 		/* when run ZSL case */
329 		if (asd->continuous_mode->val &&
330 		    asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
331 			if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
332 				return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
333 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
334 				return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
335 			else
336 				return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
337 		}
338 
339 		/*when run SDV case*/
340 		if (asd->continuous_mode->val &&
341 		    asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
342 			if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
343 				return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
344 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
345 				return IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME;
346 			else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
347 				return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
348 			else
349 				return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
350 		}
351 
352 		/*other case: default setting*/
353 		if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
354 		    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
355 		    (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
356 		     asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
357 			return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
358 		else
359 			return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
360 	}
361 
362 	if (pipe_id == IA_CSS_PIPE_ID_COPY ||
363 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
364 	    source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
365 	    (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
366 	     asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
367 		return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
368 	else
369 		return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
370 }
371 
372 static int atomisp_qbuffers_to_css_for_all_pipes(struct atomisp_sub_device *asd)
373 {
374 	enum ia_css_buffer_type buf_type;
375 	enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
376 	enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
377 	enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
378 	enum atomisp_input_stream_id input_stream_id;
379 	struct atomisp_video_pipe *capture_pipe;
380 	struct atomisp_video_pipe *preview_pipe;
381 	struct atomisp_video_pipe *video_pipe;
382 
383 	capture_pipe = &asd->video_out_capture;
384 	preview_pipe = &asd->video_out_preview;
385 	video_pipe = &asd->video_out_video_capture;
386 
387 	buf_type = atomisp_get_css_buf_type(
388 		       asd, css_preview_pipe_id,
389 		       atomisp_subdev_source_pad(&preview_pipe->vdev));
390 	input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
391 	atomisp_q_video_buffers_to_css(asd, preview_pipe,
392 				       input_stream_id,
393 				       buf_type, css_preview_pipe_id);
394 
395 	buf_type = atomisp_get_css_buf_type(asd, css_capture_pipe_id,
396 					    atomisp_subdev_source_pad(&capture_pipe->vdev));
397 	input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
398 	atomisp_q_video_buffers_to_css(asd, capture_pipe,
399 				       input_stream_id,
400 				       buf_type, css_capture_pipe_id);
401 
402 	buf_type = atomisp_get_css_buf_type(asd, css_video_pipe_id,
403 					    atomisp_subdev_source_pad(&video_pipe->vdev));
404 	input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
405 	atomisp_q_video_buffers_to_css(asd, video_pipe,
406 				       input_stream_id,
407 				       buf_type, css_video_pipe_id);
408 	return 0;
409 }
410 
411 /* queue all available buffers to css */
412 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
413 {
414 	enum ia_css_buffer_type buf_type;
415 	enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM;
416 	enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM;
417 	enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM;
418 	enum atomisp_input_stream_id input_stream_id;
419 	struct atomisp_video_pipe *capture_pipe = NULL;
420 	struct atomisp_video_pipe *vf_pipe = NULL;
421 	struct atomisp_video_pipe *preview_pipe = NULL;
422 	struct atomisp_video_pipe *video_pipe = NULL;
423 	bool raw_mode = atomisp_is_mbuscode_raw(
424 			    asd->fmt[asd->capture_pad].fmt.code);
425 
426 	if (asd->isp->inputs[asd->input_curr].camera_caps->
427 	    sensor[asd->sensor_curr].stream_num == 2 &&
428 	    !asd->yuvpp_mode)
429 		return atomisp_qbuffers_to_css_for_all_pipes(asd);
430 
431 	if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
432 		video_pipe = &asd->video_out_video_capture;
433 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
434 	} else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
435 		preview_pipe = &asd->video_out_capture;
436 		css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
437 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
438 		if (asd->continuous_mode->val) {
439 			capture_pipe = &asd->video_out_capture;
440 			vf_pipe = &asd->video_out_vf;
441 			css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
442 		}
443 		video_pipe = &asd->video_out_video_capture;
444 		preview_pipe = &asd->video_out_preview;
445 		css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
446 		css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
447 	} else if (asd->continuous_mode->val) {
448 		capture_pipe = &asd->video_out_capture;
449 		vf_pipe = &asd->video_out_vf;
450 		preview_pipe = &asd->video_out_preview;
451 
452 		css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
453 		css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
454 	} else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
455 		preview_pipe = &asd->video_out_preview;
456 		css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
457 	} else {
458 		/* ATOMISP_RUN_MODE_STILL_CAPTURE */
459 		capture_pipe = &asd->video_out_capture;
460 		if (!raw_mode)
461 			vf_pipe = &asd->video_out_vf;
462 		css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
463 	}
464 
465 #ifdef ISP2401_NEW_INPUT_SYSTEM
466 	if (asd->copy_mode) {
467 		css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
468 		css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
469 		css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
470 	}
471 #endif
472 
473 	if (asd->yuvpp_mode) {
474 		capture_pipe = &asd->video_out_capture;
475 		video_pipe   = &asd->video_out_video_capture;
476 		preview_pipe = &asd->video_out_preview;
477 		css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
478 		css_video_pipe_id   = IA_CSS_PIPE_ID_YUVPP;
479 		css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
480 	}
481 
482 	if (capture_pipe) {
483 		buf_type = atomisp_get_css_buf_type(
484 			       asd, css_capture_pipe_id,
485 			       atomisp_subdev_source_pad(&capture_pipe->vdev));
486 		input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
487 
488 		/*
489 		 * use yuvpp pipe for SOC camera.
490 		 */
491 		if (ATOMISP_USE_YUVPP(asd))
492 			css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
493 
494 		atomisp_q_video_buffers_to_css(asd, capture_pipe,
495 					       input_stream_id,
496 					       buf_type, css_capture_pipe_id);
497 	}
498 
499 	if (vf_pipe) {
500 		buf_type = atomisp_get_css_buf_type(
501 			       asd, css_capture_pipe_id,
502 			       atomisp_subdev_source_pad(&vf_pipe->vdev));
503 		if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
504 			input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
505 		else
506 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
507 
508 		/*
509 		 * use yuvpp pipe for SOC camera.
510 		 */
511 		if (ATOMISP_USE_YUVPP(asd))
512 			css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
513 		atomisp_q_video_buffers_to_css(asd, vf_pipe,
514 					       input_stream_id,
515 					       buf_type, css_capture_pipe_id);
516 	}
517 
518 	if (preview_pipe) {
519 		buf_type = atomisp_get_css_buf_type(
520 			       asd, css_preview_pipe_id,
521 			       atomisp_subdev_source_pad(&preview_pipe->vdev));
522 		if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
523 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
524 		/* else for ext isp use case */
525 		else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
526 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
527 		else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
528 			input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
529 		else
530 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
531 
532 		/*
533 		 * use yuvpp pipe for SOC camera.
534 		 */
535 		if (ATOMISP_USE_YUVPP(asd))
536 			css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
537 
538 		atomisp_q_video_buffers_to_css(asd, preview_pipe,
539 					       input_stream_id,
540 					       buf_type, css_preview_pipe_id);
541 	}
542 
543 	if (video_pipe) {
544 		buf_type = atomisp_get_css_buf_type(
545 			       asd, css_video_pipe_id,
546 			       atomisp_subdev_source_pad(&video_pipe->vdev));
547 		if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
548 			input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
549 		else
550 			input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
551 
552 		/*
553 		 * use yuvpp pipe for SOC camera.
554 		 */
555 		if (ATOMISP_USE_YUVPP(asd))
556 			css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
557 
558 		atomisp_q_video_buffers_to_css(asd, video_pipe,
559 					       input_stream_id,
560 					       buf_type, css_video_pipe_id);
561 	}
562 
563 	return 0;
564 }
565 
566 static void atomisp_buf_queue(struct videobuf_queue *vq,
567 			      struct videobuf_buffer *vb)
568 {
569 	struct atomisp_video_pipe *pipe = vq->priv_data;
570 
571 	/*
572 	 * when a frame buffer meets following conditions, it should be put into
573 	 * the waiting list:
574 	 * 1.  It is not a main output frame, and it has a per-frame parameter
575 	 *     to go with it.
576 	 * 2.  It is not a main output frame, and the waiting buffer list is not
577 	 *     empty, to keep the FIFO sequence of frame buffer processing, it
578 	 *     is put to waiting list until previous per-frame parameter buffers
579 	 *     get enqueued.
580 	 */
581 	if (!atomisp_is_vf_pipe(pipe) &&
582 	    (pipe->frame_request_config_id[vb->i] ||
583 	     !list_empty(&pipe->buffers_waiting_for_param)))
584 		list_add_tail(&vb->queue, &pipe->buffers_waiting_for_param);
585 	else
586 		list_add_tail(&vb->queue, &pipe->activeq);
587 
588 	vb->state = VIDEOBUF_QUEUED;
589 }
590 
591 static void atomisp_buf_release(struct videobuf_queue *vq,
592 				struct videobuf_buffer *vb)
593 {
594 	vb->state = VIDEOBUF_NEEDS_INIT;
595 	atomisp_videobuf_free_buf(vb);
596 }
597 
598 static int atomisp_buf_setup_output(struct videobuf_queue *vq,
599 				    unsigned int *count, unsigned int *size)
600 {
601 	struct atomisp_video_pipe *pipe = vq->priv_data;
602 
603 	*size = pipe->pix.sizeimage;
604 
605 	return 0;
606 }
607 
608 static int atomisp_buf_prepare_output(struct videobuf_queue *vq,
609 				      struct videobuf_buffer *vb,
610 				      enum v4l2_field field)
611 {
612 	struct atomisp_video_pipe *pipe = vq->priv_data;
613 
614 	vb->size = pipe->pix.sizeimage;
615 	vb->width = pipe->pix.width;
616 	vb->height = pipe->pix.height;
617 	vb->field = field;
618 	vb->state = VIDEOBUF_PREPARED;
619 
620 	return 0;
621 }
622 
623 static void atomisp_buf_queue_output(struct videobuf_queue *vq,
624 				     struct videobuf_buffer *vb)
625 {
626 	struct atomisp_video_pipe *pipe = vq->priv_data;
627 
628 	list_add_tail(&vb->queue, &pipe->activeq_out);
629 	vb->state = VIDEOBUF_QUEUED;
630 }
631 
632 static void atomisp_buf_release_output(struct videobuf_queue *vq,
633 				       struct videobuf_buffer *vb)
634 {
635 	videobuf_vmalloc_free(vb);
636 	vb->state = VIDEOBUF_NEEDS_INIT;
637 }
638 
639 static const struct videobuf_queue_ops videobuf_qops = {
640 	.buf_setup	= atomisp_buf_setup,
641 	.buf_prepare	= atomisp_buf_prepare,
642 	.buf_queue	= atomisp_buf_queue,
643 	.buf_release	= atomisp_buf_release,
644 };
645 
646 static const struct videobuf_queue_ops videobuf_qops_output = {
647 	.buf_setup	= atomisp_buf_setup_output,
648 	.buf_prepare	= atomisp_buf_prepare_output,
649 	.buf_queue	= atomisp_buf_queue_output,
650 	.buf_release	= atomisp_buf_release_output,
651 };
652 
653 static int atomisp_init_pipe(struct atomisp_video_pipe *pipe)
654 {
655 	/* init locks */
656 	spin_lock_init(&pipe->irq_lock);
657 
658 	videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL,
659 				    &pipe->irq_lock,
660 				    V4L2_BUF_TYPE_VIDEO_CAPTURE,
661 				    V4L2_FIELD_NONE,
662 				    sizeof(struct atomisp_buffer), pipe,
663 				    NULL);	/* ext_lock: NULL */
664 
665 	videobuf_queue_vmalloc_init(&pipe->outq, &videobuf_qops_output, NULL,
666 				    &pipe->irq_lock,
667 				    V4L2_BUF_TYPE_VIDEO_OUTPUT,
668 				    V4L2_FIELD_NONE,
669 				    sizeof(struct atomisp_buffer), pipe,
670 				    NULL);	/* ext_lock: NULL */
671 
672 	INIT_LIST_HEAD(&pipe->activeq);
673 	INIT_LIST_HEAD(&pipe->activeq_out);
674 	INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
675 	INIT_LIST_HEAD(&pipe->per_frame_params);
676 	memset(pipe->frame_request_config_id, 0,
677 	       VIDEO_MAX_FRAME * sizeof(unsigned int));
678 	memset(pipe->frame_params, 0,
679 	       VIDEO_MAX_FRAME *
680 	       sizeof(struct atomisp_css_params_with_list *));
681 
682 	return 0;
683 }
684 
685 static void atomisp_dev_init_struct(struct atomisp_device *isp)
686 {
687 	unsigned int i;
688 
689 	isp->sw_contex.file_input = false;
690 	isp->need_gfx_throttle = true;
691 	isp->isp_fatal_error = false;
692 	isp->mipi_frame_size = 0;
693 
694 	for (i = 0; i < isp->input_cnt; i++)
695 		isp->inputs[i].asd = NULL;
696 	/*
697 	 * For Merrifield, frequency is scalable.
698 	 * After boot-up, the default frequency is 200MHz.
699 	 */
700 	isp->sw_contex.running_freq = ISP_FREQ_200MHZ;
701 }
702 
703 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
704 {
705 	v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
706 	memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
707 	asd->params.color_effect = V4L2_COLORFX_NONE;
708 	asd->params.bad_pixel_en = true;
709 	asd->params.gdc_cac_en = false;
710 	asd->params.video_dis_en = false;
711 	asd->params.sc_en = false;
712 	asd->params.fpn_en = false;
713 	asd->params.xnr_en = false;
714 	asd->params.false_color = 0;
715 	asd->params.online_process = 1;
716 	asd->params.yuv_ds_en = 0;
717 	/* s3a grid not enabled for any pipe */
718 	asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
719 
720 	asd->params.offline_parm.num_captures = 1;
721 	asd->params.offline_parm.skip_frames = 0;
722 	asd->params.offline_parm.offset = 0;
723 	asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
724 	/* Add for channel */
725 	asd->input_curr = 0;
726 
727 	asd->mipi_frame_size = 0;
728 	asd->copy_mode = false;
729 	asd->yuvpp_mode = false;
730 
731 	asd->stream_prepared = false;
732 	asd->high_speed_mode = false;
733 	asd->sensor_array_res.height = 0;
734 	asd->sensor_array_res.width = 0;
735 	atomisp_css_init_struct(asd);
736 }
737 
738 /*
739  * file operation functions
740  */
741 static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
742 {
743 	return asd->video_out_preview.users +
744 	       asd->video_out_vf.users +
745 	       asd->video_out_capture.users +
746 	       asd->video_out_video_capture.users +
747 	       asd->video_acc.users +
748 	       asd->video_in.users;
749 }
750 
751 unsigned int atomisp_dev_users(struct atomisp_device *isp)
752 {
753 	unsigned int i, sum;
754 
755 	for (i = 0, sum = 0; i < isp->num_of_streams; i++)
756 		sum += atomisp_subdev_users(&isp->asd[i]);
757 
758 	return sum;
759 }
760 
761 static int atomisp_open(struct file *file)
762 {
763 	struct video_device *vdev = video_devdata(file);
764 	struct atomisp_device *isp = video_get_drvdata(vdev);
765 	struct atomisp_video_pipe *pipe = NULL;
766 	struct atomisp_acc_pipe *acc_pipe = NULL;
767 	struct atomisp_sub_device *asd;
768 	bool acc_node = false;
769 	int ret;
770 
771 	dev_dbg(isp->dev, "open device %s\n", vdev->name);
772 
773 	rt_mutex_lock(&isp->mutex);
774 
775 	acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
776 	if (acc_node) {
777 		acc_pipe = atomisp_to_acc_pipe(vdev);
778 		asd = acc_pipe->asd;
779 	} else {
780 		pipe = atomisp_to_video_pipe(vdev);
781 		asd = pipe->asd;
782 	}
783 	asd->subdev.devnode = vdev;
784 	/* Deferred firmware loading case. */
785 	if (isp->css_env.isp_css_fw.bytes == 0) {
786 		dev_err(isp->dev, "Deferred firmware load.\n");
787 		isp->firmware = atomisp_load_firmware(isp);
788 		if (!isp->firmware) {
789 			dev_err(isp->dev, "Failed to load ISP firmware.\n");
790 			ret = -ENOENT;
791 			goto error;
792 		}
793 		ret = atomisp_css_load_firmware(isp);
794 		if (ret) {
795 			dev_err(isp->dev, "Failed to init css.\n");
796 			goto error;
797 		}
798 		/* No need to keep FW in memory anymore. */
799 		release_firmware(isp->firmware);
800 		isp->firmware = NULL;
801 		isp->css_env.isp_css_fw.data = NULL;
802 	}
803 
804 	if (acc_node && acc_pipe->users) {
805 		dev_dbg(isp->dev, "acc node already opened\n");
806 		rt_mutex_unlock(&isp->mutex);
807 		return -EBUSY;
808 	} else if (acc_node) {
809 		goto dev_init;
810 	}
811 
812 	if (!isp->input_cnt) {
813 		dev_err(isp->dev, "no camera attached\n");
814 		ret = -EINVAL;
815 		goto error;
816 	}
817 
818 	/*
819 	 * atomisp does not allow multiple open
820 	 */
821 	if (pipe->users) {
822 		dev_dbg(isp->dev, "video node already opened\n");
823 		rt_mutex_unlock(&isp->mutex);
824 		return -EBUSY;
825 	}
826 
827 	ret = atomisp_init_pipe(pipe);
828 	if (ret)
829 		goto error;
830 
831 dev_init:
832 	if (atomisp_dev_users(isp)) {
833 		dev_dbg(isp->dev, "skip init isp in open\n");
834 		goto init_subdev;
835 	}
836 
837 	/* runtime power management, turn on ISP */
838 	ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
839 	if (ret < 0) {
840 		dev_err(isp->dev, "Failed to power on device\n");
841 		goto error;
842 	}
843 
844 	if (dypool_enable) {
845 		ret = hmm_pool_register(dypool_pgnr, HMM_POOL_TYPE_DYNAMIC);
846 		if (ret)
847 			dev_err(isp->dev, "Failed to register dynamic memory pool.\n");
848 	}
849 
850 	/* Init ISP */
851 	if (atomisp_css_init(isp)) {
852 		ret = -EINVAL;
853 		/* Need to clean up CSS init if it fails. */
854 		goto css_error;
855 	}
856 
857 	atomisp_dev_init_struct(isp);
858 
859 	ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
860 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
861 		dev_err(isp->dev, "Failed to power-on flash\n");
862 		goto css_error;
863 	}
864 
865 init_subdev:
866 	if (atomisp_subdev_users(asd))
867 		goto done;
868 
869 	atomisp_subdev_init_struct(asd);
870 
871 done:
872 
873 	if (acc_node)
874 		acc_pipe->users++;
875 	else
876 		pipe->users++;
877 	rt_mutex_unlock(&isp->mutex);
878 	return 0;
879 
880 css_error:
881 	atomisp_css_uninit(isp);
882 error:
883 	hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
884 	pm_runtime_put(vdev->v4l2_dev->dev);
885 	rt_mutex_unlock(&isp->mutex);
886 	return ret;
887 }
888 
889 static int atomisp_release(struct file *file)
890 {
891 	struct video_device *vdev = video_devdata(file);
892 	struct atomisp_device *isp = video_get_drvdata(vdev);
893 	struct atomisp_video_pipe *pipe;
894 	struct atomisp_acc_pipe *acc_pipe;
895 	struct atomisp_sub_device *asd;
896 	bool acc_node;
897 	struct v4l2_requestbuffers req;
898 	struct v4l2_subdev_fh fh;
899 	struct v4l2_rect clear_compose = {0};
900 	int ret = 0;
901 
902 	v4l2_fh_init(&fh.vfh, vdev);
903 
904 	req.count = 0;
905 	if (!isp)
906 		return -EBADF;
907 
908 	mutex_lock(&isp->streamoff_mutex);
909 	rt_mutex_lock(&isp->mutex);
910 
911 	dev_dbg(isp->dev, "release device %s\n", vdev->name);
912 	acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
913 	if (acc_node) {
914 		acc_pipe = atomisp_to_acc_pipe(vdev);
915 		asd = acc_pipe->asd;
916 	} else {
917 		pipe = atomisp_to_video_pipe(vdev);
918 		asd = pipe->asd;
919 	}
920 	asd->subdev.devnode = vdev;
921 	if (acc_node) {
922 		acc_pipe->users--;
923 		goto subdev_uninit;
924 	}
925 	pipe->users--;
926 
927 	if (pipe->capq.streaming)
928 		dev_warn(isp->dev,
929 			 "%s: ISP still streaming while closing!",
930 			 __func__);
931 
932 	if (pipe->capq.streaming &&
933 	    __atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
934 		dev_err(isp->dev,
935 			"atomisp_streamoff failed on release, driver bug");
936 		goto done;
937 	}
938 
939 	if (pipe->users)
940 		goto done;
941 
942 	if (__atomisp_reqbufs(file, NULL, &req)) {
943 		dev_err(isp->dev,
944 			"atomisp_reqbufs failed on release, driver bug");
945 		goto done;
946 	}
947 
948 	if (pipe->outq.bufs[0]) {
949 		mutex_lock(&pipe->outq.vb_lock);
950 		videobuf_queue_cancel(&pipe->outq);
951 		mutex_unlock(&pipe->outq.vb_lock);
952 	}
953 
954 	/*
955 	 * A little trick here:
956 	 * file injection input resolution is recorded in the sink pad,
957 	 * therefore can not be cleared when releaseing one device node.
958 	 * The sink pad setting can only be cleared when all device nodes
959 	 * get released.
960 	 */
961 	if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
962 		struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
963 
964 		atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
965 					V4L2_SUBDEV_FORMAT_ACTIVE,
966 					ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
967 	}
968 subdev_uninit:
969 	if (atomisp_subdev_users(asd))
970 		goto done;
971 
972 	/* clear the sink pad for file input */
973 	if (isp->sw_contex.file_input && asd->fmt_auto->val) {
974 		struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
975 
976 		atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
977 					V4L2_SUBDEV_FORMAT_ACTIVE,
978 					ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
979 	}
980 
981 	atomisp_css_free_stat_buffers(asd);
982 	atomisp_free_internal_buffers(asd);
983 	ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
984 			       core, s_power, 0);
985 	if (ret)
986 		dev_warn(isp->dev, "Failed to power-off sensor\n");
987 
988 	/* clear the asd field to show this camera is not used */
989 	isp->inputs[asd->input_curr].asd = NULL;
990 	asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
991 
992 	if (atomisp_dev_users(isp))
993 		goto done;
994 
995 	atomisp_acc_release(asd);
996 
997 	atomisp_destroy_pipes_stream_force(asd);
998 	atomisp_css_uninit(isp);
999 
1000 	if (defer_fw_load) {
1001 		atomisp_css_unload_firmware(isp);
1002 		isp->css_env.isp_css_fw.data = NULL;
1003 		isp->css_env.isp_css_fw.bytes = 0;
1004 	}
1005 
1006 	hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
1007 
1008 	ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
1009 	if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
1010 		dev_warn(isp->dev, "Failed to power-off flash\n");
1011 
1012 	if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
1013 		dev_err(isp->dev, "Failed to power off device\n");
1014 
1015 done:
1016 	if (!acc_node) {
1017 		atomisp_subdev_set_selection(&asd->subdev, fh.pad,
1018 					     V4L2_SUBDEV_FORMAT_ACTIVE,
1019 					     atomisp_subdev_source_pad(vdev),
1020 					     V4L2_SEL_TGT_COMPOSE, 0,
1021 					     &clear_compose);
1022 	}
1023 	rt_mutex_unlock(&isp->mutex);
1024 	mutex_unlock(&isp->streamoff_mutex);
1025 
1026 	return 0;
1027 }
1028 
1029 /*
1030  * Memory help functions for image frame and private parameters
1031  */
1032 static int do_isp_mm_remap(struct atomisp_device *isp,
1033 			   struct vm_area_struct *vma,
1034 			   ia_css_ptr isp_virt, u32 host_virt, u32 pgnr)
1035 {
1036 	u32 pfn;
1037 
1038 	while (pgnr) {
1039 		pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
1040 		if (remap_pfn_range(vma, host_virt, pfn,
1041 				    PAGE_SIZE, PAGE_SHARED)) {
1042 			dev_err(isp->dev, "remap_pfn_range err.\n");
1043 			return -EAGAIN;
1044 		}
1045 
1046 		isp_virt += PAGE_SIZE;
1047 		host_virt += PAGE_SIZE;
1048 		pgnr--;
1049 	}
1050 
1051 	return 0;
1052 }
1053 
1054 static int frame_mmap(struct atomisp_device *isp,
1055 		      const struct ia_css_frame *frame, struct vm_area_struct *vma)
1056 {
1057 	ia_css_ptr isp_virt;
1058 	u32 host_virt;
1059 	u32 pgnr;
1060 
1061 	if (!frame) {
1062 		dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__);
1063 		return -EINVAL;
1064 	}
1065 
1066 	host_virt = vma->vm_start;
1067 	isp_virt = frame->data;
1068 	atomisp_get_frame_pgnr(isp, frame, &pgnr);
1069 
1070 	if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr))
1071 		return -EAGAIN;
1072 
1073 	return 0;
1074 }
1075 
1076 int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
1077 				 struct vm_area_struct *vma)
1078 {
1079 	u32 offset = vma->vm_pgoff << PAGE_SHIFT;
1080 	int ret = -EINVAL, i;
1081 	struct atomisp_device *isp =
1082 	    ((struct atomisp_video_pipe *)(q->priv_data))->isp;
1083 	struct videobuf_vmalloc_memory *vm_mem;
1084 	struct videobuf_mapping *map;
1085 
1086 	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
1087 	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1088 		dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1089 		return -EINVAL;
1090 	}
1091 
1092 	mutex_lock(&q->vb_lock);
1093 	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1094 		struct videobuf_buffer *buf = q->bufs[i];
1095 
1096 		if (!buf)
1097 			continue;
1098 
1099 		map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
1100 		if (!map) {
1101 			mutex_unlock(&q->vb_lock);
1102 			return -ENOMEM;
1103 		}
1104 
1105 		buf->map = map;
1106 		map->q = q;
1107 
1108 		buf->baddr = vma->vm_start;
1109 
1110 		if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1111 		    buf->boff == offset) {
1112 			vm_mem = buf->priv;
1113 			ret = frame_mmap(isp, vm_mem->vaddr, vma);
1114 			vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1115 			break;
1116 		}
1117 	}
1118 	mutex_unlock(&q->vb_lock);
1119 
1120 	return ret;
1121 }
1122 
1123 /* The input frame contains left and right padding that need to be removed.
1124  * There is always ISP_LEFT_PAD padding on the left side.
1125  * There is also padding on the right (padded_width - width).
1126  */
1127 static int remove_pad_from_frame(struct atomisp_device *isp,
1128 				 struct ia_css_frame *in_frame, __u32 width, __u32 height)
1129 {
1130 	unsigned int i;
1131 	unsigned short *buffer;
1132 	int ret = 0;
1133 	ia_css_ptr load = in_frame->data;
1134 	ia_css_ptr store = load;
1135 
1136 	buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL);
1137 	if (!buffer)
1138 		return -ENOMEM;
1139 
1140 	load += ISP_LEFT_PAD;
1141 	for (i = 0; i < height; i++) {
1142 		ret = hmm_load(load, buffer, width * sizeof(load));
1143 		if (ret < 0)
1144 			goto remove_pad_error;
1145 
1146 		ret = hmm_store(store, buffer, width * sizeof(store));
1147 		if (ret < 0)
1148 			goto remove_pad_error;
1149 
1150 		load  += in_frame->info.padded_width;
1151 		store += width;
1152 	}
1153 
1154 remove_pad_error:
1155 	kfree(buffer);
1156 	return ret;
1157 }
1158 
1159 static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
1160 {
1161 	struct video_device *vdev = video_devdata(file);
1162 	struct atomisp_device *isp = video_get_drvdata(vdev);
1163 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1164 	struct atomisp_sub_device *asd = pipe->asd;
1165 	struct ia_css_frame *raw_virt_addr;
1166 	u32 start = vma->vm_start;
1167 	u32 end = vma->vm_end;
1168 	u32 size = end - start;
1169 	u32 origin_size, new_size;
1170 	int ret;
1171 
1172 	if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
1173 		return -EACCES;
1174 
1175 	rt_mutex_lock(&isp->mutex);
1176 
1177 	if (!(vma->vm_flags & VM_SHARED)) {
1178 		/* Map private buffer.
1179 		 * Set VM_SHARED to the flags since we need
1180 		 * to map the buffer page by page.
1181 		 * Without VM_SHARED, remap_pfn_range() treats
1182 		 * this kind of mapping as invalid.
1183 		 */
1184 		vma->vm_flags |= VM_SHARED;
1185 		ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT);
1186 		rt_mutex_unlock(&isp->mutex);
1187 		return ret;
1188 	}
1189 
1190 	/* mmap for ISP offline raw data */
1191 	if (atomisp_subdev_source_pad(vdev)
1192 	    == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
1193 	    vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) {
1194 		new_size = pipe->pix.width * pipe->pix.height * 2;
1195 		if (asd->params.online_process != 0) {
1196 			ret = -EINVAL;
1197 			goto error;
1198 		}
1199 		raw_virt_addr = asd->raw_output_frame;
1200 		if (!raw_virt_addr) {
1201 			dev_err(isp->dev, "Failed to request RAW frame\n");
1202 			ret = -EINVAL;
1203 			goto error;
1204 		}
1205 
1206 		ret = remove_pad_from_frame(isp, raw_virt_addr,
1207 					    pipe->pix.width, pipe->pix.height);
1208 		if (ret < 0) {
1209 			dev_err(isp->dev, "remove pad failed.\n");
1210 			goto error;
1211 		}
1212 		origin_size = raw_virt_addr->data_bytes;
1213 		raw_virt_addr->data_bytes = new_size;
1214 
1215 		if (size != PAGE_ALIGN(new_size)) {
1216 			dev_err(isp->dev, "incorrect size for mmap ISP  Raw Frame\n");
1217 			ret = -EINVAL;
1218 			goto error;
1219 		}
1220 
1221 		if (frame_mmap(isp, raw_virt_addr, vma)) {
1222 			dev_err(isp->dev, "frame_mmap failed.\n");
1223 			raw_virt_addr->data_bytes = origin_size;
1224 			ret = -EAGAIN;
1225 			goto error;
1226 		}
1227 		raw_virt_addr->data_bytes = origin_size;
1228 		vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1229 		rt_mutex_unlock(&isp->mutex);
1230 		return 0;
1231 	}
1232 
1233 	/*
1234 	 * mmap for normal frames
1235 	 */
1236 	if (size != pipe->pix.sizeimage) {
1237 		dev_err(isp->dev, "incorrect size for mmap ISP frames\n");
1238 		ret = -EINVAL;
1239 		goto error;
1240 	}
1241 	rt_mutex_unlock(&isp->mutex);
1242 
1243 	return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
1244 
1245 error:
1246 	rt_mutex_unlock(&isp->mutex);
1247 
1248 	return ret;
1249 }
1250 
1251 static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
1252 {
1253 	struct video_device *vdev = video_devdata(file);
1254 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1255 
1256 	return videobuf_mmap_mapper(&pipe->outq, vma);
1257 }
1258 
1259 static __poll_t atomisp_poll(struct file *file,
1260 			     struct poll_table_struct *pt)
1261 {
1262 	struct video_device *vdev = video_devdata(file);
1263 	struct atomisp_device *isp = video_get_drvdata(vdev);
1264 	struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1265 
1266 	rt_mutex_lock(&isp->mutex);
1267 	if (pipe->capq.streaming != 1) {
1268 		rt_mutex_unlock(&isp->mutex);
1269 		return EPOLLERR;
1270 	}
1271 	rt_mutex_unlock(&isp->mutex);
1272 
1273 	return videobuf_poll_stream(file, &pipe->capq, pt);
1274 }
1275 
1276 const struct v4l2_file_operations atomisp_fops = {
1277 	.owner = THIS_MODULE,
1278 	.open = atomisp_open,
1279 	.release = atomisp_release,
1280 	.mmap = atomisp_mmap,
1281 	.unlocked_ioctl = video_ioctl2,
1282 #ifdef CONFIG_COMPAT
1283 	/*
1284 	 * There are problems with this code. Disable this for now.
1285 	.compat_ioctl32 = atomisp_compat_ioctl32,
1286 	 */
1287 #endif
1288 	.poll = atomisp_poll,
1289 };
1290 
1291 const struct v4l2_file_operations atomisp_file_fops = {
1292 	.owner = THIS_MODULE,
1293 	.open = atomisp_open,
1294 	.release = atomisp_release,
1295 	.mmap = atomisp_file_mmap,
1296 	.unlocked_ioctl = video_ioctl2,
1297 #ifdef CONFIG_COMPAT
1298 	/*
1299 	 * There are problems with this code. Disable this for now.
1300 	.compat_ioctl32 = atomisp_compat_ioctl32,
1301 	 */
1302 #endif
1303 	.poll = atomisp_poll,
1304 };
1305