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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 #include <linux/module.h>
25 #include <linux/pm_runtime.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/videobuf-vmalloc.h>
30 #include "atomisp_cmd.h"
31 #include "atomisp_common.h"
32 #include "atomisp_fops.h"
33 #include "atomisp_internal.h"
34 #include "atomisp_ioctl.h"
35 #include "atomisp_compat.h"
36 #include "atomisp_subdev.h"
37 #include "atomisp_v4l2.h"
38 #include "atomisp-regs.h"
41 #include "hrt/hive_isp_css_mm_hrt.h"
43 #include "type_support.h"
44 #include "device_access/device_access.h"
45 #include "memory_access/memory_access.h"
47 #include "atomisp_acc.h"
49 #define ISP_LEFT_PAD 128 /* equal to 2*NWAY */
52 * input image data, and current frame resolution for test
54 #define ISP_PARAM_MMAP_OFFSET 0xfffff000
56 #define MAGIC_CHECK(is, should) \
58 if (unlikely((is) != (should))) { \
59 pr_err("magic mismatch: %x (expected %x)\n", \
68 static int atomisp_buf_setup(struct videobuf_queue
*vq
, unsigned int *count
,
71 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
73 *size
= pipe
->pix
.sizeimage
;
78 static int atomisp_buf_prepare(struct videobuf_queue
*vq
,
79 struct videobuf_buffer
*vb
,
80 enum v4l2_field field
)
82 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
84 vb
->size
= pipe
->pix
.sizeimage
;
85 vb
->width
= pipe
->pix
.width
;
86 vb
->height
= pipe
->pix
.height
;
88 vb
->state
= VIDEOBUF_PREPARED
;
93 static int atomisp_q_one_metadata_buffer(struct atomisp_sub_device
*asd
,
94 enum atomisp_input_stream_id stream_id
,
95 enum atomisp_css_pipe_id css_pipe_id
)
97 struct atomisp_metadata_buf
*metadata_buf
;
98 enum atomisp_metadata_type md_type
=
99 atomisp_get_metadata_type(asd
, css_pipe_id
);
100 struct list_head
*metadata_list
;
102 if (asd
->metadata_bufs_in_css
[stream_id
][css_pipe_id
] >=
104 return 0; /* we have reached CSS queue depth */
106 if (!list_empty(&asd
->metadata
[md_type
])) {
107 metadata_list
= &asd
->metadata
[md_type
];
108 } else if (!list_empty(&asd
->metadata_ready
[md_type
])) {
109 metadata_list
= &asd
->metadata_ready
[md_type
];
111 dev_warn(asd
->isp
->dev
, "%s: No metadata buffers available for type %d!\n",
116 metadata_buf
= list_entry(metadata_list
->next
,
117 struct atomisp_metadata_buf
, list
);
118 list_del_init(&metadata_buf
->list
);
120 if (atomisp_q_metadata_buffer_to_css(asd
, metadata_buf
,
121 stream_id
, css_pipe_id
)) {
122 list_add(&metadata_buf
->list
, metadata_list
);
125 list_add_tail(&metadata_buf
->list
,
126 &asd
->metadata_in_css
[md_type
]);
128 asd
->metadata_bufs_in_css
[stream_id
][css_pipe_id
]++;
133 static int atomisp_q_one_s3a_buffer(struct atomisp_sub_device
*asd
,
134 enum atomisp_input_stream_id stream_id
,
135 enum atomisp_css_pipe_id css_pipe_id
)
137 struct atomisp_s3a_buf
*s3a_buf
;
138 struct list_head
*s3a_list
;
141 if (asd
->s3a_bufs_in_css
[css_pipe_id
] >= ATOMISP_CSS_Q_DEPTH
)
142 return 0; /* we have reached CSS queue depth */
144 if (!list_empty(&asd
->s3a_stats
)) {
145 s3a_list
= &asd
->s3a_stats
;
146 } else if (!list_empty(&asd
->s3a_stats_ready
)) {
147 s3a_list
= &asd
->s3a_stats_ready
;
149 dev_warn(asd
->isp
->dev
, "%s: No s3a buffers available!\n",
154 s3a_buf
= list_entry(s3a_list
->next
, struct atomisp_s3a_buf
, list
);
155 list_del_init(&s3a_buf
->list
);
156 exp_id
= s3a_buf
->s3a_data
->exp_id
;
158 hmm_flush_vmap(s3a_buf
->s3a_data
->data_ptr
);
159 if (atomisp_q_s3a_buffer_to_css(asd
, s3a_buf
,
160 stream_id
, css_pipe_id
)) {
161 /* got from head, so return back to the head */
162 list_add(&s3a_buf
->list
, s3a_list
);
165 list_add_tail(&s3a_buf
->list
, &asd
->s3a_stats_in_css
);
166 if (s3a_list
== &asd
->s3a_stats_ready
)
167 dev_warn(asd
->isp
->dev
, "%s: drop one s3a stat which has exp_id %d!\n",
171 asd
->s3a_bufs_in_css
[css_pipe_id
]++;
175 static int atomisp_q_one_dis_buffer(struct atomisp_sub_device
*asd
,
176 enum atomisp_input_stream_id stream_id
,
177 enum atomisp_css_pipe_id css_pipe_id
)
179 struct atomisp_dis_buf
*dis_buf
;
180 unsigned long irqflags
;
182 if (asd
->dis_bufs_in_css
>= ATOMISP_CSS_Q_DEPTH
)
183 return 0; /* we have reached CSS queue depth */
185 spin_lock_irqsave(&asd
->dis_stats_lock
, irqflags
);
186 if (list_empty(&asd
->dis_stats
)) {
187 spin_unlock_irqrestore(&asd
->dis_stats_lock
, irqflags
);
188 dev_warn(asd
->isp
->dev
, "%s: No dis buffers available!\n",
193 dis_buf
= list_entry(asd
->dis_stats
.prev
,
194 struct atomisp_dis_buf
, list
);
195 list_del_init(&dis_buf
->list
);
196 spin_unlock_irqrestore(&asd
->dis_stats_lock
, irqflags
);
198 hmm_flush_vmap(dis_buf
->dis_data
->data_ptr
);
199 if (atomisp_q_dis_buffer_to_css(asd
, dis_buf
,
200 stream_id
, css_pipe_id
)) {
201 spin_lock_irqsave(&asd
->dis_stats_lock
, irqflags
);
202 /* got from tail, so return back to the tail */
203 list_add_tail(&dis_buf
->list
, &asd
->dis_stats
);
204 spin_unlock_irqrestore(&asd
->dis_stats_lock
, irqflags
);
207 spin_lock_irqsave(&asd
->dis_stats_lock
, irqflags
);
208 list_add_tail(&dis_buf
->list
, &asd
->dis_stats_in_css
);
209 spin_unlock_irqrestore(&asd
->dis_stats_lock
, irqflags
);
212 asd
->dis_bufs_in_css
++;
217 int atomisp_q_video_buffers_to_css(struct atomisp_sub_device
*asd
,
218 struct atomisp_video_pipe
*pipe
,
219 enum atomisp_input_stream_id stream_id
,
220 enum atomisp_css_buffer_type css_buf_type
,
221 enum atomisp_css_pipe_id css_pipe_id
)
223 struct videobuf_vmalloc_memory
*vm_mem
;
224 struct atomisp_css_params_with_list
*param
;
225 struct atomisp_css_dvs_grid_info
*dvs_grid
=
226 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
227 unsigned long irqflags
;
230 while (pipe
->buffers_in_css
< ATOMISP_CSS_Q_DEPTH
) {
231 struct videobuf_buffer
*vb
;
233 spin_lock_irqsave(&pipe
->irq_lock
, irqflags
);
234 if (list_empty(&pipe
->activeq
)) {
235 spin_unlock_irqrestore(&pipe
->irq_lock
, irqflags
);
238 vb
= list_entry(pipe
->activeq
.next
,
239 struct videobuf_buffer
, queue
);
240 list_del_init(&vb
->queue
);
241 vb
->state
= VIDEOBUF_ACTIVE
;
242 spin_unlock_irqrestore(&pipe
->irq_lock
, irqflags
);
245 * If there is a per_frame setting to apply on the buffer,
246 * do it before buffer en-queueing.
250 param
= pipe
->frame_params
[vb
->i
];
252 atomisp_makeup_css_parameters(asd
,
253 &asd
->params
.css_param
.update_flag
,
255 atomisp_apply_css_parameters(asd
, ¶m
->params
);
257 if (param
->params
.update_flag
.dz_config
&&
258 asd
->run_mode
->val
!= ATOMISP_RUN_MODE_VIDEO
) {
259 err
= atomisp_calculate_real_zoom_region(asd
,
260 ¶m
->params
.dz_config
, css_pipe_id
);
262 atomisp_css_set_dz_config(asd
,
263 ¶m
->params
.dz_config
);
265 atomisp_css_set_isp_config_applied_frame(asd
,
267 atomisp_css_update_isp_params_on_pipe(asd
,
268 asd
->stream_env
[stream_id
].pipes
[css_pipe_id
]);
269 asd
->params
.dvs_6axis
= (struct atomisp_css_dvs_6axis
*)
270 param
->params
.dvs_6axis
;
274 * Because the camera halv3 can't ensure to set zoom
275 * region to per_frame setting and global setting at
276 * same time and only set zoom region to pre_frame
277 * setting now.so when the pre_frame setting inculde
278 * zoom region,I will set it to global setting.
280 if (param
->params
.update_flag
.dz_config
&&
281 asd
->run_mode
->val
!= ATOMISP_RUN_MODE_VIDEO
283 memcpy(&asd
->params
.css_param
.dz_config
,
284 ¶m
->params
.dz_config
,
285 sizeof(struct ia_css_dz_config
));
286 asd
->params
.css_param
.update_flag
.dz_config
=
287 (struct atomisp_dz_config
*)
288 &asd
->params
.css_param
.dz_config
;
289 asd
->params
.css_update_params_needed
= true;
293 err
= atomisp_q_video_buffer_to_css(asd
, vm_mem
, stream_id
,
294 css_buf_type
, css_pipe_id
);
296 spin_lock_irqsave(&pipe
->irq_lock
, irqflags
);
297 list_add_tail(&vb
->queue
, &pipe
->activeq
);
298 vb
->state
= VIDEOBUF_QUEUED
;
299 spin_unlock_irqrestore(&pipe
->irq_lock
, irqflags
);
300 dev_err(asd
->isp
->dev
, "%s, css q fails: %d\n",
304 pipe
->buffers_in_css
++;
306 /* enqueue 3A/DIS/metadata buffers */
307 if (asd
->params
.curr_grid_info
.s3a_grid
.enable
&&
308 css_pipe_id
== asd
->params
.s3a_enabled_pipe
&&
309 css_buf_type
== CSS_BUFFER_TYPE_OUTPUT_FRAME
)
310 atomisp_q_one_s3a_buffer(asd
, stream_id
,
313 if (asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream_info
.
314 metadata_info
.size
&&
315 css_buf_type
== CSS_BUFFER_TYPE_OUTPUT_FRAME
)
316 atomisp_q_one_metadata_buffer(asd
, stream_id
,
319 if (dvs_grid
&& dvs_grid
->enable
&&
320 css_pipe_id
== CSS_PIPE_ID_VIDEO
&&
321 css_buf_type
== CSS_BUFFER_TYPE_OUTPUT_FRAME
)
322 atomisp_q_one_dis_buffer(asd
, stream_id
,
329 static int atomisp_get_css_buf_type(struct atomisp_sub_device
*asd
,
330 enum atomisp_css_pipe_id pipe_id
,
333 if (ATOMISP_USE_YUVPP(asd
)) {
334 /* when run ZSL case */
335 if (asd
->continuous_mode
->val
&&
336 asd
->run_mode
->val
== ATOMISP_RUN_MODE_PREVIEW
) {
337 if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
)
338 return CSS_BUFFER_TYPE_OUTPUT_FRAME
;
339 else if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
)
340 return CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
;
342 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
;
345 /*when run SDV case*/
346 if (asd
->continuous_mode
->val
&&
347 asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
) {
348 if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
)
349 return CSS_BUFFER_TYPE_OUTPUT_FRAME
;
350 else if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
)
351 return CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME
;
352 else if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_VIDEO
)
353 return CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
;
355 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
;
358 /*other case: default setting*/
359 if (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
||
360 source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_VIDEO
||
361 (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
&&
362 asd
->run_mode
->val
!= ATOMISP_RUN_MODE_VIDEO
))
363 return CSS_BUFFER_TYPE_OUTPUT_FRAME
;
365 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
;
368 if (pipe_id
== CSS_PIPE_ID_COPY
||
369 source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
||
370 source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_VIDEO
||
371 (source_pad
== ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
&&
372 asd
->run_mode
->val
!= ATOMISP_RUN_MODE_VIDEO
))
373 return CSS_BUFFER_TYPE_OUTPUT_FRAME
;
375 return CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
;
378 static int atomisp_qbuffers_to_css_for_all_pipes(struct atomisp_sub_device
*asd
)
380 enum atomisp_css_buffer_type buf_type
;
381 enum atomisp_css_pipe_id css_capture_pipe_id
= CSS_PIPE_ID_COPY
;
382 enum atomisp_css_pipe_id css_preview_pipe_id
= CSS_PIPE_ID_COPY
;
383 enum atomisp_css_pipe_id css_video_pipe_id
= CSS_PIPE_ID_COPY
;
384 enum atomisp_input_stream_id input_stream_id
;
385 struct atomisp_video_pipe
*capture_pipe
;
386 struct atomisp_video_pipe
*preview_pipe
;
387 struct atomisp_video_pipe
*video_pipe
;
389 capture_pipe
= &asd
->video_out_capture
;
390 preview_pipe
= &asd
->video_out_preview
;
391 video_pipe
= &asd
->video_out_video_capture
;
393 buf_type
= atomisp_get_css_buf_type(
394 asd
, css_preview_pipe_id
,
395 atomisp_subdev_source_pad(&preview_pipe
->vdev
));
396 input_stream_id
= ATOMISP_INPUT_STREAM_PREVIEW
;
397 atomisp_q_video_buffers_to_css(asd
, preview_pipe
,
399 buf_type
, css_preview_pipe_id
);
401 buf_type
= atomisp_get_css_buf_type(asd
, css_capture_pipe_id
,
402 atomisp_subdev_source_pad(&capture_pipe
->vdev
));
403 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
404 atomisp_q_video_buffers_to_css(asd
, capture_pipe
,
406 buf_type
, css_capture_pipe_id
);
408 buf_type
= atomisp_get_css_buf_type(asd
, css_video_pipe_id
,
409 atomisp_subdev_source_pad(&video_pipe
->vdev
));
410 input_stream_id
= ATOMISP_INPUT_STREAM_VIDEO
;
411 atomisp_q_video_buffers_to_css(asd
, video_pipe
,
413 buf_type
, css_video_pipe_id
);
418 /* queue all available buffers to css */
419 int atomisp_qbuffers_to_css(struct atomisp_sub_device
*asd
)
421 enum atomisp_css_buffer_type buf_type
;
422 enum atomisp_css_pipe_id css_capture_pipe_id
= CSS_PIPE_ID_NUM
;
423 enum atomisp_css_pipe_id css_preview_pipe_id
= CSS_PIPE_ID_NUM
;
424 enum atomisp_css_pipe_id css_video_pipe_id
= CSS_PIPE_ID_NUM
;
425 enum atomisp_input_stream_id input_stream_id
;
426 struct atomisp_video_pipe
*capture_pipe
= NULL
;
427 struct atomisp_video_pipe
*vf_pipe
= NULL
;
428 struct atomisp_video_pipe
*preview_pipe
= NULL
;
429 struct atomisp_video_pipe
*video_pipe
= NULL
;
430 bool raw_mode
= atomisp_is_mbuscode_raw(
431 asd
->fmt
[asd
->capture_pad
].fmt
.code
);
433 if (asd
->isp
->inputs
[asd
->input_curr
].camera_caps
->
434 sensor
[asd
->sensor_curr
].stream_num
== 2 &&
436 return atomisp_qbuffers_to_css_for_all_pipes(asd
);
438 if (asd
->vfpp
->val
== ATOMISP_VFPP_DISABLE_SCALER
) {
439 video_pipe
= &asd
->video_out_video_capture
;
440 css_video_pipe_id
= CSS_PIPE_ID_VIDEO
;
441 } else if (asd
->vfpp
->val
== ATOMISP_VFPP_DISABLE_LOWLAT
) {
442 preview_pipe
= &asd
->video_out_capture
;
443 css_preview_pipe_id
= CSS_PIPE_ID_CAPTURE
;
444 } else if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
) {
445 if (asd
->continuous_mode
->val
) {
446 capture_pipe
= &asd
->video_out_capture
;
447 vf_pipe
= &asd
->video_out_vf
;
448 css_capture_pipe_id
= CSS_PIPE_ID_CAPTURE
;
450 video_pipe
= &asd
->video_out_video_capture
;
451 preview_pipe
= &asd
->video_out_preview
;
452 css_video_pipe_id
= CSS_PIPE_ID_VIDEO
;
453 css_preview_pipe_id
= CSS_PIPE_ID_VIDEO
;
454 } else if (asd
->continuous_mode
->val
) {
455 capture_pipe
= &asd
->video_out_capture
;
456 vf_pipe
= &asd
->video_out_vf
;
457 preview_pipe
= &asd
->video_out_preview
;
459 css_preview_pipe_id
= CSS_PIPE_ID_PREVIEW
;
460 css_capture_pipe_id
= CSS_PIPE_ID_CAPTURE
;
461 } else if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_PREVIEW
) {
462 preview_pipe
= &asd
->video_out_preview
;
463 css_preview_pipe_id
= CSS_PIPE_ID_PREVIEW
;
465 /* ATOMISP_RUN_MODE_STILL_CAPTURE */
466 capture_pipe
= &asd
->video_out_capture
;
468 vf_pipe
= &asd
->video_out_vf
;
469 css_capture_pipe_id
= CSS_PIPE_ID_CAPTURE
;
472 #ifdef ISP2401_NEW_INPUT_SYSTEM
473 if (asd
->copy_mode
) {
474 css_capture_pipe_id
= CSS_PIPE_ID_COPY
;
475 css_preview_pipe_id
= CSS_PIPE_ID_COPY
;
476 css_video_pipe_id
= CSS_PIPE_ID_COPY
;
480 if (asd
->yuvpp_mode
) {
481 capture_pipe
= &asd
->video_out_capture
;
482 video_pipe
= &asd
->video_out_video_capture
;
483 preview_pipe
= &asd
->video_out_preview
;
484 css_capture_pipe_id
= CSS_PIPE_ID_COPY
;
485 css_video_pipe_id
= CSS_PIPE_ID_YUVPP
;
486 css_preview_pipe_id
= CSS_PIPE_ID_YUVPP
;
490 buf_type
= atomisp_get_css_buf_type(
491 asd
, css_capture_pipe_id
,
492 atomisp_subdev_source_pad(&capture_pipe
->vdev
));
493 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
496 * use yuvpp pipe for SOC camera.
498 if (ATOMISP_USE_YUVPP(asd
))
499 css_capture_pipe_id
= CSS_PIPE_ID_YUVPP
;
501 atomisp_q_video_buffers_to_css(asd
, capture_pipe
,
503 buf_type
, css_capture_pipe_id
);
507 buf_type
= atomisp_get_css_buf_type(
508 asd
, css_capture_pipe_id
,
509 atomisp_subdev_source_pad(&vf_pipe
->vdev
));
510 if (asd
->stream_env
[ATOMISP_INPUT_STREAM_POSTVIEW
].stream
)
511 input_stream_id
= ATOMISP_INPUT_STREAM_POSTVIEW
;
513 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
516 * use yuvpp pipe for SOC camera.
518 if (ATOMISP_USE_YUVPP(asd
))
519 css_capture_pipe_id
= CSS_PIPE_ID_YUVPP
;
520 atomisp_q_video_buffers_to_css(asd
, vf_pipe
,
522 buf_type
, css_capture_pipe_id
);
526 buf_type
= atomisp_get_css_buf_type(
527 asd
, css_preview_pipe_id
,
528 atomisp_subdev_source_pad(&preview_pipe
->vdev
));
529 if (ATOMISP_SOC_CAMERA(asd
) && css_preview_pipe_id
== CSS_PIPE_ID_YUVPP
)
530 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
531 /* else for ext isp use case */
532 else if (css_preview_pipe_id
== CSS_PIPE_ID_YUVPP
)
533 input_stream_id
= ATOMISP_INPUT_STREAM_VIDEO
;
534 else if (asd
->stream_env
[ATOMISP_INPUT_STREAM_PREVIEW
].stream
)
535 input_stream_id
= ATOMISP_INPUT_STREAM_PREVIEW
;
537 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
540 * use yuvpp pipe for SOC camera.
542 if (ATOMISP_USE_YUVPP(asd
))
543 css_preview_pipe_id
= CSS_PIPE_ID_YUVPP
;
545 atomisp_q_video_buffers_to_css(asd
, preview_pipe
,
547 buf_type
, css_preview_pipe_id
);
551 buf_type
= atomisp_get_css_buf_type(
552 asd
, css_video_pipe_id
,
553 atomisp_subdev_source_pad(&video_pipe
->vdev
));
554 if (asd
->stream_env
[ATOMISP_INPUT_STREAM_VIDEO
].stream
)
555 input_stream_id
= ATOMISP_INPUT_STREAM_VIDEO
;
557 input_stream_id
= ATOMISP_INPUT_STREAM_GENERAL
;
560 * use yuvpp pipe for SOC camera.
562 if (ATOMISP_USE_YUVPP(asd
))
563 css_video_pipe_id
= CSS_PIPE_ID_YUVPP
;
565 atomisp_q_video_buffers_to_css(asd
, video_pipe
,
567 buf_type
, css_video_pipe_id
);
573 static void atomisp_buf_queue(struct videobuf_queue
*vq
,
574 struct videobuf_buffer
*vb
)
576 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
579 * when a frame buffer meets following conditions, it should be put into
581 * 1. It is not a main output frame, and it has a per-frame parameter
583 * 2. It is not a main output frame, and the waiting buffer list is not
584 * empty, to keep the FIFO sequence of frame buffer processing, it
585 * is put to waiting list until previous per-frame parameter buffers
588 if (!atomisp_is_vf_pipe(pipe
) &&
589 (pipe
->frame_request_config_id
[vb
->i
] ||
590 !list_empty(&pipe
->buffers_waiting_for_param
)))
591 list_add_tail(&vb
->queue
, &pipe
->buffers_waiting_for_param
);
593 list_add_tail(&vb
->queue
, &pipe
->activeq
);
595 vb
->state
= VIDEOBUF_QUEUED
;
598 static void atomisp_buf_release(struct videobuf_queue
*vq
,
599 struct videobuf_buffer
*vb
)
601 vb
->state
= VIDEOBUF_NEEDS_INIT
;
602 atomisp_videobuf_free_buf(vb
);
605 static int atomisp_buf_setup_output(struct videobuf_queue
*vq
,
606 unsigned int *count
, unsigned int *size
)
608 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
610 *size
= pipe
->pix
.sizeimage
;
615 static int atomisp_buf_prepare_output(struct videobuf_queue
*vq
,
616 struct videobuf_buffer
*vb
,
617 enum v4l2_field field
)
619 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
621 vb
->size
= pipe
->pix
.sizeimage
;
622 vb
->width
= pipe
->pix
.width
;
623 vb
->height
= pipe
->pix
.height
;
625 vb
->state
= VIDEOBUF_PREPARED
;
630 static void atomisp_buf_queue_output(struct videobuf_queue
*vq
,
631 struct videobuf_buffer
*vb
)
633 struct atomisp_video_pipe
*pipe
= vq
->priv_data
;
635 list_add_tail(&vb
->queue
, &pipe
->activeq_out
);
636 vb
->state
= VIDEOBUF_QUEUED
;
639 static void atomisp_buf_release_output(struct videobuf_queue
*vq
,
640 struct videobuf_buffer
*vb
)
642 videobuf_vmalloc_free(vb
);
643 vb
->state
= VIDEOBUF_NEEDS_INIT
;
646 static const struct videobuf_queue_ops videobuf_qops
= {
647 .buf_setup
= atomisp_buf_setup
,
648 .buf_prepare
= atomisp_buf_prepare
,
649 .buf_queue
= atomisp_buf_queue
,
650 .buf_release
= atomisp_buf_release
,
653 static const struct videobuf_queue_ops videobuf_qops_output
= {
654 .buf_setup
= atomisp_buf_setup_output
,
655 .buf_prepare
= atomisp_buf_prepare_output
,
656 .buf_queue
= atomisp_buf_queue_output
,
657 .buf_release
= atomisp_buf_release_output
,
660 static int atomisp_init_pipe(struct atomisp_video_pipe
*pipe
)
663 spin_lock_init(&pipe
->irq_lock
);
665 videobuf_queue_vmalloc_init(&pipe
->capq
, &videobuf_qops
, NULL
,
667 V4L2_BUF_TYPE_VIDEO_CAPTURE
,
669 sizeof(struct atomisp_buffer
), pipe
,
670 NULL
); /* ext_lock: NULL */
672 videobuf_queue_vmalloc_init(&pipe
->outq
, &videobuf_qops_output
, NULL
,
674 V4L2_BUF_TYPE_VIDEO_OUTPUT
,
676 sizeof(struct atomisp_buffer
), pipe
,
677 NULL
); /* ext_lock: NULL */
679 INIT_LIST_HEAD(&pipe
->activeq
);
680 INIT_LIST_HEAD(&pipe
->activeq_out
);
681 INIT_LIST_HEAD(&pipe
->buffers_waiting_for_param
);
682 INIT_LIST_HEAD(&pipe
->per_frame_params
);
683 memset(pipe
->frame_request_config_id
, 0,
684 VIDEO_MAX_FRAME
* sizeof(unsigned int));
685 memset(pipe
->frame_params
, 0,
687 sizeof(struct atomisp_css_params_with_list
*));
692 static void atomisp_dev_init_struct(struct atomisp_device
*isp
)
696 isp
->sw_contex
.file_input
= 0;
697 isp
->need_gfx_throttle
= true;
698 isp
->isp_fatal_error
= false;
699 isp
->mipi_frame_size
= 0;
701 for (i
= 0; i
< isp
->input_cnt
; i
++)
702 isp
->inputs
[i
].asd
= NULL
;
704 * For Merrifield, frequency is scalable.
705 * After boot-up, the default frequency is 200MHz.
707 isp
->sw_contex
.running_freq
= ISP_FREQ_200MHZ
;
710 static void atomisp_subdev_init_struct(struct atomisp_sub_device
*asd
)
712 v4l2_ctrl_s_ctrl(asd
->run_mode
, ATOMISP_RUN_MODE_STILL_CAPTURE
);
713 memset(&asd
->params
.css_param
, 0, sizeof(asd
->params
.css_param
));
714 asd
->params
.color_effect
= V4L2_COLORFX_NONE
;
715 asd
->params
.bad_pixel_en
= 1;
716 asd
->params
.gdc_cac_en
= 0;
717 asd
->params
.video_dis_en
= 0;
718 asd
->params
.sc_en
= 0;
719 asd
->params
.fpn_en
= 0;
720 asd
->params
.xnr_en
= 0;
721 asd
->params
.false_color
= 0;
722 asd
->params
.online_process
= 1;
723 asd
->params
.yuv_ds_en
= 0;
724 /* s3a grid not enabled for any pipe */
725 asd
->params
.s3a_enabled_pipe
= CSS_PIPE_ID_NUM
;
727 asd
->params
.offline_parm
.num_captures
= 1;
728 asd
->params
.offline_parm
.skip_frames
= 0;
729 asd
->params
.offline_parm
.offset
= 0;
730 asd
->delayed_init
= ATOMISP_DELAYED_INIT_NOT_QUEUED
;
731 /* Add for channel */
734 asd
->mipi_frame_size
= 0;
735 asd
->copy_mode
= false;
736 asd
->yuvpp_mode
= false;
738 asd
->stream_prepared
= false;
739 asd
->high_speed_mode
= false;
740 asd
->sensor_array_res
.height
= 0;
741 asd
->sensor_array_res
.width
= 0;
742 atomisp_css_init_struct(asd
);
745 * file operation functions
747 static unsigned int atomisp_subdev_users(struct atomisp_sub_device
*asd
)
749 return asd
->video_out_preview
.users
+
750 asd
->video_out_vf
.users
+
751 asd
->video_out_capture
.users
+
752 asd
->video_out_video_capture
.users
+
753 asd
->video_acc
.users
+
757 unsigned int atomisp_dev_users(struct atomisp_device
*isp
)
760 for (i
= 0, sum
= 0; i
< isp
->num_of_streams
; i
++)
761 sum
+= atomisp_subdev_users(&isp
->asd
[i
]);
766 static int atomisp_open(struct file
*file
)
768 struct video_device
*vdev
= video_devdata(file
);
769 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
770 struct atomisp_video_pipe
*pipe
= NULL
;
771 struct atomisp_acc_pipe
*acc_pipe
= NULL
;
772 struct atomisp_sub_device
*asd
;
773 bool acc_node
= false;
776 dev_dbg(isp
->dev
, "open device %s\n", vdev
->name
);
778 rt_mutex_lock(&isp
->mutex
);
780 acc_node
= !strncmp(vdev
->name
, "ATOMISP ISP ACC",
783 acc_pipe
= atomisp_to_acc_pipe(vdev
);
786 pipe
= atomisp_to_video_pipe(vdev
);
789 asd
->subdev
.devnode
= vdev
;
790 /* Deferred firmware loading case. */
791 if (isp
->css_env
.isp_css_fw
.bytes
== 0) {
792 isp
->firmware
= atomisp_load_firmware(isp
);
793 if (!isp
->firmware
) {
794 dev_err(isp
->dev
, "Failed to load ISP firmware.\n");
798 ret
= atomisp_css_load_firmware(isp
);
800 dev_err(isp
->dev
, "Failed to init css.\n");
803 /* No need to keep FW in memory anymore. */
804 release_firmware(isp
->firmware
);
805 isp
->firmware
= NULL
;
806 isp
->css_env
.isp_css_fw
.data
= NULL
;
809 if (acc_node
&& acc_pipe
->users
) {
810 dev_dbg(isp
->dev
, "acc node already opened\n");
811 rt_mutex_unlock(&isp
->mutex
);
813 } else if (acc_node
) {
817 if (!isp
->input_cnt
) {
818 dev_err(isp
->dev
, "no camera attached\n");
824 * atomisp does not allow multiple open
827 dev_dbg(isp
->dev
, "video node already opened\n");
828 rt_mutex_unlock(&isp
->mutex
);
832 ret
= atomisp_init_pipe(pipe
);
837 if (atomisp_dev_users(isp
)) {
838 dev_dbg(isp
->dev
, "skip init isp in open\n");
842 /* runtime power management, turn on ISP */
843 ret
= pm_runtime_get_sync(vdev
->v4l2_dev
->dev
);
845 dev_err(isp
->dev
, "Failed to power on device\n");
850 ret
= hmm_pool_register(dypool_pgnr
, HMM_POOL_TYPE_DYNAMIC
);
852 dev_err(isp
->dev
, "Failed to register dynamic memory pool.\n");
856 if (atomisp_css_init(isp
)) {
858 /* Need to clean up CSS init if it fails. */
862 atomisp_dev_init_struct(isp
);
864 ret
= v4l2_subdev_call(isp
->flash
, core
, s_power
, 1);
865 if (ret
< 0 && ret
!= -ENODEV
&& ret
!= -ENOIOCTLCMD
) {
866 dev_err(isp
->dev
, "Failed to power-on flash\n");
871 if (atomisp_subdev_users(asd
))
874 atomisp_subdev_init_struct(asd
);
882 rt_mutex_unlock(&isp
->mutex
);
886 atomisp_css_uninit(isp
);
888 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC
);
889 pm_runtime_put(vdev
->v4l2_dev
->dev
);
890 rt_mutex_unlock(&isp
->mutex
);
894 static int atomisp_release(struct file
*file
)
896 struct video_device
*vdev
= video_devdata(file
);
897 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
898 struct atomisp_video_pipe
*pipe
;
899 struct atomisp_acc_pipe
*acc_pipe
;
900 struct atomisp_sub_device
*asd
;
902 struct v4l2_requestbuffers req
;
903 struct v4l2_subdev_fh fh
;
904 struct v4l2_rect clear_compose
= {0};
907 v4l2_fh_init(&fh
.vfh
, vdev
);
913 mutex_lock(&isp
->streamoff_mutex
);
914 rt_mutex_lock(&isp
->mutex
);
916 dev_dbg(isp
->dev
, "release device %s\n", vdev
->name
);
917 acc_node
= !strncmp(vdev
->name
, "ATOMISP ISP ACC",
920 acc_pipe
= atomisp_to_acc_pipe(vdev
);
923 pipe
= atomisp_to_video_pipe(vdev
);
926 asd
->subdev
.devnode
= vdev
;
933 if (pipe
->capq
.streaming
)
935 "%s: ISP still streaming while closing!",
938 if (pipe
->capq
.streaming
&&
939 __atomisp_streamoff(file
, NULL
, V4L2_BUF_TYPE_VIDEO_CAPTURE
)) {
941 "atomisp_streamoff failed on release, driver bug");
948 if (__atomisp_reqbufs(file
, NULL
, &req
)) {
950 "atomisp_reqbufs failed on release, driver bug");
954 if (pipe
->outq
.bufs
[0]) {
955 mutex_lock(&pipe
->outq
.vb_lock
);
956 videobuf_queue_cancel(&pipe
->outq
);
957 mutex_unlock(&pipe
->outq
.vb_lock
);
961 * A little trick here:
962 * file injection input resolution is recorded in the sink pad,
963 * therefore can not be cleared when releaseing one device node.
964 * The sink pad setting can only be cleared when all device nodes
967 if (!isp
->sw_contex
.file_input
&& asd
->fmt_auto
->val
) {
968 struct v4l2_mbus_framefmt isp_sink_fmt
= { 0 };
969 atomisp_subdev_set_ffmt(&asd
->subdev
, fh
.pad
,
970 V4L2_SUBDEV_FORMAT_ACTIVE
,
971 ATOMISP_SUBDEV_PAD_SINK
, &isp_sink_fmt
);
974 if (atomisp_subdev_users(asd
))
977 /* clear the sink pad for file input */
978 if (isp
->sw_contex
.file_input
&& asd
->fmt_auto
->val
) {
979 struct v4l2_mbus_framefmt isp_sink_fmt
= { 0 };
980 atomisp_subdev_set_ffmt(&asd
->subdev
, fh
.pad
,
981 V4L2_SUBDEV_FORMAT_ACTIVE
,
982 ATOMISP_SUBDEV_PAD_SINK
, &isp_sink_fmt
);
985 atomisp_css_free_stat_buffers(asd
);
986 atomisp_free_internal_buffers(asd
);
987 ret
= v4l2_subdev_call(isp
->inputs
[asd
->input_curr
].camera
,
990 dev_warn(isp
->dev
, "Failed to power-off sensor\n");
992 /* clear the asd field to show this camera is not used */
993 isp
->inputs
[asd
->input_curr
].asd
= NULL
;
994 asd
->streaming
= ATOMISP_DEVICE_STREAMING_DISABLED
;
996 if (atomisp_dev_users(isp
))
999 atomisp_acc_release(asd
);
1001 atomisp_destroy_pipes_stream_force(asd
);
1002 atomisp_css_uninit(isp
);
1004 if (defer_fw_load
) {
1005 atomisp_css_unload_firmware(isp
);
1006 isp
->css_env
.isp_css_fw
.data
= NULL
;
1007 isp
->css_env
.isp_css_fw
.bytes
= 0;
1010 hmm_pool_unregister(HMM_POOL_TYPE_DYNAMIC
);
1012 ret
= v4l2_subdev_call(isp
->flash
, core
, s_power
, 0);
1013 if (ret
< 0 && ret
!= -ENODEV
&& ret
!= -ENOIOCTLCMD
)
1014 dev_warn(isp
->dev
, "Failed to power-off flash\n");
1016 if (pm_runtime_put_sync(vdev
->v4l2_dev
->dev
) < 0)
1017 dev_err(isp
->dev
, "Failed to power off device\n");
1021 atomisp_subdev_set_selection(&asd
->subdev
, fh
.pad
,
1022 V4L2_SUBDEV_FORMAT_ACTIVE
,
1023 atomisp_subdev_source_pad(vdev
),
1024 V4L2_SEL_TGT_COMPOSE
, 0,
1027 rt_mutex_unlock(&isp
->mutex
);
1028 mutex_unlock(&isp
->streamoff_mutex
);
1034 * Memory help functions for image frame and private parameters
1036 static int do_isp_mm_remap(struct atomisp_device
*isp
,
1037 struct vm_area_struct
*vma
,
1038 ia_css_ptr isp_virt
, u32 host_virt
, u32 pgnr
)
1043 pfn
= hmm_virt_to_phys(isp_virt
) >> PAGE_SHIFT
;
1044 if (remap_pfn_range(vma
, host_virt
, pfn
,
1045 PAGE_SIZE
, PAGE_SHARED
)) {
1046 dev_err(isp
->dev
, "remap_pfn_range err.\n");
1050 isp_virt
+= PAGE_SIZE
;
1051 host_virt
+= PAGE_SIZE
;
1058 static int frame_mmap(struct atomisp_device
*isp
,
1059 const struct atomisp_css_frame
*frame
, struct vm_area_struct
*vma
)
1061 ia_css_ptr isp_virt
;
1066 dev_err(isp
->dev
, "%s: NULL frame pointer.\n", __func__
);
1070 host_virt
= vma
->vm_start
;
1071 isp_virt
= frame
->data
;
1072 atomisp_get_frame_pgnr(isp
, frame
, &pgnr
);
1074 if (do_isp_mm_remap(isp
, vma
, isp_virt
, host_virt
, pgnr
))
1080 int atomisp_videobuf_mmap_mapper(struct videobuf_queue
*q
,
1081 struct vm_area_struct
*vma
)
1083 u32 offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
1084 int ret
= -EINVAL
, i
;
1085 struct atomisp_device
*isp
=
1086 ((struct atomisp_video_pipe
*)(q
->priv_data
))->isp
;
1087 struct videobuf_vmalloc_memory
*vm_mem
;
1088 struct videobuf_mapping
*map
;
1090 MAGIC_CHECK(q
->int_ops
->magic
, MAGIC_QTYPE_OPS
);
1091 if (!(vma
->vm_flags
& VM_WRITE
) || !(vma
->vm_flags
& VM_SHARED
)) {
1092 dev_err(isp
->dev
, "map appl bug: PROT_WRITE and MAP_SHARED are required\n");
1096 mutex_lock(&q
->vb_lock
);
1097 for (i
= 0; i
< VIDEO_MAX_FRAME
; i
++) {
1098 struct videobuf_buffer
*buf
= q
->bufs
[i
];
1102 map
= kzalloc(sizeof(struct videobuf_mapping
), GFP_KERNEL
);
1104 mutex_unlock(&q
->vb_lock
);
1111 buf
->baddr
= vma
->vm_start
;
1113 if (buf
&& buf
->memory
== V4L2_MEMORY_MMAP
&&
1114 buf
->boff
== offset
) {
1116 ret
= frame_mmap(isp
, vm_mem
->vaddr
, vma
);
1117 vma
->vm_flags
|= VM_IO
|VM_DONTEXPAND
|VM_DONTDUMP
;
1121 mutex_unlock(&q
->vb_lock
);
1126 /* The input frame contains left and right padding that need to be removed.
1127 * There is always ISP_LEFT_PAD padding on the left side.
1128 * There is also padding on the right (padded_width - width).
1130 static int remove_pad_from_frame(struct atomisp_device
*isp
,
1131 struct atomisp_css_frame
*in_frame
, __u32 width
, __u32 height
)
1134 unsigned short *buffer
;
1136 ia_css_ptr load
= in_frame
->data
;
1137 ia_css_ptr store
= load
;
1139 buffer
= kmalloc(width
*sizeof(load
), GFP_KERNEL
);
1143 load
+= ISP_LEFT_PAD
;
1144 for (i
= 0; i
< height
; i
++) {
1145 ret
= hmm_load(load
, buffer
, width
*sizeof(load
));
1147 goto remove_pad_error
;
1149 ret
= hmm_store(store
, buffer
, width
*sizeof(store
));
1151 goto remove_pad_error
;
1153 load
+= in_frame
->info
.padded_width
;
1162 static int atomisp_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1164 struct video_device
*vdev
= video_devdata(file
);
1165 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1166 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
1167 struct atomisp_sub_device
*asd
= pipe
->asd
;
1168 struct atomisp_css_frame
*raw_virt_addr
;
1169 u32 start
= vma
->vm_start
;
1170 u32 end
= vma
->vm_end
;
1171 u32 size
= end
- start
;
1172 u32 origin_size
, new_size
;
1175 if (!(vma
->vm_flags
& (VM_WRITE
| VM_READ
)))
1178 rt_mutex_lock(&isp
->mutex
);
1180 if (!(vma
->vm_flags
& VM_SHARED
)) {
1181 /* Map private buffer.
1182 * Set VM_SHARED to the flags since we need
1183 * to map the buffer page by page.
1184 * Without VM_SHARED, remap_pfn_range() treats
1185 * this kind of mapping as invalid.
1187 vma
->vm_flags
|= VM_SHARED
;
1188 ret
= hmm_mmap(vma
, vma
->vm_pgoff
<< PAGE_SHIFT
);
1189 rt_mutex_unlock(&isp
->mutex
);
1193 /* mmap for ISP offline raw data */
1194 if (atomisp_subdev_source_pad(vdev
)
1195 == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
&&
1196 vma
->vm_pgoff
== (ISP_PARAM_MMAP_OFFSET
>> PAGE_SHIFT
)) {
1197 new_size
= pipe
->pix
.width
* pipe
->pix
.height
* 2;
1198 if (asd
->params
.online_process
!= 0) {
1202 raw_virt_addr
= asd
->raw_output_frame
;
1203 if (raw_virt_addr
== NULL
) {
1204 dev_err(isp
->dev
, "Failed to request RAW frame\n");
1209 ret
= remove_pad_from_frame(isp
, raw_virt_addr
,
1210 pipe
->pix
.width
, pipe
->pix
.height
);
1212 dev_err(isp
->dev
, "remove pad failed.\n");
1215 origin_size
= raw_virt_addr
->data_bytes
;
1216 raw_virt_addr
->data_bytes
= new_size
;
1218 if (size
!= PAGE_ALIGN(new_size
)) {
1219 dev_err(isp
->dev
, "incorrect size for mmap ISP Raw Frame\n");
1224 if (frame_mmap(isp
, raw_virt_addr
, vma
)) {
1225 dev_err(isp
->dev
, "frame_mmap failed.\n");
1226 raw_virt_addr
->data_bytes
= origin_size
;
1230 raw_virt_addr
->data_bytes
= origin_size
;
1231 vma
->vm_flags
|= VM_IO
|VM_DONTEXPAND
|VM_DONTDUMP
;
1232 rt_mutex_unlock(&isp
->mutex
);
1237 * mmap for normal frames
1239 if (size
!= pipe
->pix
.sizeimage
) {
1240 dev_err(isp
->dev
, "incorrect size for mmap ISP frames\n");
1244 rt_mutex_unlock(&isp
->mutex
);
1246 return atomisp_videobuf_mmap_mapper(&pipe
->capq
, vma
);
1249 rt_mutex_unlock(&isp
->mutex
);
1254 static int atomisp_file_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1256 struct video_device
*vdev
= video_devdata(file
);
1257 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
1259 return videobuf_mmap_mapper(&pipe
->outq
, vma
);
1262 static unsigned int atomisp_poll(struct file
*file
,
1263 struct poll_table_struct
*pt
)
1265 struct video_device
*vdev
= video_devdata(file
);
1266 struct atomisp_device
*isp
= video_get_drvdata(vdev
);
1267 struct atomisp_video_pipe
*pipe
= atomisp_to_video_pipe(vdev
);
1269 rt_mutex_lock(&isp
->mutex
);
1270 if (pipe
->capq
.streaming
!= 1) {
1271 rt_mutex_unlock(&isp
->mutex
);
1274 rt_mutex_unlock(&isp
->mutex
);
1276 return videobuf_poll_stream(file
, &pipe
->capq
, pt
);
1279 const struct v4l2_file_operations atomisp_fops
= {
1280 .owner
= THIS_MODULE
,
1281 .open
= atomisp_open
,
1282 .release
= atomisp_release
,
1283 .mmap
= atomisp_mmap
,
1284 .unlocked_ioctl
= video_ioctl2
,
1285 #ifdef CONFIG_COMPAT
1286 .compat_ioctl32
= atomisp_compat_ioctl32
,
1288 .poll
= atomisp_poll
,
1291 const struct v4l2_file_operations atomisp_file_fops
= {
1292 .owner
= THIS_MODULE
,
1293 .open
= atomisp_open
,
1294 .release
= atomisp_release
,
1295 .mmap
= atomisp_file_mmap
,
1296 .unlocked_ioctl
= video_ioctl2
,
1297 #ifdef CONFIG_COMPAT
1298 .compat_ioctl32
= atomisp_compat_ioctl32
,
1300 .poll
= atomisp_poll
,