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 unsigned int 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
,