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