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 if (WARN_ON(css_pipe_id >= IA_CSS_PIPE_ID_NUM))
225 return -EINVAL;
226
227 while (pipe->buffers_in_css < ATOMISP_CSS_Q_DEPTH) {
228 struct videobuf_buffer *vb;
229
230 spin_lock_irqsave(&pipe->irq_lock, irqflags);
231 if (list_empty(&pipe->activeq)) {
232 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
233 return -EINVAL;
234 }
235 vb = list_entry(pipe->activeq.next,
236 struct videobuf_buffer, queue);
237 list_del_init(&vb->queue);
238 vb->state = VIDEOBUF_ACTIVE;
239 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
240
241 /*
242 * If there is a per_frame setting to apply on the buffer,
243 * do it before buffer en-queueing.
244 */
245 vm_mem = vb->priv;
246
247 param = pipe->frame_params[vb->i];
248 if (param) {
249 atomisp_makeup_css_parameters(asd,
250 &asd->params.css_param.update_flag,
251 ¶m->params);
252 atomisp_apply_css_parameters(asd, ¶m->params);
253
254 if (param->params.update_flag.dz_config &&
255 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
256 err = atomisp_calculate_real_zoom_region(asd,
257 ¶m->params.dz_config, css_pipe_id);
258 if (!err)
259 asd->params.config.dz_config = ¶m->params.dz_config;
260 }
261 atomisp_css_set_isp_config_applied_frame(asd,
262 vm_mem->vaddr);
263 atomisp_css_update_isp_params_on_pipe(asd,
264 asd->stream_env[stream_id].pipes[css_pipe_id]);
265 asd->params.dvs_6axis = (struct ia_css_dvs_6axis_config *)
266 param->params.dvs_6axis;
267
268 /*
269 * WORKAROUND:
270 * Because the camera halv3 can't ensure to set zoom
271 * region to per_frame setting and global setting at
272 * same time and only set zoom region to pre_frame
273 * setting now.so when the pre_frame setting include
274 * zoom region,I will set it to global setting.
275 */
276 if (param->params.update_flag.dz_config &&
277 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
278 && !err) {
279 memcpy(&asd->params.css_param.dz_config,
280 ¶m->params.dz_config,
281 sizeof(struct ia_css_dz_config));
282 asd->params.css_param.update_flag.dz_config =
283 (struct atomisp_dz_config *)
284 &asd->params.css_param.dz_config;
285 asd->params.css_update_params_needed = true;
286 }
287 }
288 /* Enqueue buffer */
289 err = atomisp_q_video_buffer_to_css(asd, vm_mem, stream_id,
290 css_buf_type, css_pipe_id);
291 if (err) {
292 spin_lock_irqsave(&pipe->irq_lock, irqflags);
293 list_add_tail(&vb->queue, &pipe->activeq);
294 vb->state = VIDEOBUF_QUEUED;
295 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
296 dev_err(asd->isp->dev, "%s, css q fails: %d\n",
297 __func__, err);
298 return -EINVAL;
299 }
300 pipe->buffers_in_css++;
301
302 /* enqueue 3A/DIS/metadata buffers */
303 if (asd->params.curr_grid_info.s3a_grid.enable &&
304 css_pipe_id == asd->params.s3a_enabled_pipe &&
305 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
306 atomisp_q_one_s3a_buffer(asd, stream_id,
307 css_pipe_id);
308
309 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
310 metadata_info.size &&
311 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
312 atomisp_q_one_metadata_buffer(asd, stream_id,
313 css_pipe_id);
314
315 if (dvs_grid && dvs_grid->enable &&
316 css_pipe_id == IA_CSS_PIPE_ID_VIDEO &&
317 css_buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
318 atomisp_q_one_dis_buffer(asd, stream_id,
319 css_pipe_id);
320 }
321
322 return 0;
323 }
324
atomisp_get_css_buf_type(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id,uint16_t source_pad)325 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
326 enum ia_css_pipe_id pipe_id,
327 uint16_t source_pad)
328 {
329 if (ATOMISP_USE_YUVPP(asd)) {
330 /* when run ZSL case */
331 if (asd->continuous_mode->val &&
332 asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
333 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
334 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
335 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
336 return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
337 else
338 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
339 }
340
341 /*when run SDV case*/
342 if (asd->continuous_mode->val &&
343 asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
344 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE)
345 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
346 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
347 return IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME;
348 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
349 return IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
350 else
351 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
352 }
353
354 /*other case: default setting*/
355 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
356 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
357 (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
358 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
359 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
360 else
361 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
362 }
363
364 if (pipe_id == IA_CSS_PIPE_ID_COPY ||
365 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE ||
366 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO ||
367 (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW &&
368 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO))
369 return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
370 else
371 return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
372 }
373
atomisp_qbuffers_to_css_for_all_pipes(struct atomisp_sub_device * asd)374 static int atomisp_qbuffers_to_css_for_all_pipes(struct atomisp_sub_device *asd)
375 {
376 enum ia_css_buffer_type buf_type;
377 enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
378 enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
379 enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
380 enum atomisp_input_stream_id input_stream_id;
381 struct atomisp_video_pipe *capture_pipe;
382 struct atomisp_video_pipe *preview_pipe;
383 struct atomisp_video_pipe *video_pipe;
384
385 capture_pipe = &asd->video_out_capture;
386 preview_pipe = &asd->video_out_preview;
387 video_pipe = &asd->video_out_video_capture;
388
389 buf_type = atomisp_get_css_buf_type(
390 asd, css_preview_pipe_id,
391 atomisp_subdev_source_pad(&preview_pipe->vdev));
392 input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
393 atomisp_q_video_buffers_to_css(asd, preview_pipe,
394 input_stream_id,
395 buf_type, css_preview_pipe_id);
396
397 buf_type = atomisp_get_css_buf_type(asd, css_capture_pipe_id,
398 atomisp_subdev_source_pad(&capture_pipe->vdev));
399 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
400 atomisp_q_video_buffers_to_css(asd, capture_pipe,
401 input_stream_id,
402 buf_type, css_capture_pipe_id);
403
404 buf_type = atomisp_get_css_buf_type(asd, css_video_pipe_id,
405 atomisp_subdev_source_pad(&video_pipe->vdev));
406 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
407 atomisp_q_video_buffers_to_css(asd, video_pipe,
408 input_stream_id,
409 buf_type, css_video_pipe_id);
410 return 0;
411 }
412
413 /* queue all available buffers to css */
atomisp_qbuffers_to_css(struct atomisp_sub_device * asd)414 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
415 {
416 enum ia_css_buffer_type buf_type;
417 enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM;
418 enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM;
419 enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM;
420 enum atomisp_input_stream_id input_stream_id;
421 struct atomisp_video_pipe *capture_pipe = NULL;
422 struct atomisp_video_pipe *vf_pipe = NULL;
423 struct atomisp_video_pipe *preview_pipe = NULL;
424 struct atomisp_video_pipe *video_pipe = NULL;
425 bool raw_mode = atomisp_is_mbuscode_raw(
426 asd->fmt[asd->capture_pad].fmt.code);
427
428 if (asd->isp->inputs[asd->input_curr].camera_caps->
429 sensor[asd->sensor_curr].stream_num == 2 &&
430 !asd->yuvpp_mode)
431 return atomisp_qbuffers_to_css_for_all_pipes(asd);
432
433 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
434 video_pipe = &asd->video_out_video_capture;
435 css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
436 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
437 preview_pipe = &asd->video_out_capture;
438 css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
439 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
440 if (asd->continuous_mode->val) {
441 capture_pipe = &asd->video_out_capture;
442 vf_pipe = &asd->video_out_vf;
443 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
444 }
445 video_pipe = &asd->video_out_video_capture;
446 preview_pipe = &asd->video_out_preview;
447 css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO;
448 css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO;
449 } else if (asd->continuous_mode->val) {
450 capture_pipe = &asd->video_out_capture;
451 vf_pipe = &asd->video_out_vf;
452 preview_pipe = &asd->video_out_preview;
453
454 css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
455 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
456 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
457 preview_pipe = &asd->video_out_preview;
458 css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW;
459 } else {
460 /* ATOMISP_RUN_MODE_STILL_CAPTURE */
461 capture_pipe = &asd->video_out_capture;
462 if (!raw_mode)
463 vf_pipe = &asd->video_out_vf;
464 css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE;
465 }
466
467 if (IS_ISP2401 && asd->copy_mode) {
468 css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
469 css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
470 css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
471 }
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
atomisp_buf_queue(struct videobuf_queue * vq,struct videobuf_buffer * vb)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
atomisp_buf_release(struct videobuf_queue * vq,struct videobuf_buffer * vb)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
atomisp_buf_setup_output(struct videobuf_queue * vq,unsigned int * count,unsigned int * size)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
atomisp_buf_prepare_output(struct videobuf_queue * vq,struct videobuf_buffer * vb,enum v4l2_field field)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
atomisp_buf_queue_output(struct videobuf_queue * vq,struct videobuf_buffer * vb)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
atomisp_buf_release_output(struct videobuf_queue * vq,struct videobuf_buffer * vb)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
atomisp_init_pipe(struct atomisp_video_pipe * pipe)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
atomisp_dev_init_struct(struct atomisp_device * isp)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
atomisp_subdev_init_struct(struct atomisp_sub_device * asd)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 */
atomisp_subdev_users(struct atomisp_sub_device * asd)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
atomisp_dev_users(struct atomisp_device * isp)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
atomisp_open(struct file * file)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 /*
774 * Ensure that if we are still loading we block. Once the loading
775 * is over we can proceed. We can't blindly hold the lock until
776 * that occurs as if the load fails we'll deadlock the unload
777 */
778 rt_mutex_lock(&isp->loading);
779 /*
780 * FIXME: revisit this with a better check once the code structure
781 * is cleaned up a bit more
782 */
783 ret = v4l2_fh_open(file);
784 if (ret) {
785 dev_err(isp->dev,
786 "%s: v4l2_fh_open() returned error %d\n",
787 __func__, ret);
788 rt_mutex_unlock(&isp->loading);
789 return ret;
790 }
791 if (!isp->ready) {
792 rt_mutex_unlock(&isp->loading);
793 return -ENXIO;
794 }
795 rt_mutex_unlock(&isp->loading);
796
797 rt_mutex_lock(&isp->mutex);
798
799 acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
800 if (acc_node) {
801 acc_pipe = atomisp_to_acc_pipe(vdev);
802 asd = acc_pipe->asd;
803 } else {
804 pipe = atomisp_to_video_pipe(vdev);
805 asd = pipe->asd;
806 }
807 asd->subdev.devnode = vdev;
808 /* Deferred firmware loading case. */
809 if (isp->css_env.isp_css_fw.bytes == 0) {
810 dev_err(isp->dev, "Deferred firmware load.\n");
811 isp->firmware = atomisp_load_firmware(isp);
812 if (!isp->firmware) {
813 dev_err(isp->dev, "Failed to load ISP firmware.\n");
814 ret = -ENOENT;
815 goto error;
816 }
817 ret = atomisp_css_load_firmware(isp);
818 if (ret) {
819 dev_err(isp->dev, "Failed to init css.\n");
820 goto error;
821 }
822 /* No need to keep FW in memory anymore. */
823 release_firmware(isp->firmware);
824 isp->firmware = NULL;
825 isp->css_env.isp_css_fw.data = NULL;
826 }
827
828 if (acc_node && acc_pipe->users) {
829 dev_dbg(isp->dev, "acc node already opened\n");
830 rt_mutex_unlock(&isp->mutex);
831 return -EBUSY;
832 } else if (acc_node) {
833 goto dev_init;
834 }
835
836 if (!isp->input_cnt) {
837 dev_err(isp->dev, "no camera attached\n");
838 ret = -EINVAL;
839 goto error;
840 }
841
842 /*
843 * atomisp does not allow multiple open
844 */
845 if (pipe->users) {
846 dev_dbg(isp->dev, "video node already opened\n");
847 rt_mutex_unlock(&isp->mutex);
848 return -EBUSY;
849 }
850
851 ret = atomisp_init_pipe(pipe);
852 if (ret)
853 goto error;
854
855 dev_init:
856 if (atomisp_dev_users(isp)) {
857 dev_dbg(isp->dev, "skip init isp in open\n");
858 goto init_subdev;
859 }
860
861 /* runtime power management, turn on ISP */
862 ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
863 if (ret < 0) {
864 dev_err(isp->dev, "Failed to power on device\n");
865 goto error;
866 }
867
868 if (dypool_enable) {
869 ret = hmm_pool_register(dypool_pgnr, HMM_POOL_TYPE_DYNAMIC);
870 if (ret)
871 dev_err(isp->dev, "Failed to register dynamic memory pool.\n");
872 }
873
874 /* Init ISP */
875 if (atomisp_css_init(isp)) {
876 ret = -EINVAL;
877 /* Need to clean up CSS init if it fails. */
878 goto css_error;
879 }
880
881 atomisp_dev_init_struct(isp);
882
883 ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
884 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
885 dev_err(isp->dev, "Failed to power-on flash\n");
886 goto css_error;
887 }
888
889 init_subdev:
890 if (atomisp_subdev_users(asd))
891 goto done;
892
893 atomisp_subdev_init_struct(asd);
894
895 done:
896
897 if (acc_node)
898 acc_pipe->users++;
899 else
900 pipe->users++;
901 rt_mutex_unlock(&isp->mutex);
902
903 /* Ensure that a mode is set */
904 if (!acc_node)
905 v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode);
906
907 return 0;
908
909 css_error:
910 atomisp_css_uninit(isp);
911 pm_runtime_put(vdev->v4l2_dev->dev);
912 error:
913 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
914 rt_mutex_unlock(&isp->mutex);
915 return ret;
916 }
917
atomisp_release(struct file * file)918 static int atomisp_release(struct file *file)
919 {
920 struct video_device *vdev = video_devdata(file);
921 struct atomisp_device *isp = video_get_drvdata(vdev);
922 struct atomisp_video_pipe *pipe;
923 struct atomisp_acc_pipe *acc_pipe;
924 struct atomisp_sub_device *asd;
925 bool acc_node;
926 struct v4l2_requestbuffers req;
927 struct v4l2_subdev_fh fh;
928 struct v4l2_rect clear_compose = {0};
929 int ret = 0;
930
931 v4l2_fh_init(&fh.vfh, vdev);
932
933 req.count = 0;
934 if (!isp)
935 return -EBADF;
936
937 mutex_lock(&isp->streamoff_mutex);
938 rt_mutex_lock(&isp->mutex);
939
940 dev_dbg(isp->dev, "release device %s\n", vdev->name);
941 acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
942 if (acc_node) {
943 acc_pipe = atomisp_to_acc_pipe(vdev);
944 asd = acc_pipe->asd;
945 } else {
946 pipe = atomisp_to_video_pipe(vdev);
947 asd = pipe->asd;
948 }
949 asd->subdev.devnode = vdev;
950 if (acc_node) {
951 acc_pipe->users--;
952 goto subdev_uninit;
953 }
954 pipe->users--;
955
956 if (pipe->capq.streaming)
957 dev_warn(isp->dev,
958 "%s: ISP still streaming while closing!",
959 __func__);
960
961 if (pipe->capq.streaming &&
962 __atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
963 dev_err(isp->dev,
964 "atomisp_streamoff failed on release, driver bug");
965 goto done;
966 }
967
968 if (pipe->users)
969 goto done;
970
971 if (__atomisp_reqbufs(file, NULL, &req)) {
972 dev_err(isp->dev,
973 "atomisp_reqbufs failed on release, driver bug");
974 goto done;
975 }
976
977 if (pipe->outq.bufs[0]) {
978 mutex_lock(&pipe->outq.vb_lock);
979 videobuf_queue_cancel(&pipe->outq);
980 mutex_unlock(&pipe->outq.vb_lock);
981 }
982
983 /*
984 * A little trick here:
985 * file injection input resolution is recorded in the sink pad,
986 * therefore can not be cleared when releaseing one device node.
987 * The sink pad setting can only be cleared when all device nodes
988 * get released.
989 */
990 if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
991 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
992
993 atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
994 V4L2_SUBDEV_FORMAT_ACTIVE,
995 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
996 }
997 subdev_uninit:
998 if (atomisp_subdev_users(asd))
999 goto done;
1000
1001 /* clear the sink pad for file input */
1002 if (isp->sw_contex.file_input && asd->fmt_auto->val) {
1003 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
1004
1005 atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
1006 V4L2_SUBDEV_FORMAT_ACTIVE,
1007 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
1008 }
1009
1010 atomisp_css_free_stat_buffers(asd);
1011 atomisp_free_internal_buffers(asd);
1012 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
1013 core, s_power, 0);
1014 if (ret)
1015 dev_warn(isp->dev, "Failed to power-off sensor\n");
1016
1017 /* clear the asd field to show this camera is not used */
1018 isp->inputs[asd->input_curr].asd = NULL;
1019 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
1020
1021 if (atomisp_dev_users(isp))
1022 goto done;
1023
1024 atomisp_acc_release(asd);
1025
1026 atomisp_destroy_pipes_stream_force(asd);
1027 atomisp_css_uninit(isp);
1028
1029 if (defer_fw_load) {
1030 ia_css_unload_firmware();
1031 isp->css_env.isp_css_fw.data = NULL;
1032 isp->css_env.isp_css_fw.bytes = 0;
1033 }
1034
1035 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
1036
1037 ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
1038 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
1039 dev_warn(isp->dev, "Failed to power-off flash\n");
1040
1041 if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
1042 dev_err(isp->dev, "Failed to power off device\n");
1043
1044 done:
1045 if (!acc_node) {
1046 atomisp_subdev_set_selection(&asd->subdev, fh.state,
1047 V4L2_SUBDEV_FORMAT_ACTIVE,
1048 atomisp_subdev_source_pad(vdev),
1049 V4L2_SEL_TGT_COMPOSE, 0,
1050 &clear_compose);
1051 }
1052 rt_mutex_unlock(&isp->mutex);
1053 mutex_unlock(&isp->streamoff_mutex);
1054
1055 return v4l2_fh_release(file);
1056 }
1057
1058 /*
1059 * Memory help functions for image frame and private parameters
1060 */
do_isp_mm_remap(struct atomisp_device * isp,struct vm_area_struct * vma,ia_css_ptr isp_virt,u32 host_virt,u32 pgnr)1061 static int do_isp_mm_remap(struct atomisp_device *isp,
1062 struct vm_area_struct *vma,
1063 ia_css_ptr isp_virt, u32 host_virt, u32 pgnr)
1064 {
1065 u32 pfn;
1066
1067 while (pgnr) {
1068 pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
1069 if (remap_pfn_range(vma, host_virt, pfn,
1070 PAGE_SIZE, PAGE_SHARED)) {
1071 dev_err(isp->dev, "remap_pfn_range err.\n");
1072 return -EAGAIN;
1073 }
1074
1075 isp_virt += PAGE_SIZE;
1076 host_virt += PAGE_SIZE;
1077 pgnr--;
1078 }
1079
1080 return 0;
1081 }
1082
frame_mmap(struct atomisp_device * isp,const struct ia_css_frame * frame,struct vm_area_struct * vma)1083 static int frame_mmap(struct atomisp_device *isp,
1084 const struct ia_css_frame *frame, struct vm_area_struct *vma)
1085 {
1086 ia_css_ptr isp_virt;
1087 u32 host_virt;
1088 u32 pgnr;
1089
1090 if (!frame) {
1091 dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__);
1092 return -EINVAL;
1093 }
1094
1095 host_virt = vma->vm_start;
1096 isp_virt = frame->data;
1097 pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE);
1098
1099 if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr))
1100 return -EAGAIN;
1101
1102 return 0;
1103 }
1104
atomisp_videobuf_mmap_mapper(struct videobuf_queue * q,struct vm_area_struct * vma)1105 int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
1106 struct vm_area_struct *vma)
1107 {
1108 u32 offset = vma->vm_pgoff << PAGE_SHIFT;
1109 int ret = -EINVAL, i;
1110 struct atomisp_device *isp =
1111 ((struct atomisp_video_pipe *)(q->priv_data))->isp;
1112 struct videobuf_vmalloc_memory *vm_mem;
1113 struct videobuf_mapping *map;
1114
1115 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
1116 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1117 dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1118 return -EINVAL;
1119 }
1120
1121 mutex_lock(&q->vb_lock);
1122 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1123 struct videobuf_buffer *buf = q->bufs[i];
1124
1125 if (!buf)
1126 continue;
1127
1128 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
1129 if (!map) {
1130 mutex_unlock(&q->vb_lock);
1131 return -ENOMEM;
1132 }
1133
1134 buf->map = map;
1135 map->q = q;
1136
1137 buf->baddr = vma->vm_start;
1138
1139 if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1140 buf->boff == offset) {
1141 vm_mem = buf->priv;
1142 ret = frame_mmap(isp, vm_mem->vaddr, vma);
1143 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1144 break;
1145 }
1146 }
1147 mutex_unlock(&q->vb_lock);
1148
1149 return ret;
1150 }
1151
1152 /* The input frame contains left and right padding that need to be removed.
1153 * There is always ISP_LEFT_PAD padding on the left side.
1154 * There is also padding on the right (padded_width - width).
1155 */
remove_pad_from_frame(struct atomisp_device * isp,struct ia_css_frame * in_frame,__u32 width,__u32 height)1156 static int remove_pad_from_frame(struct atomisp_device *isp,
1157 struct ia_css_frame *in_frame, __u32 width, __u32 height)
1158 {
1159 unsigned int i;
1160 unsigned short *buffer;
1161 int ret = 0;
1162 ia_css_ptr load = in_frame->data;
1163 ia_css_ptr store = load;
1164
1165 buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL);
1166 if (!buffer)
1167 return -ENOMEM;
1168
1169 load += ISP_LEFT_PAD;
1170 for (i = 0; i < height; i++) {
1171 ret = hmm_load(load, buffer, width * sizeof(load));
1172 if (ret < 0)
1173 goto remove_pad_error;
1174
1175 ret = hmm_store(store, buffer, width * sizeof(store));
1176 if (ret < 0)
1177 goto remove_pad_error;
1178
1179 load += in_frame->info.padded_width;
1180 store += width;
1181 }
1182
1183 remove_pad_error:
1184 kfree(buffer);
1185 return ret;
1186 }
1187
atomisp_mmap(struct file * file,struct vm_area_struct * vma)1188 static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
1189 {
1190 struct video_device *vdev = video_devdata(file);
1191 struct atomisp_device *isp = video_get_drvdata(vdev);
1192 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1193 struct atomisp_sub_device *asd = pipe->asd;
1194 struct ia_css_frame *raw_virt_addr;
1195 u32 start = vma->vm_start;
1196 u32 end = vma->vm_end;
1197 u32 size = end - start;
1198 u32 origin_size, new_size;
1199 int ret;
1200
1201 if (!asd) {
1202 dev_err(isp->dev, "%s(): asd is NULL, device is %s\n",
1203 __func__, vdev->name);
1204 return -EINVAL;
1205 }
1206
1207 if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
1208 return -EACCES;
1209
1210 rt_mutex_lock(&isp->mutex);
1211
1212 if (!(vma->vm_flags & VM_SHARED)) {
1213 /* Map private buffer.
1214 * Set VM_SHARED to the flags since we need
1215 * to map the buffer page by page.
1216 * Without VM_SHARED, remap_pfn_range() treats
1217 * this kind of mapping as invalid.
1218 */
1219 vma->vm_flags |= VM_SHARED;
1220 ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT);
1221 rt_mutex_unlock(&isp->mutex);
1222 return ret;
1223 }
1224
1225 /* mmap for ISP offline raw data */
1226 if (atomisp_subdev_source_pad(vdev)
1227 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
1228 vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) {
1229 new_size = pipe->pix.width * pipe->pix.height * 2;
1230 if (asd->params.online_process != 0) {
1231 ret = -EINVAL;
1232 goto error;
1233 }
1234 raw_virt_addr = asd->raw_output_frame;
1235 if (!raw_virt_addr) {
1236 dev_err(isp->dev, "Failed to request RAW frame\n");
1237 ret = -EINVAL;
1238 goto error;
1239 }
1240
1241 ret = remove_pad_from_frame(isp, raw_virt_addr,
1242 pipe->pix.width, pipe->pix.height);
1243 if (ret < 0) {
1244 dev_err(isp->dev, "remove pad failed.\n");
1245 goto error;
1246 }
1247 origin_size = raw_virt_addr->data_bytes;
1248 raw_virt_addr->data_bytes = new_size;
1249
1250 if (size != PAGE_ALIGN(new_size)) {
1251 dev_err(isp->dev, "incorrect size for mmap ISP Raw Frame\n");
1252 ret = -EINVAL;
1253 goto error;
1254 }
1255
1256 if (frame_mmap(isp, raw_virt_addr, vma)) {
1257 dev_err(isp->dev, "frame_mmap failed.\n");
1258 raw_virt_addr->data_bytes = origin_size;
1259 ret = -EAGAIN;
1260 goto error;
1261 }
1262 raw_virt_addr->data_bytes = origin_size;
1263 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1264 rt_mutex_unlock(&isp->mutex);
1265 return 0;
1266 }
1267
1268 /*
1269 * mmap for normal frames
1270 */
1271 if (size != pipe->pix.sizeimage) {
1272 dev_err(isp->dev, "incorrect size for mmap ISP frames\n");
1273 ret = -EINVAL;
1274 goto error;
1275 }
1276 rt_mutex_unlock(&isp->mutex);
1277
1278 return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
1279
1280 error:
1281 rt_mutex_unlock(&isp->mutex);
1282
1283 return ret;
1284 }
1285
atomisp_file_mmap(struct file * file,struct vm_area_struct * vma)1286 static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
1287 {
1288 struct video_device *vdev = video_devdata(file);
1289 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1290
1291 return videobuf_mmap_mapper(&pipe->outq, vma);
1292 }
1293
atomisp_poll(struct file * file,struct poll_table_struct * pt)1294 static __poll_t atomisp_poll(struct file *file,
1295 struct poll_table_struct *pt)
1296 {
1297 struct video_device *vdev = video_devdata(file);
1298 struct atomisp_device *isp = video_get_drvdata(vdev);
1299 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1300
1301 rt_mutex_lock(&isp->mutex);
1302 if (pipe->capq.streaming != 1) {
1303 rt_mutex_unlock(&isp->mutex);
1304 return EPOLLERR;
1305 }
1306 rt_mutex_unlock(&isp->mutex);
1307
1308 return videobuf_poll_stream(file, &pipe->capq, pt);
1309 }
1310
1311 const struct v4l2_file_operations atomisp_fops = {
1312 .owner = THIS_MODULE,
1313 .open = atomisp_open,
1314 .release = atomisp_release,
1315 .mmap = atomisp_mmap,
1316 .unlocked_ioctl = video_ioctl2,
1317 #ifdef CONFIG_COMPAT
1318 /*
1319 * this was removed because of bugs, the interface
1320 * needs to be made safe for compat tasks instead.
1321 .compat_ioctl32 = atomisp_compat_ioctl32,
1322 */
1323 #endif
1324 .poll = atomisp_poll,
1325 };
1326
1327 const struct v4l2_file_operations atomisp_file_fops = {
1328 .owner = THIS_MODULE,
1329 .open = atomisp_open,
1330 .release = atomisp_release,
1331 .mmap = atomisp_file_mmap,
1332 .unlocked_ioctl = video_ioctl2,
1333 #ifdef CONFIG_COMPAT
1334 /* .compat_ioctl32 = atomisp_compat_ioctl32, */
1335 #endif
1336 .poll = atomisp_poll,
1337 };
1338