2 * Support for Medifield PNW Camera Imaging ISP subsystem.
4 * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
6 * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
20 #include <linux/module.h>
21 #include <linux/pm_runtime.h>
23 #include <media/v4l2-ioctl.h>
24 #include <media/videobuf-vmalloc.h>
26 #include "atomisp_cmd.h"
27 #include "atomisp_common.h"
28 #include "atomisp_fops.h"
29 #include "atomisp_internal.h"
30 #include "atomisp_ioctl.h"
31 #include "atomisp_compat.h"
32 #include "atomisp_subdev.h"
33 #include "atomisp_v4l2.h"
34 #include "atomisp-regs.h"
37 #include "hrt/hive_isp_css_mm_hrt.h"
39 #include "type_support.h"
40 #include "device_access/device_access.h"
41 #include "memory_access/memory_access.h"
43 #include "atomisp_acc.h"
45 #define ISP_LEFT_PAD 128 /* equal to 2*NWAY */
48 * input image data, and current frame resolution for test
50 #define ISP_PARAM_MMAP_OFFSET 0xfffff000
52 #define MAGIC_CHECK(is, should) \
54 if (unlikely((is) != (should))) { \
55 pr_err("magic mismatch: %x (expected %x)\n", \
64 static int atomisp_buf_setup(struct videobuf_queue *vq, unsigned int *count,
67 struct atomisp_video_pipe *pipe = vq->priv_data;
69 *size = pipe->pix.sizeimage;
74 static int atomisp_buf_prepare(struct videobuf_queue *vq,
75 struct videobuf_buffer *vb,
76 enum v4l2_field field)
78 struct atomisp_video_pipe *pipe = vq->priv_data;
80 vb->size = pipe->pix.sizeimage;
81 vb->width = pipe->pix.width;
82 vb->height = pipe->pix.height;
84 vb->state = VIDEOBUF_PREPARED;
89 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device *asd,
90 enum atomisp_input_stream_id stream_id,
91 enum atomisp_css_pipe_id css_pipe_id)
93 struct atomisp_metadata_buf *metadata_buf;
94 enum atomisp_metadata_type md_type =
95 atomisp_get_metadata_type(asd, css_pipe_id);
96 struct list_head *metadata_list;
98 if (asd->metadata_bufs_in_css[stream_id][css_pipe_id] >=
100 return 0; /* we have reached CSS queue depth */
102 if (!list_empty(&asd->metadata[md_type])) {
103 metadata_list = &asd->metadata[md_type];
104 } else if (!list_empty(&asd->metadata_ready[md_type])) {
105 metadata_list = &asd->metadata_ready[md_type];
107 dev_warn(asd->isp->dev, "%s: No metadata buffers available for type %d!\n",
112 metadata_buf = list_entry(metadata_list->next,
113 struct atomisp_metadata_buf, list);
114 list_del_init(&metadata_buf->list);
116 if (atomisp_q_metadata_buffer_to_css(asd, metadata_buf,
117 stream_id, css_pipe_id)) {
118 list_add(&metadata_buf->list, metadata_list);
121 list_add_tail(&metadata_buf->list,
122 &asd->metadata_in_css[md_type]);
124 asd->metadata_bufs_in_css[stream_id][css_pipe_id]++;
129 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device *asd,
130 enum atomisp_input_stream_id stream_id,
131 enum atomisp_css_pipe_id css_pipe_id)
133 struct atomisp_s3a_buf *s3a_buf;
134 struct list_head *s3a_list;
137 if (asd->s3a_bufs_in_css[css_pipe_id] >= ATOMISP_CSS_Q_DEPTH)
138 return 0; /* we have reached CSS queue depth */
140 if (!list_empty(&asd->s3a_stats)) {
141 s3a_list = &asd->s3a_stats;
142 } else if (!list_empty(&asd->s3a_stats_ready)) {
143 s3a_list = &asd->s3a_stats_ready;
145 dev_warn(asd->isp->dev, "%s: No s3a buffers available!\n",
150 s3a_buf = list_entry(s3a_list->next, struct atomisp_s3a_buf, list);
151 list_del_init(&s3a_buf->list);
152 exp_id = s3a_buf->s3a_data->exp_id;
154 hmm_flush_vmap(s3a_buf->s3a_data->data_ptr);
155 if (atomisp_q_s3a_buffer_to_css(asd, s3a_buf,
156 stream_id, css_pipe_id)) {
157 /* got from head, so return back to the head */
158 list_add(&s3a_buf->list, s3a_list);
161 list_add_tail(&s3a_buf->list, &asd->s3a_stats_in_css);
162 if (s3a_list == &asd->s3a_stats_ready)
163 dev_warn(asd->isp->dev, "%s: drop one s3a stat which has exp_id %d!\n",
167 asd->s3a_bufs_in_css[css_pipe_id]++;
171 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device *asd,
172 enum atomisp_input_stream_id stream_id,
173 enum atomisp_css_pipe_id css_pipe_id)
175 struct atomisp_dis_buf *dis_buf;
176 unsigned long irqflags;
178 if (asd->dis_bufs_in_css >= ATOMISP_CSS_Q_DEPTH)
179 return 0; /* we have reached CSS queue depth */
181 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
182 if (list_empty(&asd->dis_stats)) {
183 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
184 dev_warn(asd->isp->dev, "%s: No dis buffers available!\n",
189 dis_buf = list_entry(asd->dis_stats.prev,
190 struct atomisp_dis_buf, list);
191 list_del_init(&dis_buf->list);
192 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
194 hmm_flush_vmap(dis_buf->dis_data->data_ptr);
195 if (atomisp_q_dis_buffer_to_css(asd, dis_buf,
196 stream_id, css_pipe_id)) {
197 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
198 /* got from tail, so return back to the tail */
199 list_add_tail(&dis_buf->list, &asd->dis_stats);
200 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
203 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
204 list_add_tail(&dis_buf->list, &asd->dis_stats_in_css);
205 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
208 asd->dis_bufs_in_css++;
213 int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd,
214 struct atomisp_video_pipe *pipe,
215 enum atomisp_input_stream_id stream_id,
216 enum atomisp_css_buffer_type css_buf_type,
217 enum atomisp_css_pipe_id css_pipe_id)
219 struct videobuf_vmalloc_memory *vm_mem;
220 struct atomisp_css_params_with_list *param;
221 struct atomisp_css_dvs_grid_info *dvs_grid =
222 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
223 unsigned long irqflags;
226 while (pipe->buffers_in_css < ATOMISP_CSS_Q_DEPTH) {
227 struct videobuf_buffer *vb;
229 spin_lock_irqsave(&pipe->irq_lock, irqflags);
230 if (list_empty(&pipe->activeq)) {
231 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
234 vb = list_entry(pipe->activeq.next,
235 struct videobuf_buffer, queue);
236 list_del_init(&vb->queue);
237 vb->state = VIDEOBUF_ACTIVE;
238 spin_unlock_irqrestore(&pipe->irq_lock, irqflags);
241 * If there is a per_frame setting to apply on the buffer,
242 * do it before buffer en-queueing.
246 param = pipe->frame_params[vb->i];
248 atomisp_makeup_css_parameters(asd,
249 &asd->params.css_param.update_flag,
251 atomisp_apply_css_parameters(asd, ¶m->params);
253 if (param->params.update_flag.dz_config &&
254 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) {
255 err = atomisp_calculate_real_zoom_region(asd,
256 ¶m->params.dz_config, css_pipe_id);
258 atomisp_css_set_dz_config(asd,
259 ¶m->params.dz_config);
261 atomisp_css_set_isp_config_applied_frame(asd,
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 atomisp_css_dvs_6axis *)
266 param->params.dvs_6axis;
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 inculde
274 * zoom region,I will set it to global setting.
276 if (param->params.update_flag.dz_config &&
277 asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO
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;
289 err = atomisp_q_video_buffer_to_css(asd, vm_mem, stream_id,
290 css_buf_type, css_pipe_id);
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",
300 pipe->buffers_in_css++;
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 == CSS_BUFFER_TYPE_OUTPUT_FRAME)
306 atomisp_q_one_s3a_buffer(asd, stream_id,
309 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info.
310 metadata_info.size &&
311 css_buf_type == CSS_BUFFER_TYPE_OUTPUT_FRAME)
312 atomisp_q_one_metadata_buffer(asd, stream_id,
315 if (dvs_grid && dvs_grid->enable &&
316 css_pipe_id == CSS_PIPE_ID_VIDEO &&
317 css_buf_type == CSS_BUFFER_TYPE_OUTPUT_FRAME)
318 atomisp_q_one_dis_buffer(asd, stream_id,
325 static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd,
326 enum atomisp_css_pipe_id pipe_id,
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 CSS_BUFFER_TYPE_OUTPUT_FRAME;
335 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
336 return CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
338 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
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 CSS_BUFFER_TYPE_OUTPUT_FRAME;
346 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW)
347 return CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME;
348 else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO)
349 return CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME;
351 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
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 CSS_BUFFER_TYPE_OUTPUT_FRAME;
361 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
364 if (pipe_id == 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 CSS_BUFFER_TYPE_OUTPUT_FRAME;
371 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME;
374 static int atomisp_qbuffers_to_css_for_all_pipes(struct atomisp_sub_device *asd)
376 enum atomisp_css_buffer_type buf_type;
377 enum atomisp_css_pipe_id css_capture_pipe_id = CSS_PIPE_ID_COPY;
378 enum atomisp_css_pipe_id css_preview_pipe_id = CSS_PIPE_ID_COPY;
379 enum atomisp_css_pipe_id css_video_pipe_id = 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;
385 capture_pipe = &asd->video_out_capture;
386 preview_pipe = &asd->video_out_preview;
387 video_pipe = &asd->video_out_video_capture;
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,
395 buf_type, css_preview_pipe_id);
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,
402 buf_type, css_capture_pipe_id);
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,
409 buf_type, css_video_pipe_id);
414 /* queue all available buffers to css */
415 int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd)
417 enum atomisp_css_buffer_type buf_type;
418 enum atomisp_css_pipe_id css_capture_pipe_id = CSS_PIPE_ID_NUM;
419 enum atomisp_css_pipe_id css_preview_pipe_id = CSS_PIPE_ID_NUM;
420 enum atomisp_css_pipe_id css_video_pipe_id = CSS_PIPE_ID_NUM;
421 enum atomisp_input_stream_id input_stream_id;
422 struct atomisp_video_pipe *capture_pipe = NULL;
423 struct atomisp_video_pipe *vf_pipe = NULL;
424 struct atomisp_video_pipe *preview_pipe = NULL;
425 struct atomisp_video_pipe *video_pipe = NULL;
426 bool raw_mode = atomisp_is_mbuscode_raw(
427 asd->fmt[asd->capture_pad].fmt.code);
429 if (asd->isp->inputs[asd->input_curr].camera_caps->
430 sensor[asd->sensor_curr].stream_num == 2 &&
432 return atomisp_qbuffers_to_css_for_all_pipes(asd);
434 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
435 video_pipe = &asd->video_out_video_capture;
436 css_video_pipe_id = CSS_PIPE_ID_VIDEO;
437 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
438 preview_pipe = &asd->video_out_capture;
439 css_preview_pipe_id = CSS_PIPE_ID_CAPTURE;
440 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
441 if (asd->continuous_mode->val) {
442 capture_pipe = &asd->video_out_capture;
443 vf_pipe = &asd->video_out_vf;
444 css_capture_pipe_id = CSS_PIPE_ID_CAPTURE;
446 video_pipe = &asd->video_out_video_capture;
447 preview_pipe = &asd->video_out_preview;
448 css_video_pipe_id = CSS_PIPE_ID_VIDEO;
449 css_preview_pipe_id = CSS_PIPE_ID_VIDEO;
450 } else if (asd->continuous_mode->val) {
451 capture_pipe = &asd->video_out_capture;
452 vf_pipe = &asd->video_out_vf;
453 preview_pipe = &asd->video_out_preview;
455 css_preview_pipe_id = CSS_PIPE_ID_PREVIEW;
456 css_capture_pipe_id = CSS_PIPE_ID_CAPTURE;
457 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) {
458 preview_pipe = &asd->video_out_preview;
459 css_preview_pipe_id = CSS_PIPE_ID_PREVIEW;
461 /* ATOMISP_RUN_MODE_STILL_CAPTURE */
462 capture_pipe = &asd->video_out_capture;
464 vf_pipe = &asd->video_out_vf;
465 css_capture_pipe_id = CSS_PIPE_ID_CAPTURE;
468 #ifdef ISP2401_NEW_INPUT_SYSTEM
469 if (asd->copy_mode) {
470 css_capture_pipe_id = CSS_PIPE_ID_COPY;
471 css_preview_pipe_id = CSS_PIPE_ID_COPY;
472 css_video_pipe_id = CSS_PIPE_ID_COPY;
476 if (asd->yuvpp_mode) {
477 capture_pipe = &asd->video_out_capture;
478 video_pipe = &asd->video_out_video_capture;
479 preview_pipe = &asd->video_out_preview;
480 css_capture_pipe_id = CSS_PIPE_ID_COPY;
481 css_video_pipe_id = CSS_PIPE_ID_YUVPP;
482 css_preview_pipe_id = CSS_PIPE_ID_YUVPP;
486 buf_type = atomisp_get_css_buf_type(
487 asd, css_capture_pipe_id,
488 atomisp_subdev_source_pad(&capture_pipe->vdev));
489 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
492 * use yuvpp pipe for SOC camera.
494 if (ATOMISP_USE_YUVPP(asd))
495 css_capture_pipe_id = CSS_PIPE_ID_YUVPP;
497 atomisp_q_video_buffers_to_css(asd, capture_pipe,
499 buf_type, css_capture_pipe_id);
503 buf_type = atomisp_get_css_buf_type(
504 asd, css_capture_pipe_id,
505 atomisp_subdev_source_pad(&vf_pipe->vdev));
506 if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream)
507 input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW;
509 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
512 * use yuvpp pipe for SOC camera.
514 if (ATOMISP_USE_YUVPP(asd))
515 css_capture_pipe_id = CSS_PIPE_ID_YUVPP;
516 atomisp_q_video_buffers_to_css(asd, vf_pipe,
518 buf_type, css_capture_pipe_id);
522 buf_type = atomisp_get_css_buf_type(
523 asd, css_preview_pipe_id,
524 atomisp_subdev_source_pad(&preview_pipe->vdev));
525 if (ATOMISP_SOC_CAMERA(asd) && css_preview_pipe_id == CSS_PIPE_ID_YUVPP)
526 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
527 /* else for ext isp use case */
528 else if (css_preview_pipe_id == CSS_PIPE_ID_YUVPP)
529 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
530 else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream)
531 input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW;
533 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
536 * use yuvpp pipe for SOC camera.
538 if (ATOMISP_USE_YUVPP(asd))
539 css_preview_pipe_id = CSS_PIPE_ID_YUVPP;
541 atomisp_q_video_buffers_to_css(asd, preview_pipe,
543 buf_type, css_preview_pipe_id);
547 buf_type = atomisp_get_css_buf_type(
548 asd, css_video_pipe_id,
549 atomisp_subdev_source_pad(&video_pipe->vdev));
550 if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream)
551 input_stream_id = ATOMISP_INPUT_STREAM_VIDEO;
553 input_stream_id = ATOMISP_INPUT_STREAM_GENERAL;
556 * use yuvpp pipe for SOC camera.
558 if (ATOMISP_USE_YUVPP(asd))
559 css_video_pipe_id = CSS_PIPE_ID_YUVPP;
561 atomisp_q_video_buffers_to_css(asd, video_pipe,
563 buf_type, css_video_pipe_id);
569 static void atomisp_buf_queue(struct videobuf_queue *vq,
570 struct videobuf_buffer *vb)
572 struct atomisp_video_pipe *pipe = vq->priv_data;
575 * when a frame buffer meets following conditions, it should be put into
577 * 1. It is not a main output frame, and it has a per-frame parameter
579 * 2. It is not a main output frame, and the waiting buffer list is not
580 * empty, to keep the FIFO sequence of frame buffer processing, it
581 * is put to waiting list until previous per-frame parameter buffers
584 if (!atomisp_is_vf_pipe(pipe) &&
585 (pipe->frame_request_config_id[vb->i] ||
586 !list_empty(&pipe->buffers_waiting_for_param)))
587 list_add_tail(&vb->queue, &pipe->buffers_waiting_for_param);
589 list_add_tail(&vb->queue, &pipe->activeq);
591 vb->state = VIDEOBUF_QUEUED;
594 static void atomisp_buf_release(struct videobuf_queue *vq,
595 struct videobuf_buffer *vb)
597 vb->state = VIDEOBUF_NEEDS_INIT;
598 atomisp_videobuf_free_buf(vb);
601 static int atomisp_buf_setup_output(struct videobuf_queue *vq,
602 unsigned int *count, unsigned int *size)
604 struct atomisp_video_pipe *pipe = vq->priv_data;
606 *size = pipe->pix.sizeimage;
611 static int atomisp_buf_prepare_output(struct videobuf_queue *vq,
612 struct videobuf_buffer *vb,
613 enum v4l2_field field)
615 struct atomisp_video_pipe *pipe = vq->priv_data;
617 vb->size = pipe->pix.sizeimage;
618 vb->width = pipe->pix.width;
619 vb->height = pipe->pix.height;
621 vb->state = VIDEOBUF_PREPARED;
626 static void atomisp_buf_queue_output(struct videobuf_queue *vq,
627 struct videobuf_buffer *vb)
629 struct atomisp_video_pipe *pipe = vq->priv_data;
631 list_add_tail(&vb->queue, &pipe->activeq_out);
632 vb->state = VIDEOBUF_QUEUED;
635 static void atomisp_buf_release_output(struct videobuf_queue *vq,
636 struct videobuf_buffer *vb)
638 videobuf_vmalloc_free(vb);
639 vb->state = VIDEOBUF_NEEDS_INIT;
642 static const struct videobuf_queue_ops videobuf_qops = {
643 .buf_setup = atomisp_buf_setup,
644 .buf_prepare = atomisp_buf_prepare,
645 .buf_queue = atomisp_buf_queue,
646 .buf_release = atomisp_buf_release,
649 static const struct videobuf_queue_ops videobuf_qops_output = {
650 .buf_setup = atomisp_buf_setup_output,
651 .buf_prepare = atomisp_buf_prepare_output,
652 .buf_queue = atomisp_buf_queue_output,
653 .buf_release = atomisp_buf_release_output,
656 static int atomisp_init_pipe(struct atomisp_video_pipe *pipe)
659 spin_lock_init(&pipe->irq_lock);
661 videobuf_queue_vmalloc_init(&pipe->capq, &videobuf_qops, NULL,
663 V4L2_BUF_TYPE_VIDEO_CAPTURE,
665 sizeof(struct atomisp_buffer), pipe,
666 NULL); /* ext_lock: NULL */
668 videobuf_queue_vmalloc_init(&pipe->outq, &videobuf_qops_output, NULL,
670 V4L2_BUF_TYPE_VIDEO_OUTPUT,
672 sizeof(struct atomisp_buffer), pipe,
673 NULL); /* ext_lock: NULL */
675 INIT_LIST_HEAD(&pipe->activeq);
676 INIT_LIST_HEAD(&pipe->activeq_out);
677 INIT_LIST_HEAD(&pipe->buffers_waiting_for_param);
678 INIT_LIST_HEAD(&pipe->per_frame_params);
679 memset(pipe->frame_request_config_id, 0,
680 VIDEO_MAX_FRAME * sizeof(unsigned int));
681 memset(pipe->frame_params, 0,
683 sizeof(struct atomisp_css_params_with_list *));
688 static void atomisp_dev_init_struct(struct atomisp_device *isp)
692 isp->sw_contex.file_input = 0;
693 isp->need_gfx_throttle = true;
694 isp->isp_fatal_error = false;
695 isp->mipi_frame_size = 0;
697 for (i = 0; i < isp->input_cnt; i++)
698 isp->inputs[i].asd = NULL;
700 * For Merrifield, frequency is scalable.
701 * After boot-up, the default frequency is 200MHz.
703 isp->sw_contex.running_freq = ISP_FREQ_200MHZ;
706 static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd)
708 v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_STILL_CAPTURE);
709 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
710 asd->params.color_effect = V4L2_COLORFX_NONE;
711 asd->params.bad_pixel_en = 1;
712 asd->params.gdc_cac_en = 0;
713 asd->params.video_dis_en = 0;
714 asd->params.sc_en = 0;
715 asd->params.fpn_en = 0;
716 asd->params.xnr_en = 0;
717 asd->params.false_color = 0;
718 asd->params.online_process = 1;
719 asd->params.yuv_ds_en = 0;
720 /* s3a grid not enabled for any pipe */
721 asd->params.s3a_enabled_pipe = CSS_PIPE_ID_NUM;
723 asd->params.offline_parm.num_captures = 1;
724 asd->params.offline_parm.skip_frames = 0;
725 asd->params.offline_parm.offset = 0;
726 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED;
727 /* Add for channel */
730 asd->mipi_frame_size = 0;
731 asd->copy_mode = false;
732 asd->yuvpp_mode = false;
734 asd->stream_prepared = false;
735 asd->high_speed_mode = false;
736 asd->sensor_array_res.height = 0;
737 asd->sensor_array_res.width = 0;
738 atomisp_css_init_struct(asd);
741 * file operation functions
743 static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)
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 +
753 unsigned int atomisp_dev_users(struct atomisp_device *isp)
756 for (i = 0, sum = 0; i < isp->num_of_streams; i++)
757 sum += atomisp_subdev_users(&isp->asd[i]);
762 static int atomisp_open(struct file *file)
764 struct video_device *vdev = video_devdata(file);
765 struct atomisp_device *isp = video_get_drvdata(vdev);
766 struct atomisp_video_pipe *pipe = NULL;
767 struct atomisp_acc_pipe *acc_pipe = NULL;
768 struct atomisp_sub_device *asd;
769 bool acc_node = false;
772 dev_dbg(isp->dev, "open device %s\n", vdev->name);
774 rt_mutex_lock(&isp->mutex);
776 acc_node = !strncmp(vdev->name, "ATOMISP ISP ACC",
779 acc_pipe = atomisp_to_acc_pipe(vdev);
782 pipe = atomisp_to_video_pipe(vdev);
785 asd->subdev.devnode = vdev;
786 /* Deferred firmware loading case. */
787 if (isp->css_env.isp_css_fw.bytes == 0) {
788 isp->firmware = atomisp_load_firmware(isp);
789 if (!isp->firmware) {
790 dev_err(isp->dev, "Failed to load ISP firmware.\n");
794 ret = atomisp_css_load_firmware(isp);
796 dev_err(isp->dev, "Failed to init css.\n");
799 /* No need to keep FW in memory anymore. */
800 release_firmware(isp->firmware);
801 isp->firmware = NULL;
802 isp->css_env.isp_css_fw.data = NULL;
805 if (acc_node && acc_pipe->users) {
806 dev_dbg(isp->dev, "acc node already opened\n");
807 rt_mutex_unlock(&isp->mutex);
809 } else if (acc_node) {
813 if (!isp->input_cnt) {
814 dev_err(isp->dev, "no camera attached\n");
820 * atomisp does not allow multiple open
823 dev_dbg(isp->dev, "video node already opened\n");
824 rt_mutex_unlock(&isp->mutex);
828 ret = atomisp_init_pipe(pipe);
833 if (atomisp_dev_users(isp)) {
834 dev_dbg(isp->dev, "skip init isp in open\n");
838 /* runtime power management, turn on ISP */
839 ret = pm_runtime_get_sync(vdev->v4l2_dev->dev);
841 dev_err(isp->dev, "Failed to power on device\n");
846 ret = hmm_pool_register(dypool_pgnr, HMM_POOL_TYPE_DYNAMIC);
848 dev_err(isp->dev, "Failed to register dynamic memory pool.\n");
852 if (atomisp_css_init(isp)) {
854 /* Need to clean up CSS init if it fails. */
858 atomisp_dev_init_struct(isp);
860 ret = v4l2_subdev_call(isp->flash, core, s_power, 1);
861 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) {
862 dev_err(isp->dev, "Failed to power-on flash\n");
867 if (atomisp_subdev_users(asd))
870 atomisp_subdev_init_struct(asd);
878 rt_mutex_unlock(&isp->mutex);
882 atomisp_css_uninit(isp);
884 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
885 pm_runtime_put(vdev->v4l2_dev->dev);
886 rt_mutex_unlock(&isp->mutex);
890 static int atomisp_release(struct file *file)
892 struct video_device *vdev = video_devdata(file);
893 struct atomisp_device *isp = video_get_drvdata(vdev);
894 struct atomisp_video_pipe *pipe;
895 struct atomisp_acc_pipe *acc_pipe;
896 struct atomisp_sub_device *asd;
898 struct v4l2_requestbuffers req;
899 struct v4l2_subdev_fh fh;
900 struct v4l2_rect clear_compose = {0};
903 v4l2_fh_init(&fh.vfh, vdev);
909 mutex_lock(&isp->streamoff_mutex);
910 rt_mutex_lock(&isp->mutex);
912 dev_dbg(isp->dev, "release device %s\n", vdev->name);
913 acc_node = !strncmp(vdev->name, "ATOMISP ISP ACC",
916 acc_pipe = atomisp_to_acc_pipe(vdev);
919 pipe = atomisp_to_video_pipe(vdev);
922 asd->subdev.devnode = vdev;
929 if (pipe->capq.streaming)
931 "%s: ISP still streaming while closing!",
934 if (pipe->capq.streaming &&
935 __atomisp_streamoff(file, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
937 "atomisp_streamoff failed on release, driver bug");
944 if (__atomisp_reqbufs(file, NULL, &req)) {
946 "atomisp_reqbufs failed on release, driver bug");
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);
957 * A little trick here:
958 * file injection input resolution is recorded in the sink pad,
959 * therefore can not be cleared when releaseing one device node.
960 * The sink pad setting can only be cleared when all device nodes
963 if (!isp->sw_contex.file_input && asd->fmt_auto->val) {
964 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
965 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
966 V4L2_SUBDEV_FORMAT_ACTIVE,
967 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
970 if (atomisp_subdev_users(asd))
973 /* clear the sink pad for file input */
974 if (isp->sw_contex.file_input && asd->fmt_auto->val) {
975 struct v4l2_mbus_framefmt isp_sink_fmt = { 0 };
976 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad,
977 V4L2_SUBDEV_FORMAT_ACTIVE,
978 ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt);
981 atomisp_css_free_stat_buffers(asd);
982 atomisp_free_internal_buffers(asd);
983 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera,
986 dev_warn(isp->dev, "Failed to power-off sensor\n");
988 /* clear the asd field to show this camera is not used */
989 isp->inputs[asd->input_curr].asd = NULL;
990 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
992 if (atomisp_dev_users(isp))
995 atomisp_acc_release(asd);
997 atomisp_destroy_pipes_stream_force(asd);
998 atomisp_css_uninit(isp);
1000 if (defer_fw_load) {
1001 atomisp_css_unload_firmware(isp);
1002 isp->css_env.isp_css_fw.data = NULL;
1003 isp->css_env.isp_css_fw.bytes = 0;
1006 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC);
1008 ret = v4l2_subdev_call(isp->flash, core, s_power, 0);
1009 if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD)
1010 dev_warn(isp->dev, "Failed to power-off flash\n");
1012 if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0)
1013 dev_err(isp->dev, "Failed to power off device\n");
1017 atomisp_subdev_set_selection(&asd->subdev, fh.pad,
1018 V4L2_SUBDEV_FORMAT_ACTIVE,
1019 atomisp_subdev_source_pad(vdev),
1020 V4L2_SEL_TGT_COMPOSE, 0,
1023 rt_mutex_unlock(&isp->mutex);
1024 mutex_unlock(&isp->streamoff_mutex);
1030 * Memory help functions for image frame and private parameters
1032 static int do_isp_mm_remap(struct atomisp_device *isp,
1033 struct vm_area_struct *vma,
1034 ia_css_ptr isp_virt, u32 host_virt, u32 pgnr)
1039 pfn = hmm_virt_to_phys(isp_virt) >> PAGE_SHIFT;
1040 if (remap_pfn_range(vma, host_virt, pfn,
1041 PAGE_SIZE, PAGE_SHARED)) {
1042 dev_err(isp->dev, "remap_pfn_range err.\n");
1046 isp_virt += PAGE_SIZE;
1047 host_virt += PAGE_SIZE;
1054 static int frame_mmap(struct atomisp_device *isp,
1055 const struct atomisp_css_frame *frame, struct vm_area_struct *vma)
1057 ia_css_ptr isp_virt;
1062 dev_err(isp->dev, "%s: NULL frame pointer.\n", __func__);
1066 host_virt = vma->vm_start;
1067 isp_virt = frame->data;
1068 atomisp_get_frame_pgnr(isp, frame, &pgnr);
1070 if (do_isp_mm_remap(isp, vma, isp_virt, host_virt, pgnr))
1076 int atomisp_videobuf_mmap_mapper(struct videobuf_queue *q,
1077 struct vm_area_struct *vma)
1079 u32 offset = vma->vm_pgoff << PAGE_SHIFT;
1080 int ret = -EINVAL, i;
1081 struct atomisp_device *isp =
1082 ((struct atomisp_video_pipe *)(q->priv_data))->isp;
1083 struct videobuf_vmalloc_memory *vm_mem;
1084 struct videobuf_mapping *map;
1086 MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);
1087 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) {
1088 dev_err(isp->dev, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1092 mutex_lock(&q->vb_lock);
1093 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1094 struct videobuf_buffer *buf = q->bufs[i];
1098 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
1100 mutex_unlock(&q->vb_lock);
1107 buf->baddr = vma->vm_start;
1109 if (buf && buf->memory == V4L2_MEMORY_MMAP &&
1110 buf->boff == offset) {
1112 ret = frame_mmap(isp, vm_mem->vaddr, vma);
1113 vma->vm_flags |= VM_IO|VM_DONTEXPAND|VM_DONTDUMP;
1117 mutex_unlock(&q->vb_lock);
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).
1126 static int remove_pad_from_frame(struct atomisp_device *isp,
1127 struct atomisp_css_frame *in_frame, __u32 width, __u32 height)
1130 unsigned short *buffer;
1132 ia_css_ptr load = in_frame->data;
1133 ia_css_ptr store = load;
1135 buffer = kmalloc(width*sizeof(load), GFP_KERNEL);
1139 load += ISP_LEFT_PAD;
1140 for (i = 0; i < height; i++) {
1141 ret = hmm_load(load, buffer, width*sizeof(load));
1143 goto remove_pad_error;
1145 ret = hmm_store(store, buffer, width*sizeof(store));
1147 goto remove_pad_error;
1149 load += in_frame->info.padded_width;
1158 static int atomisp_mmap(struct file *file, struct vm_area_struct *vma)
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 atomisp_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;
1171 if (!(vma->vm_flags & (VM_WRITE | VM_READ)))
1174 rt_mutex_lock(&isp->mutex);
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.
1183 vma->vm_flags |= VM_SHARED;
1184 ret = hmm_mmap(vma, vma->vm_pgoff << PAGE_SHIFT);
1185 rt_mutex_unlock(&isp->mutex);
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) {
1198 raw_virt_addr = asd->raw_output_frame;
1199 if (raw_virt_addr == NULL) {
1200 dev_err(isp->dev, "Failed to request RAW frame\n");
1205 ret = remove_pad_from_frame(isp, raw_virt_addr,
1206 pipe->pix.width, pipe->pix.height);
1208 dev_err(isp->dev, "remove pad failed.\n");
1211 origin_size = raw_virt_addr->data_bytes;
1212 raw_virt_addr->data_bytes = new_size;
1214 if (size != PAGE_ALIGN(new_size)) {
1215 dev_err(isp->dev, "incorrect size for mmap ISP Raw Frame\n");
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;
1226 raw_virt_addr->data_bytes = origin_size;
1227 vma->vm_flags |= VM_IO|VM_DONTEXPAND|VM_DONTDUMP;
1228 rt_mutex_unlock(&isp->mutex);
1233 * mmap for normal frames
1235 if (size != pipe->pix.sizeimage) {
1236 dev_err(isp->dev, "incorrect size for mmap ISP frames\n");
1240 rt_mutex_unlock(&isp->mutex);
1242 return atomisp_videobuf_mmap_mapper(&pipe->capq, vma);
1245 rt_mutex_unlock(&isp->mutex);
1250 static int atomisp_file_mmap(struct file *file, struct vm_area_struct *vma)
1252 struct video_device *vdev = video_devdata(file);
1253 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev);
1255 return videobuf_mmap_mapper(&pipe->outq, vma);
1258 static __poll_t atomisp_poll(struct file *file,
1259 struct poll_table_struct *pt)
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);
1265 rt_mutex_lock(&isp->mutex);
1266 if (pipe->capq.streaming != 1) {
1267 rt_mutex_unlock(&isp->mutex);
1270 rt_mutex_unlock(&isp->mutex);
1272 return videobuf_poll_stream(file, &pipe->capq, pt);
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 .compat_ioctl32 = atomisp_compat_ioctl32,
1284 .poll = atomisp_poll,
1287 const struct v4l2_file_operations atomisp_file_fops = {
1288 .owner = THIS_MODULE,
1289 .open = atomisp_open,
1290 .release = atomisp_release,
1291 .mmap = atomisp_file_mmap,
1292 .unlocked_ioctl = video_ioctl2,
1293 #ifdef CONFIG_COMPAT
1294 .compat_ioctl32 = atomisp_compat_ioctl32,
1296 .poll = atomisp_poll,