1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
44
45
46
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
61
62static 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
72static 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
87static 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;
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
127static 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;
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
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
169static 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;
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
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
211int 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
243
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
270
271
272
273
274
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
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
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
325static 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
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
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
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
374static 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
414int 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
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#ifdef ISP2401_NEW_INPUT_SYSTEM
468 if (asd->copy_mode) {
469 css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
470 css_preview_pipe_id = IA_CSS_PIPE_ID_COPY;
471 css_video_pipe_id = IA_CSS_PIPE_ID_COPY;
472 }
473#endif
474
475 if (asd->yuvpp_mode) {
476 capture_pipe = &asd->video_out_capture;
477 video_pipe = &asd->video_out_video_capture;
478 preview_pipe = &asd->video_out_preview;
479 css_capture_pipe_id = IA_CSS_PIPE_ID_COPY;
480 css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
481 css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
482 }
483
484 if (capture_pipe) {
485 buf_type = atomisp_get_css_buf_type(
486 asd, css_capture_pipe_id,
487 atomisp_subdev_source_pad(&capture_pipe->vdev));
488 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
489
490
491
492
493 if (ATOMISP_USE_YUVPP(asd))
494 css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
495
496 atomisp_q_video_buffers_to_css(asd, capture_pipe,
497 input_stream_id,
498 buf_type, css_capture_pipe_id);
499 }
500
501 if (vf_pipe) {
502 buf_type = atomisp_get_css_buf_type(
503 asd, css_capture_pipe_id,
504 atomisp_subdev_source_pad(&vf_pipe->vdev));
505 if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
506 input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
507 else
508 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
509
510
511
512
513 if (ATOMISP_USE_YUVPP(asd))
514 css_capture_pipe_id = IA_CSS_PIPE_ID_YUVPP;
515 atomisp_q_video_buffers_to_css(asd, vf_pipe,
516 input_stream_id,
517 buf_type, css_capture_pipe_id);
518 }
519
520 if (preview_pipe) {
521 buf_type = atomisp_get_css_buf_type(
522 asd, css_preview_pipe_id,
523 atomisp_subdev_source_pad(&preview_pipe->vdev));
524 if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
525 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
526
527 else if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP)
528 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
529 else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
530 input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
531 else
532 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
533
534
535
536
537 if (ATOMISP_USE_YUVPP(asd))
538 css_preview_pipe_id = IA_CSS_PIPE_ID_YUVPP;
539
540 atomisp_q_video_buffers_to_css(asd, preview_pipe,
541 input_stream_id,
542 buf_type, css_preview_pipe_id);
543 }
544
545 if (video_pipe) {
546 buf_type = atomisp_get_css_buf_type(
547 asd, css_video_pipe_id,
548 atomisp_subdev_source_pad(&video_pipe->vdev));
549 if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
550 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
551 else
552 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
553
554
555
556
557 if (ATOMISP_USE_YUVPP(asd))
558 css_video_pipe_id = IA_CSS_PIPE_ID_YUVPP;
559
560 atomisp_q_video_buffers_to_css(asd, video_pipe,
561 input_stream_id,
562 buf_type, css_video_pipe_id);
563 }
564
565 return 0;
566}
567
568static void atomisp_buf_queue(struct videobuf_queue *vq,
569 struct videobuf_buffer *vb)
570{
571 struct atomisp_video_pipe *pipe = vq->priv_data;
572
573
574
575
576
577
578
579
580
581
582
583 if (!atomisp_is_vf_pipe(pipe) &&
584 (pipe->frame_request_config_id[vb->i] ||
585 !list_empty(&pipe->buffers_waiting_for_param)))
586 list_add_tail(&vb->queue, &pipe->buffers_waiting_for_param);
587 else
588 list_add_tail(&vb->queue, &pipe->activeq);
589
590 vb->state = VIDEOBUF_QUEUED;
591}
592
593static void atomisp_buf_release(struct videobuf_queue *vq,
594 struct videobuf_buffer *vb)
595{
596 vb->state = VIDEOBUF_NEEDS_INIT;
597 atomisp_videobuf_free_buf(vb);
598}
599
600static int atomisp_buf_setup_output(struct videobuf_queue *vq,
601 unsigned int *count, unsigned int *size)
602{
603 struct atomisp_video_pipe *pipe = vq->priv_data;
604
605 *size = pipe->pix.sizeimage;
606
607 return 0;
608}
609
610static int atomisp_buf_prepare_output(struct videobuf_queue *vq,
611 struct videobuf_buffer *vb,
612 enum v4l2_field field)
613{
614 struct atomisp_video_pipe *pipe = vq->priv_data;
615
616 vb->size = pipe->pix.sizeimage;
617 vb->width = pipe->pix.width;
618 vb->height = pipe->pix.height;
619 vb->field = field;
620 vb->state = VIDEOBUF_PREPARED;
621
622 return 0;
623}
624
625static void atomisp_buf_queue_output(struct videobuf_queue *vq,
626 struct videobuf_buffer *vb)
627{
628 struct atomisp_video_pipe *pipe = vq->priv_data;
629
630 list_add_tail(&vb->queue, &pipe->activeq_out);
631 vb->state = VIDEOBUF_QUEUED;
632}
633
634static void atomisp_buf_release_output(struct videobuf_queue *vq,
635 struct videobuf_buffer *vb)
636{
637 videobuf_vmalloc_free(vb);
638 vb->state = VIDEOBUF_NEEDS_INIT;
639}
640
641static const struct videobuf_queue_ops videobuf_qops = {
642 .buf_setup = atomisp_buf_setup,
643 .buf_prepare = atomisp_buf_prepare,
644 .buf_queue = atomisp_buf_queue,
645 .buf_release = atomisp_buf_release,
646};
647
648static const struct videobuf_queue_ops videobuf_qops_output = {
649 .buf_setup = atomisp_buf_setup_output,
650 .buf_prepare = atomisp_buf_prepare_output,
651 .buf_queue = atomisp_buf_queue_output,
652 .buf_release = atomisp_buf_release_output,
653};
654
655static int atomisp_init_pipe(struct atomisp_video_pipe *pipe)
656{
657
658 spin_lock_init(&pipe->irq_lock);
659
660 videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL,
661 &pipe->irq_lock,
662 V4L2_BUF_TYPE_VIDEO_CAPTURE,
663 V4L2_FIELD_NONE,
664 sizeof(struct atomisp_buffer), pipe,
665 NULL);
666
667 videobuf_queue_vmalloc_init(&pipe->outq, &videobuf_qops_output, NULL,
668 &pipe->irq_lock,
669 V4L2_BUF_TYPE_VIDEO_OUTPUT,
670 V4L2_FIELD_NONE,
671 sizeof(struct atomisp_buffer), pipe,
672 NULL);
673
674 INIT_LIST_HEAD(&pipe->activeq);
675 INIT_LIST_HEAD(&pipe->activeq_out);
676 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
677 INIT_LIST_HEAD(&pipe->per_frame_params);
678 memset(pipe->frame_request_config_id, 0,
679 VIDEO_MAX_FRAME * sizeof(unsigned int));
680 memset(pipe->frame_params, 0,
681 VIDEO_MAX_FRAME *
682 sizeof(struct atomisp_css_params_with_list *));
683
684 return 0;
685}
686
687static void atomisp_dev_init_struct(struct atomisp_device *isp)
688{
689 unsigned int i;
690
691 isp->sw_contex.file_input = false;
692 isp->need_gfx_throttle = true;
693 isp->isp_fatal_error = false;
694 isp->mipi_frame_size = 0;
695
696 for (i = 0; i < isp->input_cnt; i++)
697 isp->inputs[i].asd = NULL;
698
699
700
701
702 isp->sw_contex.running_freq = ISP_FREQ_200MHZ;
703}
704
705static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
706{
707 v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
708 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
709 asd->params.color_effect = V4L2_COLORFX_NONE;
710 asd->params.bad_pixel_en = true;
711 asd->params.gdc_cac_en = false;
712 asd->params.video_dis_en = false;
713 asd->params.sc_en = false;
714 asd->params.fpn_en = false;
715 asd->params.xnr_en = false;
716 asd->params.false_color = 0;
717 asd->params.online_process = 1;
718 asd->params.yuv_ds_en = 0;
719
720 asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM;
721
722 asd->params.offline_parm.num_captures = 1;
723 asd->params.offline_parm.skip_frames = 0;
724 asd->params.offline_parm.offset = 0;
725 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
726
727 asd->input_curr = 0;
728
729 asd->mipi_frame_size = 0;
730 asd->copy_mode = false;
731 asd->yuvpp_mode = false;
732
733 asd->stream_prepared = false;
734 asd->high_speed_mode = false;
735 asd->sensor_array_res.height = 0;
736 asd->sensor_array_res.width = 0;
737 atomisp_css_init_struct(asd);
738}
739
740
741
742
743static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
744{
745 return asd->video_out_preview.users +
746 asd->video_out_vf.users +
747 asd->video_out_capture.users +
748 asd->video_out_video_capture.users +
749 asd->video_acc.users +
750 asd->video_in.users;
751}
752
753unsigned int atomisp_dev_users(struct atomisp_device *isp)
754{
755 unsigned int i, sum;
756
757 for (i = 0, sum = 0; i < isp->num_of_streams; i++)
758 sum += atomisp_subdev_users(&isp->asd[i]);
759
760 return sum;
761}
762
763static int atomisp_open(struct file *file)
764{
765 struct video_device *vdev = video_devdata(file);
766 struct atomisp_device *isp = video_get_drvdata(vdev);
767 struct atomisp_video_pipe *pipe = NULL;
768 struct atomisp_acc_pipe *acc_pipe = NULL;
769 struct atomisp_sub_device *asd;
770 bool acc_node = false;
771 int ret;
772
773 dev_dbg(isp->dev, "open device %s\n", vdev->name);
774
775 rt_mutex_lock(&isp->mutex);
776
777 acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
778 if (acc_node) {
779 acc_pipe = atomisp_to_acc_pipe(vdev);
780 asd = acc_pipe->asd;
781 } else {
782 pipe = atomisp_to_video_pipe(vdev);
783 asd = pipe->asd;
784 }
785 asd->subdev.devnode = vdev;
786
787 if (isp->css_env.isp_css_fw.bytes == 0) {
788 dev_err(isp->dev, "Deferred firmware load.\n");
789 isp->firmware = atomisp_load_firmware(isp);
790 if (!isp->firmware) {
791 dev_err(isp->dev, "Failed to load ISP firmware.\n");
792 ret = -ENOENT;
793 goto error;
794 }
795 ret = atomisp_css_load_firmware(isp);
796 if (ret) {
797 dev_err(isp->dev, "Failed to init css.\n");
798 goto error;
799 }
800
801 release_firmware(isp->firmware);
802 isp->firmware = NULL;
803 isp->css_env.isp_css_fw.data = NULL;
804 }
805
806 if (acc_node && acc_pipe->users) {
807 dev_dbg(isp->dev, "acc node already opened\n");
808 rt_mutex_unlock(&isp->mutex);
809 return -EBUSY;
810 } else if (acc_node) {
811 goto dev_init;
812 }
813
814 if (!isp->input_cnt) {
815 dev_err(isp->dev, "no camera attached\n");
816 ret = -EINVAL;
817 goto error;
818 }
819
820
821
822
823 if (pipe->users) {
824 dev_dbg(isp->dev, "video node already opened\n");
825 rt_mutex_unlock(&isp->mutex);
826 return -EBUSY;
827 }
828
829 ret = atomisp_init_pipe(pipe);
830 if (ret)
831 goto error;
832
833dev_init:
834 if (atomisp_dev_users(isp)) {
835 dev_dbg(isp->dev, "skip init isp in open\n");
836 goto init_subdev;
837 }
838
839
840 ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev);
841 if (ret < 0) {
842 dev_err(isp->dev, "Failed to power on device\n");
843 goto error;
844 }
845
846 if (dypool_enable) {
847 ret = hmm_pool_register(dypool_pgnr, HMM_POOL_TYPE_DYNAMIC);
848 if (ret)
849 dev_err(isp->dev, "Failed to register dynamic memory pool.\n");
850 }
851
852
853 if (atomisp_css_init(isp)) {
854 ret = -EINVAL;
855
856 goto css_error;
857 }
858
859 atomisp_dev_init_struct(isp);
860
861 ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
862 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
863 dev_err(isp->dev, "Failed to power-on flash\n");
864 goto css_error;
865 }
866
867init_subdev:
868 if (atomisp_subdev_users(asd))
869 goto done;
870
871 atomisp_subdev_init_struct(asd);
872
873done:
874
875 if (acc_node)
876 acc_pipe->users++;
877 else
878 pipe->users++;
879 rt_mutex_unlock(&isp->mutex);
880 return 0;
881
882css_error:
883 atomisp_css_uninit(isp);
884 pm_runtime_put(vdev->v4l2_dev->dev);
885error:
886 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
887 rt_mutex_unlock(&isp->mutex);
888 return ret;
889}
890
891static int atomisp_release(struct file *file)
892{
893 struct video_device *vdev = video_devdata(file);
894 struct atomisp_device *isp = video_get_drvdata(vdev);
895 struct atomisp_video_pipe *pipe;
896 struct atomisp_acc_pipe *acc_pipe;
897 struct atomisp_sub_device *asd;
898 bool acc_node;
899 struct v4l2_requestbuffers req;
900 struct v4l2_subdev_fh fh;
901 struct v4l2_rect clear_compose = {0};
902 int ret = 0;
903
904 v4l2_fh_init(&fh.vfh, vdev);
905
906 req.count = 0;
907 if (!isp)
908 return -EBADF;
909
910 mutex_lock(&isp->streamoff_mutex);
911 rt_mutex_lock(&isp->mutex);
912
913 dev_dbg(isp->dev, "release device %s\n", vdev->name);
914 acc_node = !strcmp(vdev->name, "ATOMISP ISP ACC");
915 if (acc_node) {
916 acc_pipe = atomisp_to_acc_pipe(vdev);
917 asd = acc_pipe->asd;
918 } else {
919 pipe = atomisp_to_video_pipe(vdev);
920 asd = pipe->asd;
921 }
922 asd->subdev.devnode = vdev;
923 if (acc_node) {
924 acc_pipe->users--;
925 goto subdev_uninit;
926 }
927 pipe->users--;
928
929 if (pipe->capq.streaming)
930 dev_warn(isp->dev,
931 "%s: ISP still streaming while closing!",
932 __func__);
933
934 if (pipe->capq.streaming &&
935 __atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
936 dev_err(isp->dev,
937 "atomisp_streamoff failed on release, driver bug");
938 goto done;
939 }
940
941 if (pipe->users)
942 goto done;
943
944 if (__atomisp_reqbufs(file, NULL, &req)) {
945 dev_err(isp->dev,
946 "atomisp_reqbufs failed on release, driver bug");
947 goto done;
948 }
949
950 if (pipe->outq.bufs[0]) {
951 mutex_lock(&pipe->outq.vb_lock);
952 videobuf_queue_cancel(&pipe->outq);
953 mutex_unlock(&pipe->outq.vb_lock);
954 }
955
956
957
958
959
960
961
962
963 if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
964 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
965
966 atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
967 V4L2_SUBDEV_FORMAT_ACTIVE,
968 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
969 }
970subdev_uninit:
971 if (atomisp_subdev_users(asd))
972 goto done;
973
974
975 if (isp->sw_contex.file_input && asd->fmt_auto->val) {
976 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
977
978 atomisp_subdev_set_ffmt(&asd->subdev, fh.state,
979 V4L2_SUBDEV_FORMAT_ACTIVE,
980 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
981 }
982
983 atomisp_css_free_stat_buffers(asd);
984 atomisp_free_internal_buffers(asd);
985 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
986 core, s_power, 0);
987 if (ret)
988 dev_warn(isp->dev, "Failed to power-off sensor\n");
989
990
991 isp->inputs[asd->input_curr].asd = NULL;
992 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
993
994 if (atomisp_dev_users(isp))
995 goto done;
996
997 atomisp_acc_release(asd);
998
999 atomisp_destroy_pipes_stream_force(asd);
1000 atomisp_css_uninit(isp);
1001
1002 if (defer_fw_load) {
1003 ia_css_unload_firmware();
1004 isp->css_env.isp_css_fw.data = NULL;
1005 isp->css_env.isp_css_fw.bytes = 0;
1006 }
1007
1008 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
1009
1010 ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
1011 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
1012 dev_warn(isp->dev, "Failed to power-off flash\n");
1013
1014 if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
1015 dev_err(isp->dev, "Failed to power off device\n");
1016
1017done:
1018 if (!acc_node) {
1019 atomisp_subdev_set_selection(&asd->subdev, fh.state,
1020 V4L2_SUBDEV_FORMAT_ACTIVE,
1021 atomisp_subdev_source_pad(vdev),
1022 V4L2_SEL_TGT_COMPOSE, 0,
1023 &clear_compose);
1024 }
1025 rt_mutex_unlock(&isp->mutex);
1026 mutex_unlock(&isp->streamoff_mutex);
1027
1028 return 0;
1029}
1030
1031
1032
1033
1034static int do_isp_mm_remap(struct atomisp_device *isp,
1035 struct vm_area_struct *vma,
1036 ia_css_ptr isp_virt, u32 host_virt, u32 pgnr)
1037{
1038 u32 pfn;
1039
1040 while (pgnr) {
1041 pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
1042 if (remap_pfn_range(vma, host_virt, pfn,
1043 PAGE_SIZE, PAGE_SHARED)) {
1044 dev_err(isp->dev, "remap_pfn_range err.\n");
1045 return -EAGAIN;
1046 }
1047
1048 isp_virt += PAGE_SIZE;
1049 host_virt += PAGE_SIZE;
1050 pgnr--;
1051 }
1052
1053 return 0;
1054}
1055
1056static int frame_mmap(struct atomisp_device *isp,
1057 const struct ia_css_frame *frame, struct vm_area_struct *vma)
1058{
1059 ia_css_ptr isp_virt;
1060 u32 host_virt;
1061 u32 pgnr;
1062
1063 if (!frame) {
1064 dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__);
1065 return -EINVAL;
1066 }
1067
1068 host_virt = vma->vm_start;
1069 isp_virt = frame->data;
1070 atomisp_get_frame_pgnr(isp, frame, &pgnr);
1071
1072 if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr))
1073 return -EAGAIN;
1074
1075 return 0;
1076}
1077
1078int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
1079 struct vm_area_struct *vma)
1080{
1081 u32 offset = vma->vm_pgoff << PAGE_SHIFT;
1082 int ret = -EINVAL, i;
1083 struct atomisp_device *isp =
1084 ((struct atomisp_video_pipe *)(q->priv_data))->isp;
1085 struct videobuf_vmalloc_memory *vm_mem;
1086 struct videobuf_mapping *map;
1087
1088 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
1089 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1090 dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1091 return -EINVAL;
1092 }
1093
1094 mutex_lock(&q->vb_lock);
1095 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1096 struct videobuf_buffer *buf = q->bufs[i];
1097
1098 if (!buf)
1099 continue;
1100
1101 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
1102 if (!map) {
1103 mutex_unlock(&q->vb_lock);
1104 return -ENOMEM;
1105 }
1106
1107 buf->map = map;
1108 map->q = q;
1109
1110 buf->baddr = vma->vm_start;
1111
1112 if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1113 buf->boff == offset) {
1114 vm_mem = buf->priv;
1115 ret = frame_mmap(isp, vm_mem->vaddr, vma);
1116 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1117 break;
1118 }
1119 }
1120 mutex_unlock(&q->vb_lock);
1121
1122 return ret;
1123}
1124
1125
1126
1127
1128
1129static int remove_pad_from_frame(struct atomisp_device *isp,
1130 struct ia_css_frame *in_frame, __u32 width, __u32 height)
1131{
1132 unsigned int i;
1133 unsigned short *buffer;
1134 int ret = 0;
1135 ia_css_ptr load = in_frame->data;
1136 ia_css_ptr store = load;
1137
1138 buffer = kmalloc_array(width, sizeof(load), GFP_KERNEL);
1139 if (!buffer)
1140 return -ENOMEM;
1141
1142 load += ISP_LEFT_PAD;
1143 for (i = 0; i < height; i++) {
1144 ret = hmm_load(load, buffer, width * sizeof(load));
1145 if (ret < 0)
1146 goto remove_pad_error;
1147
1148 ret = hmm_store(store, buffer, width * sizeof(store));
1149 if (ret < 0)
1150 goto remove_pad_error;
1151
1152 load += in_frame->info.padded_width;
1153 store += width;
1154 }
1155
1156remove_pad_error:
1157 kfree(buffer);
1158 return ret;
1159}
1160
1161static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
1162{
1163 struct video_device *vdev = video_devdata(file);
1164 struct atomisp_device *isp = video_get_drvdata(vdev);
1165 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1166 struct atomisp_sub_device *asd = pipe->asd;
1167 struct ia_css_frame *raw_virt_addr;
1168 u32 start = vma->vm_start;
1169 u32 end = vma->vm_end;
1170 u32 size = end - start;
1171 u32 origin_size, new_size;
1172 int ret;
1173
1174 if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
1175 return -EACCES;
1176
1177 rt_mutex_lock(&isp->mutex);
1178
1179 if (!(vma->vm_flags & VM_SHARED)) {
1180
1181
1182
1183
1184
1185
1186 vma->vm_flags |= VM_SHARED;
1187 ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT);
1188 rt_mutex_unlock(&isp->mutex);
1189 return ret;
1190 }
1191
1192
1193 if (atomisp_subdev_source_pad(vdev)
1194 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE &&
1195 vma->vm_pgoff == (ISP_PARAM_MMAP_OFFSET >> PAGE_SHIFT)) {
1196 new_size = pipe->pix.width * pipe->pix.height * 2;
1197 if (asd->params.online_process != 0) {
1198 ret = -EINVAL;
1199 goto error;
1200 }
1201 raw_virt_addr = asd->raw_output_frame;
1202 if (!raw_virt_addr) {
1203 dev_err(isp->dev, "Failed to request RAW frame\n");
1204 ret = -EINVAL;
1205 goto error;
1206 }
1207
1208 ret = remove_pad_from_frame(isp, raw_virt_addr,
1209 pipe->pix.width, pipe->pix.height);
1210 if (ret < 0) {
1211 dev_err(isp->dev, "remove pad failed.\n");
1212 goto error;
1213 }
1214 origin_size = raw_virt_addr->data_bytes;
1215 raw_virt_addr->data_bytes = new_size;
1216
1217 if (size != PAGE_ALIGN(new_size)) {
1218 dev_err(isp->dev, "incorrect size for mmap ISP Raw Frame\n");
1219 ret = -EINVAL;
1220 goto error;
1221 }
1222
1223 if (frame_mmap(isp, raw_virt_addr, vma)) {
1224 dev_err(isp->dev, "frame_mmap failed.\n");
1225 raw_virt_addr->data_bytes = origin_size;
1226 ret = -EAGAIN;
1227 goto error;
1228 }
1229 raw_virt_addr->data_bytes = origin_size;
1230 vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
1231 rt_mutex_unlock(&isp->mutex);
1232 return 0;
1233 }
1234
1235
1236
1237
1238 if (size != pipe->pix.sizeimage) {
1239 dev_err(isp->dev, "incorrect size for mmap ISP frames\n");
1240 ret = -EINVAL;
1241 goto error;
1242 }
1243 rt_mutex_unlock(&isp->mutex);
1244
1245 return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
1246
1247error:
1248 rt_mutex_unlock(&isp->mutex);
1249
1250 return ret;
1251}
1252
1253static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
1254{
1255 struct video_device *vdev = video_devdata(file);
1256 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1257
1258 return videobuf_mmap_mapper(&pipe->outq, vma);
1259}
1260
1261static __poll_t atomisp_poll(struct file *file,
1262 struct poll_table_struct *pt)
1263{
1264 struct video_device *vdev = video_devdata(file);
1265 struct atomisp_device *isp = video_get_drvdata(vdev);
1266 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1267
1268 rt_mutex_lock(&isp->mutex);
1269 if (pipe->capq.streaming != 1) {
1270 rt_mutex_unlock(&isp->mutex);
1271 return EPOLLERR;
1272 }
1273 rt_mutex_unlock(&isp->mutex);
1274
1275 return videobuf_poll_stream(file, &pipe->capq, pt);
1276}
1277
1278const struct v4l2_file_operations atomisp_fops = {
1279 .owner = THIS_MODULE,
1280 .open = atomisp_open,
1281 .release = atomisp_release,
1282 .mmap = atomisp_mmap,
1283 .unlocked_ioctl = video_ioctl2,
1284#ifdef CONFIG_COMPAT
1285
1286
1287
1288
1289
1290#endif
1291 .poll = atomisp_poll,
1292};
1293
1294const struct v4l2_file_operations atomisp_file_fops = {
1295 .owner = THIS_MODULE,
1296 .open = atomisp_open,
1297 .release = atomisp_release,
1298 .mmap = atomisp_file_mmap,
1299 .unlocked_ioctl = video_ioctl2,
1300#ifdef CONFIG_COMPAT
1301
1302#endif
1303 .poll = atomisp_poll,
1304};
1305