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