2 * Support for Clovertrail PNW Camera Imaging ISP subsystem.
4 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #include <media/videobuf-vmalloc.h>
19 #include <media/v4l2-dev.h>
20 #include <media/v4l2-event.h>
22 #include "mmu/isp_mmu.h"
23 #include "mmu/sh_mmu_mrfld.h"
24 #include "hmm/hmm_bo.h"
27 #include "atomisp_compat.h"
28 #include "atomisp_internal.h"
29 #include "atomisp_cmd.h"
30 #include "atomisp-regs.h"
31 #include "atomisp_fops.h"
32 #include "atomisp_ioctl.h"
33 #include "atomisp_acc.h"
35 #include "hrt/hive_isp_css_mm_hrt.h"
37 #include <asm/intel-mid.h>
39 #include "ia_css_debug.h"
40 #include "ia_css_isp_param.h"
41 #include "sh_css_hrt.h"
42 #include "ia_css_isys.h"
44 #include <linux/pm_runtime.h>
46 /* Assume max number of ACC stages */
47 #define MAX_ACC_STAGES 20
49 /* Ideally, this should come from CSS headers */
53 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
54 * #4684168, if concurrency access happened, system may hard hang.
56 static DEFINE_SPINLOCK(mmio_lock
);
58 enum frame_info_type
{
60 ATOMISP_CSS_SECOND_VF_FRAME
,
61 ATOMISP_CSS_OUTPUT_FRAME
,
62 ATOMISP_CSS_SECOND_OUTPUT_FRAME
,
63 ATOMISP_CSS_RAW_FRAME
,
66 struct bayer_ds_factor
{
67 unsigned int numerator
;
68 unsigned int denominator
;
71 void atomisp_css_debug_dump_sp_sw_debug_info(void)
73 ia_css_debug_dump_sp_sw_debug_info();
76 void atomisp_css_debug_dump_debug_info(const char *context
)
78 ia_css_debug_dump_debug_info(context
);
81 void atomisp_css_debug_set_dtrace_level(const unsigned int trace_level
)
83 ia_css_debug_set_dtrace_level(trace_level
);
86 unsigned int atomisp_css_debug_get_dtrace_level(void)
88 return ia_css_debug_trace_level
;
91 void atomisp_css2_hw_store_8(hrt_address addr
, uint8_t data
)
95 spin_lock_irqsave(&mmio_lock
, flags
);
96 _hrt_master_port_store_8(addr
, data
);
97 spin_unlock_irqrestore(&mmio_lock
, flags
);
100 static void atomisp_css2_hw_store_16(hrt_address addr
, uint16_t data
)
104 spin_lock_irqsave(&mmio_lock
, flags
);
105 _hrt_master_port_store_16(addr
, data
);
106 spin_unlock_irqrestore(&mmio_lock
, flags
);
109 static void atomisp_css2_hw_store_32(hrt_address addr
, uint32_t data
)
113 spin_lock_irqsave(&mmio_lock
, flags
);
114 _hrt_master_port_store_32(addr
, data
);
115 spin_unlock_irqrestore(&mmio_lock
, flags
);
118 static uint8_t atomisp_css2_hw_load_8(hrt_address addr
)
123 spin_lock_irqsave(&mmio_lock
, flags
);
124 ret
= _hrt_master_port_load_8(addr
);
125 spin_unlock_irqrestore(&mmio_lock
, flags
);
129 uint16_t atomisp_css2_hw_load_16(hrt_address addr
)
134 spin_lock_irqsave(&mmio_lock
, flags
);
135 ret
= _hrt_master_port_load_16(addr
);
136 spin_unlock_irqrestore(&mmio_lock
, flags
);
139 uint32_t atomisp_css2_hw_load_32(hrt_address addr
)
144 spin_lock_irqsave(&mmio_lock
, flags
);
145 ret
= _hrt_master_port_load_32(addr
);
146 spin_unlock_irqrestore(&mmio_lock
, flags
);
150 static void atomisp_css2_hw_store(hrt_address addr
,
151 const void *from
, uint32_t n
)
155 unsigned int _to
= (unsigned int)addr
;
156 const char *_from
= (const char *)from
;
158 spin_lock_irqsave(&mmio_lock
, flags
);
159 for (i
= 0; i
< n
; i
++, _to
++, _from
++)
160 _hrt_master_port_store_8(_to
, *_from
);
161 spin_unlock_irqrestore(&mmio_lock
, flags
);
164 static void atomisp_css2_hw_load(hrt_address addr
, void *to
, uint32_t n
)
168 char *_to
= (char *)to
;
169 unsigned int _from
= (unsigned int)addr
;
171 spin_lock_irqsave(&mmio_lock
, flags
);
172 for (i
= 0; i
< n
; i
++, _to
++, _from
++)
173 *_to
= _hrt_master_port_load_8(_from
);
174 spin_unlock_irqrestore(&mmio_lock
, flags
);
177 static int atomisp_css2_dbg_print(const char *fmt
, va_list args
)
183 static int atomisp_css2_dbg_ftrace_print(const char *fmt
, va_list args
)
185 ftrace_vprintk(fmt
, args
);
189 static int atomisp_css2_err_print(const char *fmt
, va_list args
)
195 void atomisp_store_uint32(hrt_address addr
, uint32_t data
)
197 atomisp_css2_hw_store_32(addr
, data
);
200 void atomisp_load_uint32(hrt_address addr
, uint32_t *data
)
202 *data
= atomisp_css2_hw_load_32(addr
);
204 static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr
)
206 if (sh_mmu_mrfld
.get_pd_base
== NULL
) {
207 dev_err(atomisp_dev
, "get mmu base address failed.\n");
211 *mmu_base_addr
= sh_mmu_mrfld
.get_pd_base(&bo_device
.mmu
,
212 bo_device
.mmu
.base_address
);
216 static void atomisp_isp_parameters_clean_up(
217 struct atomisp_css_isp_config
*config
)
220 * Set NULL to configs pointer to avoid they are set into isp again when
221 * some configs are changed and need to be updated later.
223 memset(config
, 0, sizeof(*config
));
226 static void __dump_pipe_config(struct atomisp_sub_device
*asd
,
227 struct atomisp_stream_env
*stream_env
,
228 unsigned int pipe_id
)
230 struct atomisp_device
*isp
= asd
->isp
;
232 if (stream_env
->pipes
[pipe_id
]) {
233 struct ia_css_pipe_config
*p_config
;
234 struct ia_css_pipe_extra_config
*pe_config
;
236 p_config
= &stream_env
->pipe_configs
[pipe_id
];
237 pe_config
= &stream_env
->pipe_extra_configs
[pipe_id
];
238 dev_dbg(isp
->dev
, "dumping pipe[%d] config:\n", pipe_id
);
240 "pipe_config.pipe_mode:%d.\n", p_config
->mode
);
242 "pipe_config.output_info[0] w=%d, h=%d.\n",
243 p_config
->output_info
[0].res
.width
,
244 p_config
->output_info
[0].res
.height
);
246 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
247 p_config
->vf_pp_in_res
.width
,
248 p_config
->vf_pp_in_res
.height
);
250 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
251 p_config
->capt_pp_in_res
.width
,
252 p_config
->capt_pp_in_res
.height
);
254 "pipe_config.output.padded w=%d.\n",
255 p_config
->output_info
[0].padded_width
);
257 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
258 p_config
->vf_output_info
[0].res
.width
,
259 p_config
->vf_output_info
[0].res
.height
);
261 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
262 p_config
->bayer_ds_out_res
.width
,
263 p_config
->bayer_ds_out_res
.height
);
265 "pipe_config.envelope w=%d, h=%d.\n",
266 p_config
->dvs_envelope
.width
,
267 p_config
->dvs_envelope
.height
);
269 "pipe_config.dvs_frame_delay=%d.\n",
270 p_config
->dvs_frame_delay
);
272 "pipe_config.isp_pipe_version:%d.\n",
273 p_config
->isp_pipe_version
);
275 "pipe_config.acc_extension=%p.\n",
276 p_config
->acc_extension
);
278 "pipe_config.acc_stages=%p.\n",
279 p_config
->acc_stages
);
281 "pipe_config.num_acc_stages=%d.\n",
282 p_config
->num_acc_stages
);
284 "pipe_config.acc_num_execs=%d.\n",
285 p_config
->acc_num_execs
);
287 "pipe_config.default_capture_config.capture_mode=%d.\n",
288 p_config
->default_capture_config
.mode
);
290 "pipe_config.enable_dz=%d.\n",
291 p_config
->enable_dz
);
293 "pipe_config.default_capture_config.enable_xnr=%d.\n",
294 p_config
->default_capture_config
.enable_xnr
);
296 "dumping pipe[%d] extra config:\n", pipe_id
);
298 "pipe_extra_config.enable_raw_binning:%d.\n",
299 pe_config
->enable_raw_binning
);
301 "pipe_extra_config.enable_yuv_ds:%d.\n",
302 pe_config
->enable_yuv_ds
);
304 "pipe_extra_config.enable_high_speed:%d.\n",
305 pe_config
->enable_high_speed
);
307 "pipe_extra_config.enable_dvs_6axis:%d.\n",
308 pe_config
->enable_dvs_6axis
);
310 "pipe_extra_config.enable_reduced_pipe:%d.\n",
311 pe_config
->enable_reduced_pipe
);
313 "pipe_(extra_)config.enable_dz:%d.\n",
314 p_config
->enable_dz
);
316 "pipe_extra_config.disable_vf_pp:%d.\n",
317 pe_config
->disable_vf_pp
);
321 static void __dump_stream_config(struct atomisp_sub_device
*asd
,
322 struct atomisp_stream_env
*stream_env
)
324 struct atomisp_device
*isp
= asd
->isp
;
325 struct ia_css_stream_config
*s_config
;
327 bool valid_stream
= false;
329 for (j
= 0; j
< IA_CSS_PIPE_ID_NUM
; j
++) {
330 if (stream_env
->pipes
[j
]) {
331 __dump_pipe_config(asd
, stream_env
, j
);
337 s_config
= &stream_env
->stream_config
;
338 dev_dbg(isp
->dev
, "stream_config.mode=%d.\n", s_config
->mode
);
340 if (s_config
->mode
== IA_CSS_INPUT_MODE_SENSOR
||
341 s_config
->mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
) {
342 dev_dbg(isp
->dev
, "stream_config.source.port.port=%d.\n",
343 s_config
->source
.port
.port
);
344 dev_dbg(isp
->dev
, "stream_config.source.port.num_lanes=%d.\n",
345 s_config
->source
.port
.num_lanes
);
346 dev_dbg(isp
->dev
, "stream_config.source.port.timeout=%d.\n",
347 s_config
->source
.port
.timeout
);
348 dev_dbg(isp
->dev
, "stream_config.source.port.rxcount=0x%x.\n",
349 s_config
->source
.port
.rxcount
);
350 dev_dbg(isp
->dev
, "stream_config.source.port.compression.type=%d.\n",
351 s_config
->source
.port
.compression
.type
);
352 dev_dbg(isp
->dev
, "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
353 s_config
->source
.port
.compression
.
354 compressed_bits_per_pixel
);
355 dev_dbg(isp
->dev
, "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
356 s_config
->source
.port
.compression
.
357 uncompressed_bits_per_pixel
);
358 } else if (s_config
->mode
== IA_CSS_INPUT_MODE_TPG
) {
359 dev_dbg(isp
->dev
, "stream_config.source.tpg.id=%d.\n",
360 s_config
->source
.tpg
.id
);
361 dev_dbg(isp
->dev
, "stream_config.source.tpg.mode=%d.\n",
362 s_config
->source
.tpg
.mode
);
363 dev_dbg(isp
->dev
, "stream_config.source.tpg.x_mask=%d.\n",
364 s_config
->source
.tpg
.x_mask
);
365 dev_dbg(isp
->dev
, "stream_config.source.tpg.x_delta=%d.\n",
366 s_config
->source
.tpg
.x_delta
);
367 dev_dbg(isp
->dev
, "stream_config.source.tpg.y_mask=%d.\n",
368 s_config
->source
.tpg
.y_mask
);
369 dev_dbg(isp
->dev
, "stream_config.source.tpg.y_delta=%d.\n",
370 s_config
->source
.tpg
.y_delta
);
371 dev_dbg(isp
->dev
, "stream_config.source.tpg.xy_mask=%d.\n",
372 s_config
->source
.tpg
.xy_mask
);
373 } else if (s_config
->mode
== IA_CSS_INPUT_MODE_PRBS
) {
374 dev_dbg(isp
->dev
, "stream_config.source.prbs.id=%d.\n",
375 s_config
->source
.prbs
.id
);
376 dev_dbg(isp
->dev
, "stream_config.source.prbs.h_blank=%d.\n",
377 s_config
->source
.prbs
.h_blank
);
378 dev_dbg(isp
->dev
, "stream_config.source.prbs.v_blank=%d.\n",
379 s_config
->source
.prbs
.v_blank
);
380 dev_dbg(isp
->dev
, "stream_config.source.prbs.seed=%d.\n",
381 s_config
->source
.prbs
.seed
);
382 dev_dbg(isp
->dev
, "stream_config.source.prbs.seed1=%d.\n",
383 s_config
->source
.prbs
.seed1
);
386 for (j
= 0; j
< IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
; j
++) {
387 dev_dbg(isp
->dev
, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
389 s_config
->isys_config
[j
].input_res
.width
,
390 s_config
->isys_config
[j
].input_res
.height
);
392 dev_dbg(isp
->dev
, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
394 s_config
->isys_config
[j
].linked_isys_stream_id
);
396 dev_dbg(isp
->dev
, "stream_configisys_config[%d].format=%d\n",
398 s_config
->isys_config
[j
].format
);
400 dev_dbg(isp
->dev
, "stream_configisys_config[%d].valid=%d.\n",
402 s_config
->isys_config
[j
].valid
);
405 dev_dbg(isp
->dev
, "stream_config.input_config.input_res w=%d, h=%d.\n",
406 s_config
->input_config
.input_res
.width
,
407 s_config
->input_config
.input_res
.height
);
409 dev_dbg(isp
->dev
, "stream_config.input_config.effective_res w=%d, h=%d.\n",
410 s_config
->input_config
.effective_res
.width
,
411 s_config
->input_config
.effective_res
.height
);
413 dev_dbg(isp
->dev
, "stream_config.input_config.format=%d\n",
414 s_config
->input_config
.format
);
416 dev_dbg(isp
->dev
, "stream_config.input_config.bayer_order=%d.\n",
417 s_config
->input_config
.bayer_order
);
419 dev_dbg(isp
->dev
, "stream_config.pixels_per_clock=%d.\n",
420 s_config
->pixels_per_clock
);
421 dev_dbg(isp
->dev
, "stream_config.online=%d.\n", s_config
->online
);
422 dev_dbg(isp
->dev
, "stream_config.continuous=%d.\n",
423 s_config
->continuous
);
424 dev_dbg(isp
->dev
, "stream_config.disable_cont_viewfinder=%d.\n",
425 s_config
->disable_cont_viewfinder
);
426 dev_dbg(isp
->dev
, "stream_config.channel_id=%d.\n",
427 s_config
->channel_id
);
428 dev_dbg(isp
->dev
, "stream_config.init_num_cont_raw_buf=%d.\n",
429 s_config
->init_num_cont_raw_buf
);
430 dev_dbg(isp
->dev
, "stream_config.target_num_cont_raw_buf=%d.\n",
431 s_config
->target_num_cont_raw_buf
);
432 dev_dbg(isp
->dev
, "stream_config.left_padding=%d.\n",
433 s_config
->left_padding
);
434 dev_dbg(isp
->dev
, "stream_config.sensor_binning_factor=%d.\n",
435 s_config
->sensor_binning_factor
);
436 dev_dbg(isp
->dev
, "stream_config.pixels_per_clock=%d.\n",
437 s_config
->pixels_per_clock
);
438 dev_dbg(isp
->dev
, "stream_config.pack_raw_pixels=%d.\n",
439 s_config
->pack_raw_pixels
);
440 dev_dbg(isp
->dev
, "stream_config.flash_gpio_pin=%d.\n",
441 s_config
->flash_gpio_pin
);
442 dev_dbg(isp
->dev
, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
443 s_config
->mipi_buffer_config
.size_mem_words
);
444 dev_dbg(isp
->dev
, "stream_config.mipi_buffer_config.contiguous=%d.\n",
445 s_config
->mipi_buffer_config
.contiguous
);
446 dev_dbg(isp
->dev
, "stream_config.metadata_config.data_type=%d.\n",
447 s_config
->metadata_config
.data_type
);
448 dev_dbg(isp
->dev
, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
449 s_config
->metadata_config
.resolution
.width
,
450 s_config
->metadata_config
.resolution
.height
);
453 static int __destroy_stream(struct atomisp_sub_device
*asd
,
454 struct atomisp_stream_env
*stream_env
, bool force
)
456 struct atomisp_device
*isp
= asd
->isp
;
458 unsigned long timeout
;
460 if (!stream_env
->stream
)
464 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
465 if (stream_env
->update_pipe
[i
])
468 if (i
== IA_CSS_PIPE_ID_NUM
)
472 if (stream_env
->stream_state
== CSS_STREAM_STARTED
473 && ia_css_stream_stop(stream_env
->stream
) != IA_CSS_SUCCESS
) {
474 dev_err(isp
->dev
, "stop stream failed.\n");
478 if (stream_env
->stream_state
== CSS_STREAM_STARTED
) {
479 timeout
= jiffies
+ msecs_to_jiffies(40);
481 if (ia_css_stream_has_stopped(stream_env
->stream
))
484 if (time_after(jiffies
, timeout
)) {
485 dev_warn(isp
->dev
, "stop stream timeout.\n");
489 usleep_range(100, 200);
493 stream_env
->stream_state
= CSS_STREAM_STOPPED
;
495 if (ia_css_stream_destroy(stream_env
->stream
) != IA_CSS_SUCCESS
) {
496 dev_err(isp
->dev
, "destroy stream failed.\n");
499 stream_env
->stream_state
= CSS_STREAM_UNINIT
;
500 stream_env
->stream
= NULL
;
505 static int __destroy_streams(struct atomisp_sub_device
*asd
, bool force
)
509 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
510 ret
= __destroy_stream(asd
, &asd
->stream_env
[i
], force
);
514 asd
->stream_prepared
= false;
517 static int __create_stream(struct atomisp_sub_device
*asd
,
518 struct atomisp_stream_env
*stream_env
)
520 int pipe_index
= 0, i
;
521 struct ia_css_pipe
*multi_pipes
[IA_CSS_PIPE_ID_NUM
];
523 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++) {
524 if (stream_env
->pipes
[i
])
525 multi_pipes
[pipe_index
++] = stream_env
->pipes
[i
];
530 stream_env
->stream_config
.target_num_cont_raw_buf
=
531 asd
->continuous_raw_buffer_size
->val
;
532 stream_env
->stream_config
.channel_id
= stream_env
->ch_id
;
533 stream_env
->stream_config
.ia_css_enable_raw_buffer_locking
=
534 asd
->enable_raw_buffer_lock
->val
;
536 __dump_stream_config(asd
, stream_env
);
537 if (ia_css_stream_create(&stream_env
->stream_config
,
538 pipe_index
, multi_pipes
, &stream_env
->stream
) != IA_CSS_SUCCESS
)
540 if (ia_css_stream_get_info(stream_env
->stream
,
541 &stream_env
->stream_info
) != IA_CSS_SUCCESS
) {
542 ia_css_stream_destroy(stream_env
->stream
);
543 stream_env
->stream
= NULL
;
547 stream_env
->stream_state
= CSS_STREAM_CREATED
;
551 static int __create_streams(struct atomisp_sub_device
*asd
)
555 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
556 ret
= __create_stream(asd
, &asd
->stream_env
[i
]);
560 asd
->stream_prepared
= true;
563 for (i
--; i
>= 0; i
--)
564 __destroy_stream(asd
, &asd
->stream_env
[i
], true);
568 static int __destroy_stream_pipes(struct atomisp_sub_device
*asd
,
569 struct atomisp_stream_env
*stream_env
,
572 struct atomisp_device
*isp
= asd
->isp
;
576 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++) {
577 if (!stream_env
->pipes
[i
] ||
578 !(force
|| stream_env
->update_pipe
[i
]))
580 if (ia_css_pipe_destroy(stream_env
->pipes
[i
])
583 "destroy pipe[%d]failed.cannot recover.\n", i
);
586 stream_env
->pipes
[i
] = NULL
;
587 stream_env
->update_pipe
[i
] = false;
592 static int __destroy_pipes(struct atomisp_sub_device
*asd
, bool force
)
594 struct atomisp_device
*isp
= asd
->isp
;
598 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
599 if (asd
->stream_env
[i
].stream
) {
602 "cannot destroy css pipes for stream[%d].\n",
607 ret
= __destroy_stream_pipes(asd
, &asd
->stream_env
[i
], force
);
615 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device
*asd
)
617 __destroy_streams(asd
, true);
618 __destroy_pipes(asd
, true);
621 static void __apply_additional_pipe_config(
622 struct atomisp_sub_device
*asd
,
623 struct atomisp_stream_env
*stream_env
,
624 enum ia_css_pipe_id pipe_id
)
626 struct atomisp_device
*isp
= asd
->isp
;
628 if (pipe_id
< 0 || pipe_id
>= IA_CSS_PIPE_ID_NUM
) {
630 "wrong pipe_id for additional pipe config.\n");
634 /* apply default pipe config */
635 stream_env
->pipe_configs
[pipe_id
].isp_pipe_version
= 2;
636 stream_env
->pipe_configs
[pipe_id
].enable_dz
=
637 asd
->disable_dz
->val
? false : true;
638 /* apply isp 2.2 specific config for baytrail*/
640 case IA_CSS_PIPE_ID_CAPTURE
:
641 /* enable capture pp/dz manually or digital zoom would
643 if (stream_env
->pipe_configs
[pipe_id
].
644 default_capture_config
.mode
== CSS_CAPTURE_MODE_RAW
)
645 stream_env
->pipe_configs
[pipe_id
].enable_dz
= false;
648 /* the isp default to use ISP2.2 and the camera hal will
649 * control whether use isp2.7 */
650 if (asd
->select_isp_version
->val
==
651 ATOMISP_CSS_ISP_PIPE_VERSION_2_7
)
652 stream_env
->pipe_configs
[pipe_id
].isp_pipe_version
=
653 SH_CSS_ISP_PIPE_VERSION_2_7
;
655 stream_env
->pipe_configs
[pipe_id
].isp_pipe_version
=
656 SH_CSS_ISP_PIPE_VERSION_2_2
;
659 case IA_CSS_PIPE_ID_VIDEO
:
660 /* enable reduced pipe to have binary
661 * video_dz_2_min selected*/
662 stream_env
->pipe_extra_configs
[pipe_id
]
663 .enable_reduced_pipe
= true;
664 stream_env
->pipe_configs
[pipe_id
]
666 if (ATOMISP_SOC_CAMERA(asd
))
667 stream_env
->pipe_configs
[pipe_id
].enable_dz
= true;
669 if (asd
->params
.video_dis_en
) {
670 stream_env
->pipe_extra_configs
[pipe_id
]
671 .enable_dvs_6axis
= true;
672 stream_env
->pipe_configs
[pipe_id
]
674 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY
;
677 case IA_CSS_PIPE_ID_PREVIEW
:
679 case IA_CSS_PIPE_ID_YUVPP
:
680 case IA_CSS_PIPE_ID_COPY
:
681 if (ATOMISP_SOC_CAMERA(asd
))
682 stream_env
->pipe_configs
[pipe_id
].enable_dz
= true;
684 stream_env
->pipe_configs
[pipe_id
].enable_dz
= false;
686 case IA_CSS_PIPE_ID_ACC
:
687 stream_env
->pipe_configs
[pipe_id
].mode
= IA_CSS_PIPE_MODE_ACC
;
688 stream_env
->pipe_configs
[pipe_id
].enable_dz
= false;
695 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device
*asd
,
696 enum ia_css_pipe_id pipe_id
)
701 if (pipe_id
== CSS_PIPE_ID_ACC
|| pipe_id
== CSS_PIPE_ID_YUVPP
)
705 if (asd
->vfpp
->val
== ATOMISP_VFPP_DISABLE_SCALER
) {
706 if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
710 } else if (asd
->vfpp
->val
== ATOMISP_VFPP_DISABLE_LOWLAT
) {
711 if (pipe_id
== IA_CSS_PIPE_ID_CAPTURE
)
721 if (asd
->copy_mode
&& pipe_id
== IA_CSS_PIPE_ID_COPY
)
724 switch (asd
->run_mode
->val
) {
725 case ATOMISP_RUN_MODE_STILL_CAPTURE
:
726 if (pipe_id
== IA_CSS_PIPE_ID_CAPTURE
)
730 case ATOMISP_RUN_MODE_PREVIEW
:
731 if (!asd
->continuous_mode
->val
) {
732 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
737 /* fall through to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE */
738 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE
:
739 if (pipe_id
== IA_CSS_PIPE_ID_CAPTURE
||
740 pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
744 case ATOMISP_RUN_MODE_VIDEO
:
745 if (!asd
->continuous_mode
->val
) {
746 if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
||
747 pipe_id
== IA_CSS_PIPE_ID_YUVPP
)
752 /* fall through to ATOMISP_RUN_MODE_SDV */
753 case ATOMISP_RUN_MODE_SDV
:
754 if (pipe_id
== IA_CSS_PIPE_ID_CAPTURE
||
755 pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
764 static int __create_pipe(struct atomisp_sub_device
*asd
,
765 struct atomisp_stream_env
*stream_env
,
766 enum ia_css_pipe_id pipe_id
)
768 struct atomisp_device
*isp
= asd
->isp
;
769 struct ia_css_pipe_extra_config extra_config
;
772 if (pipe_id
>= IA_CSS_PIPE_ID_NUM
)
775 if (pipe_id
!= CSS_PIPE_ID_ACC
&&
776 !stream_env
->pipe_configs
[pipe_id
].output_info
[0].res
.width
)
779 if (pipe_id
== CSS_PIPE_ID_ACC
&&
780 !stream_env
->pipe_configs
[pipe_id
].acc_extension
)
783 if (!is_pipe_valid_to_current_run_mode(asd
, pipe_id
))
786 ia_css_pipe_extra_config_defaults(&extra_config
);
788 __apply_additional_pipe_config(asd
, stream_env
, pipe_id
);
789 if (!memcmp(&extra_config
,
790 &stream_env
->pipe_extra_configs
[pipe_id
],
791 sizeof(extra_config
)))
792 ret
= ia_css_pipe_create(
793 &stream_env
->pipe_configs
[pipe_id
],
794 &stream_env
->pipes
[pipe_id
]);
796 ret
= ia_css_pipe_create_extra(
797 &stream_env
->pipe_configs
[pipe_id
],
798 &stream_env
->pipe_extra_configs
[pipe_id
],
799 &stream_env
->pipes
[pipe_id
]);
800 if (ret
!= IA_CSS_SUCCESS
)
801 dev_err(isp
->dev
, "create pipe[%d] error.\n", pipe_id
);
805 static int __create_pipes(struct atomisp_sub_device
*asd
)
810 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
811 for (j
= 0; j
< IA_CSS_PIPE_ID_NUM
; j
++) {
812 ret
= __create_pipe(asd
, &asd
->stream_env
[i
], j
);
813 if (ret
!= IA_CSS_SUCCESS
)
816 if (j
< IA_CSS_PIPE_ID_NUM
)
821 for (; i
>= 0; i
--) {
822 for (j
--; j
>= 0; j
--) {
823 if (asd
->stream_env
[i
].pipes
[j
]) {
824 ia_css_pipe_destroy(asd
->stream_env
[i
].pipes
[j
]);
825 asd
->stream_env
[i
].pipes
[j
] = NULL
;
828 j
= IA_CSS_PIPE_ID_NUM
;
833 void atomisp_create_pipes_stream(struct atomisp_sub_device
*asd
)
836 __create_streams(asd
);
839 int atomisp_css_update_stream(struct atomisp_sub_device
*asd
)
842 struct atomisp_device
*isp
= asd
->isp
;
844 if (__destroy_streams(asd
, true) != IA_CSS_SUCCESS
)
845 dev_warn(isp
->dev
, "destroy stream failed.\n");
847 if (__destroy_pipes(asd
, true) != IA_CSS_SUCCESS
)
848 dev_warn(isp
->dev
, "destroy pipe failed.\n");
850 ret
= __create_pipes(asd
);
851 if (ret
!= IA_CSS_SUCCESS
) {
852 dev_err(isp
->dev
, "create pipe failed %d.\n", ret
);
856 ret
= __create_streams(asd
);
857 if (ret
!= IA_CSS_SUCCESS
) {
858 dev_warn(isp
->dev
, "create stream failed %d.\n", ret
);
859 __destroy_pipes(asd
, true);
866 int atomisp_css_init(struct atomisp_device
*isp
)
868 unsigned int mmu_base_addr
;
872 ret
= hmm_get_mmu_base_addr(&mmu_base_addr
);
877 err
= ia_css_init(&isp
->css_env
.isp_css_env
, NULL
,
878 (uint32_t)mmu_base_addr
, IA_CSS_IRQ_TYPE_PULSE
);
879 if (err
!= IA_CSS_SUCCESS
) {
880 dev_err(isp
->dev
, "css init failed --- bad firmware?\n");
883 ia_css_enable_isys_event_queue(true);
885 isp
->css_initialized
= true;
886 dev_dbg(isp
->dev
, "sh_css_init success\n");
891 static inline int __set_css_print_env(struct atomisp_device
*isp
, int opt
)
896 isp
->css_env
.isp_css_env
.print_env
.debug_print
= NULL
;
898 isp
->css_env
.isp_css_env
.print_env
.debug_print
=
899 atomisp_css2_dbg_ftrace_print
;
901 isp
->css_env
.isp_css_env
.print_env
.debug_print
=
902 atomisp_css2_dbg_print
;
909 int atomisp_css_check_firmware_version(struct atomisp_device
*isp
)
911 if (!sh_css_check_firmware_version((void *)isp
->firmware
->data
)) {
912 dev_err(isp
->dev
, "Fw version check failed.\n");
918 int atomisp_css_load_firmware(struct atomisp_device
*isp
)
923 isp
->css_env
.isp_css_fw
.data
= (void *)isp
->firmware
->data
;
924 isp
->css_env
.isp_css_fw
.bytes
= isp
->firmware
->size
;
926 isp
->css_env
.isp_css_env
.hw_access_env
.store_8
=
927 atomisp_css2_hw_store_8
;
928 isp
->css_env
.isp_css_env
.hw_access_env
.store_16
=
929 atomisp_css2_hw_store_16
;
930 isp
->css_env
.isp_css_env
.hw_access_env
.store_32
=
931 atomisp_css2_hw_store_32
;
933 isp
->css_env
.isp_css_env
.hw_access_env
.load_8
= atomisp_css2_hw_load_8
;
934 isp
->css_env
.isp_css_env
.hw_access_env
.load_16
=
935 atomisp_css2_hw_load_16
;
936 isp
->css_env
.isp_css_env
.hw_access_env
.load_32
=
937 atomisp_css2_hw_load_32
;
939 isp
->css_env
.isp_css_env
.hw_access_env
.load
= atomisp_css2_hw_load
;
940 isp
->css_env
.isp_css_env
.hw_access_env
.store
= atomisp_css2_hw_store
;
942 __set_css_print_env(isp
, dbg_func
);
944 isp
->css_env
.isp_css_env
.print_env
.error_print
= atomisp_css2_err_print
;
946 /* load isp fw into ISP memory */
947 err
= ia_css_load_firmware(&isp
->css_env
.isp_css_env
,
948 &isp
->css_env
.isp_css_fw
);
949 if (err
!= IA_CSS_SUCCESS
) {
950 dev_err(isp
->dev
, "css load fw failed.\n");
957 void atomisp_css_unload_firmware(struct atomisp_device
*isp
)
959 ia_css_unload_firmware();
962 void atomisp_css_uninit(struct atomisp_device
*isp
)
964 struct atomisp_sub_device
*asd
;
967 for (i
= 0; i
< isp
->num_of_streams
; i
++) {
969 atomisp_isp_parameters_clean_up(&asd
->params
.config
);
970 asd
->params
.css_update_params_needed
= false;
973 isp
->css_initialized
= false;
977 void atomisp_css_suspend(struct atomisp_device
*isp
)
979 isp
->css_initialized
= false;
983 int atomisp_css_resume(struct atomisp_device
*isp
)
985 unsigned int mmu_base_addr
;
988 ret
= hmm_get_mmu_base_addr(&mmu_base_addr
);
990 dev_err(isp
->dev
, "get base address error.\n");
994 ret
= ia_css_init(&isp
->css_env
.isp_css_env
, NULL
,
995 mmu_base_addr
, IA_CSS_IRQ_TYPE_PULSE
);
997 dev_err(isp
->dev
, "re-init css failed.\n");
1000 ia_css_enable_isys_event_queue(true);
1002 isp
->css_initialized
= true;
1006 int atomisp_css_irq_translate(struct atomisp_device
*isp
,
1007 unsigned int *infos
)
1011 err
= ia_css_irq_translate(infos
);
1012 if (err
!= IA_CSS_SUCCESS
) {
1014 "%s:failed to translate irq (err = %d,infos = %d)\n",
1015 __func__
, err
, *infos
);
1022 void atomisp_css_rx_get_irq_info(enum ia_css_csi2_port port
,
1023 unsigned int *infos
)
1025 #ifndef ISP2401_NEW_INPUT_SYSTEM
1026 ia_css_isys_rx_get_irq_info(port
, infos
);
1032 void atomisp_css_rx_clear_irq_info(enum ia_css_csi2_port port
,
1035 #ifndef ISP2401_NEW_INPUT_SYSTEM
1036 ia_css_isys_rx_clear_irq_info(port
, infos
);
1040 int atomisp_css_irq_enable(struct atomisp_device
*isp
,
1041 enum atomisp_css_irq_info info
, bool enable
)
1043 if (ia_css_irq_enable(info
, enable
) != IA_CSS_SUCCESS
) {
1044 dev_warn(isp
->dev
, "%s:Invalid irq info.\n", __func__
);
1051 void atomisp_css_init_struct(struct atomisp_sub_device
*asd
)
1055 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
1056 asd
->stream_env
[i
].stream
= NULL
;
1057 for (j
= 0; j
< IA_CSS_PIPE_MODE_NUM
; j
++) {
1058 asd
->stream_env
[i
].pipes
[j
] = NULL
;
1059 asd
->stream_env
[i
].update_pipe
[j
] = false;
1060 ia_css_pipe_config_defaults(
1061 &asd
->stream_env
[i
].pipe_configs
[j
]);
1062 ia_css_pipe_extra_config_defaults(
1063 &asd
->stream_env
[i
].pipe_extra_configs
[j
]);
1065 ia_css_stream_config_defaults(&asd
->stream_env
[i
].stream_config
);
1069 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device
*asd
,
1070 struct videobuf_vmalloc_memory
*vm_mem
,
1071 enum atomisp_input_stream_id stream_id
,
1072 enum atomisp_css_buffer_type css_buf_type
,
1073 enum atomisp_css_pipe_id css_pipe_id
)
1075 struct atomisp_stream_env
*stream_env
= &asd
->stream_env
[stream_id
];
1076 struct ia_css_buffer css_buf
= {0};
1077 enum ia_css_err err
;
1079 css_buf
.type
= css_buf_type
;
1080 css_buf
.data
.frame
= vm_mem
->vaddr
;
1082 err
= ia_css_pipe_enqueue_buffer(
1083 stream_env
->pipes
[css_pipe_id
], &css_buf
);
1084 if (err
!= IA_CSS_SUCCESS
)
1090 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device
*asd
,
1091 struct atomisp_metadata_buf
*metadata_buf
,
1092 enum atomisp_input_stream_id stream_id
,
1093 enum atomisp_css_pipe_id css_pipe_id
)
1095 struct atomisp_stream_env
*stream_env
= &asd
->stream_env
[stream_id
];
1096 struct ia_css_buffer buffer
= {0};
1097 struct atomisp_device
*isp
= asd
->isp
;
1099 buffer
.type
= IA_CSS_BUFFER_TYPE_METADATA
;
1100 buffer
.data
.metadata
= metadata_buf
->metadata
;
1101 if (ia_css_pipe_enqueue_buffer(stream_env
->pipes
[css_pipe_id
],
1103 dev_err(isp
->dev
, "failed to q meta data buffer\n");
1110 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device
*asd
,
1111 struct atomisp_s3a_buf
*s3a_buf
,
1112 enum atomisp_input_stream_id stream_id
,
1113 enum atomisp_css_pipe_id css_pipe_id
)
1115 struct atomisp_stream_env
*stream_env
= &asd
->stream_env
[stream_id
];
1116 struct ia_css_buffer buffer
= {0};
1117 struct atomisp_device
*isp
= asd
->isp
;
1119 buffer
.type
= IA_CSS_BUFFER_TYPE_3A_STATISTICS
;
1120 buffer
.data
.stats_3a
= s3a_buf
->s3a_data
;
1121 if (ia_css_pipe_enqueue_buffer(
1122 stream_env
->pipes
[css_pipe_id
],
1124 dev_dbg(isp
->dev
, "failed to q s3a stat buffer\n");
1131 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device
*asd
,
1132 struct atomisp_dis_buf
*dis_buf
,
1133 enum atomisp_input_stream_id stream_id
,
1134 enum atomisp_css_pipe_id css_pipe_id
)
1136 struct atomisp_stream_env
*stream_env
= &asd
->stream_env
[stream_id
];
1137 struct ia_css_buffer buffer
= {0};
1138 struct atomisp_device
*isp
= asd
->isp
;
1140 buffer
.type
= IA_CSS_BUFFER_TYPE_DIS_STATISTICS
;
1141 buffer
.data
.stats_dvs
= dis_buf
->dis_data
;
1142 if (ia_css_pipe_enqueue_buffer(
1143 stream_env
->pipes
[css_pipe_id
],
1145 dev_dbg(isp
->dev
, "failed to q dvs stat buffer\n");
1152 void atomisp_css_mmu_invalidate_cache(void)
1154 ia_css_mmu_invalidate_cache();
1157 void atomisp_css_mmu_invalidate_tlb(void)
1159 ia_css_mmu_invalidate_cache();
1162 void atomisp_css_mmu_set_page_table_base_index(unsigned long base_index
)
1167 * Check whether currently running MIPI buffer size fulfill
1168 * the requirement of the stream to be run
1170 bool __need_realloc_mipi_buffer(struct atomisp_device
*isp
)
1174 for (i
= 0; i
< isp
->num_of_streams
; i
++) {
1175 struct atomisp_sub_device
*asd
= &isp
->asd
[i
];
1177 if (asd
->streaming
!=
1178 ATOMISP_DEVICE_STREAMING_ENABLED
)
1180 if (asd
->mipi_frame_size
< isp
->mipi_frame_size
)
1187 int atomisp_css_start(struct atomisp_sub_device
*asd
,
1188 enum atomisp_css_pipe_id pipe_id
, bool in_reset
)
1190 struct atomisp_device
*isp
= asd
->isp
;
1191 bool sp_is_started
= false;
1195 if (__destroy_streams(asd
, true))
1196 dev_warn(isp
->dev
, "destroy stream failed.\n");
1198 if (__destroy_pipes(asd
, true))
1199 dev_warn(isp
->dev
, "destroy pipe failed.\n");
1201 if (__create_pipes(asd
)) {
1202 dev_err(isp
->dev
, "create pipe error.\n");
1205 if (__create_streams(asd
)) {
1206 dev_err(isp
->dev
, "create stream error.\n");
1210 /* in_reset == true, extension firmwares are reloaded after the recovery */
1211 atomisp_acc_load_extensions(asd
);
1215 * For dual steam case, it is possible that:
1216 * 1: for this stream, it is at the stage that:
1217 * - after set_fmt is called
1218 * - before stream on is called
1219 * 2: for the other stream, the stream off is called which css reset
1222 * Thus the stream created in set_fmt get destroyed and need to be
1223 * recreated in the next stream on.
1225 if (asd
->stream_prepared
== false) {
1226 if (__create_pipes(asd
)) {
1227 dev_err(isp
->dev
, "create pipe error.\n");
1230 if (__create_streams(asd
)) {
1231 dev_err(isp
->dev
, "create stream error.\n");
1237 * SP can only be started one time
1238 * if atomisp_subdev_streaming_count() tell there already has some
1239 * subdev at streamming, then SP should already be started previously,
1240 * so need to skip start sp procedure
1242 if (atomisp_streaming_count(isp
)) {
1243 dev_dbg(isp
->dev
, "skip start sp\n");
1245 if (!sh_css_hrt_system_is_idle())
1246 dev_err(isp
->dev
, "CSS HW not idle before starting SP\n");
1247 if (ia_css_start_sp() != IA_CSS_SUCCESS
) {
1248 dev_err(isp
->dev
, "start sp error.\n");
1252 sp_is_started
= true;
1256 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
1257 if (asd
->stream_env
[i
].stream
) {
1258 if (ia_css_stream_start(asd
->stream_env
[i
]
1259 .stream
) != IA_CSS_SUCCESS
) {
1260 dev_err(isp
->dev
, "stream[%d] start error.\n", i
);
1264 asd
->stream_env
[i
].stream_state
= CSS_STREAM_STARTED
;
1265 dev_dbg(isp
->dev
, "stream[%d] started.\n", i
);
1273 __destroy_streams(asd
, true);
1275 __destroy_pipes(asd
, true);
1277 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1281 * SP can not be stop if other streams are in use
1283 if ((atomisp_streaming_count(isp
) == 0) && sp_is_started
)
1289 void atomisp_css_update_isp_params(struct atomisp_sub_device
*asd
)
1293 * for ISP2401 new input system, this api is under development.
1294 * Calling it would cause kernel panic.
1298 * Check if it is Cherry Trail and also new input system
1300 if (asd
->copy_mode
) {
1301 dev_warn(asd
->isp
->dev
,
1302 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1307 ia_css_stream_set_isp_config(
1308 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
1309 &asd
->params
.config
);
1310 atomisp_isp_parameters_clean_up(&asd
->params
.config
);
1314 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device
*asd
,
1315 struct ia_css_pipe
*pipe
)
1317 enum ia_css_err ret
;
1320 atomisp_css_update_isp_params(asd
);
1324 dev_dbg(asd
->isp
->dev
, "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1325 __func__
, asd
->params
.config
.output_frame
,
1326 asd
->params
.config
.isp_config_id
, pipe
);
1328 ret
= ia_css_stream_set_isp_config_on_pipe(
1329 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
1330 &asd
->params
.config
, pipe
);
1331 if (ret
!= IA_CSS_SUCCESS
)
1332 dev_warn(asd
->isp
->dev
, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1334 atomisp_isp_parameters_clean_up(&asd
->params
.config
);
1337 int atomisp_css_queue_buffer(struct atomisp_sub_device
*asd
,
1338 enum atomisp_input_stream_id stream_id
,
1339 enum atomisp_css_pipe_id pipe_id
,
1340 enum atomisp_css_buffer_type buf_type
,
1341 struct atomisp_css_buffer
*isp_css_buffer
)
1343 if (ia_css_pipe_enqueue_buffer(
1344 asd
->stream_env
[stream_id
].pipes
[pipe_id
],
1345 &isp_css_buffer
->css_buffer
)
1352 int atomisp_css_dequeue_buffer(struct atomisp_sub_device
*asd
,
1353 enum atomisp_input_stream_id stream_id
,
1354 enum atomisp_css_pipe_id pipe_id
,
1355 enum atomisp_css_buffer_type buf_type
,
1356 struct atomisp_css_buffer
*isp_css_buffer
)
1358 struct atomisp_device
*isp
= asd
->isp
;
1359 enum ia_css_err err
;
1361 err
= ia_css_pipe_dequeue_buffer(
1362 asd
->stream_env
[stream_id
].pipes
[pipe_id
],
1363 &isp_css_buffer
->css_buffer
);
1364 if (err
!= IA_CSS_SUCCESS
) {
1366 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err
);
1373 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device
*asd
,
1375 struct atomisp_s3a_buf
*s3a_buf
,
1376 struct atomisp_dis_buf
*dis_buf
,
1377 struct atomisp_metadata_buf
*md_buf
)
1379 struct atomisp_device
*isp
= asd
->isp
;
1380 struct atomisp_css_dvs_grid_info
*dvs_grid_info
=
1381 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
1383 if (s3a_buf
&& asd
->params
.curr_grid_info
.s3a_grid
.enable
) {
1386 s3a_buf
->s3a_data
= ia_css_isp_3a_statistics_allocate(
1387 &asd
->params
.curr_grid_info
.s3a_grid
);
1388 if (!s3a_buf
->s3a_data
) {
1389 dev_err(isp
->dev
, "3a buf allocation failed.\n");
1393 s3a_ptr
= hmm_vmap(s3a_buf
->s3a_data
->data_ptr
, true);
1394 s3a_buf
->s3a_map
= ia_css_isp_3a_statistics_map_allocate(
1395 s3a_buf
->s3a_data
, s3a_ptr
);
1398 if (dis_buf
&& dvs_grid_info
&& dvs_grid_info
->enable
) {
1401 dis_buf
->dis_data
= ia_css_isp_dvs2_statistics_allocate(
1403 if (!dis_buf
->dis_data
) {
1404 dev_err(isp
->dev
, "dvs buf allocation failed.\n");
1406 ia_css_isp_3a_statistics_free(s3a_buf
->s3a_data
);
1410 dvs_ptr
= hmm_vmap(dis_buf
->dis_data
->data_ptr
, true);
1411 dis_buf
->dvs_map
= ia_css_isp_dvs_statistics_map_allocate(
1412 dis_buf
->dis_data
, dvs_ptr
);
1415 if (asd
->stream_env
[stream_id
].stream_info
.
1416 metadata_info
.size
&& md_buf
) {
1417 md_buf
->metadata
= ia_css_metadata_allocate(
1418 &asd
->stream_env
[stream_id
].stream_info
.metadata_info
);
1419 if (!md_buf
->metadata
) {
1421 ia_css_isp_3a_statistics_free(s3a_buf
->s3a_data
);
1423 ia_css_isp_dvs2_statistics_free(dis_buf
->dis_data
);
1424 dev_err(isp
->dev
, "metadata buf allocation failed.\n");
1427 md_buf
->md_vptr
= hmm_vmap(md_buf
->metadata
->address
, false);
1433 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf
*s3a_buf
)
1435 if (s3a_buf
->s3a_data
)
1436 hmm_vunmap(s3a_buf
->s3a_data
->data_ptr
);
1438 ia_css_isp_3a_statistics_map_free(s3a_buf
->s3a_map
);
1439 s3a_buf
->s3a_map
= NULL
;
1440 ia_css_isp_3a_statistics_free(s3a_buf
->s3a_data
);
1443 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf
*dis_buf
)
1445 if (dis_buf
->dis_data
)
1446 hmm_vunmap(dis_buf
->dis_data
->data_ptr
);
1448 ia_css_isp_dvs_statistics_map_free(dis_buf
->dvs_map
);
1449 dis_buf
->dvs_map
= NULL
;
1450 ia_css_isp_dvs2_statistics_free(dis_buf
->dis_data
);
1453 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf
*metadata_buf
)
1455 if (metadata_buf
->md_vptr
) {
1456 hmm_vunmap(metadata_buf
->metadata
->address
);
1457 metadata_buf
->md_vptr
= NULL
;
1459 ia_css_metadata_free(metadata_buf
->metadata
);
1462 void atomisp_css_free_stat_buffers(struct atomisp_sub_device
*asd
)
1464 struct atomisp_s3a_buf
*s3a_buf
, *_s3a_buf
;
1465 struct atomisp_dis_buf
*dis_buf
, *_dis_buf
;
1466 struct atomisp_metadata_buf
*md_buf
, *_md_buf
;
1467 struct atomisp_css_dvs_grid_info
*dvs_grid_info
=
1468 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
1471 /* 3A statistics use vmalloc, DIS use kmalloc */
1472 if (dvs_grid_info
&& dvs_grid_info
->enable
) {
1473 ia_css_dvs2_coefficients_free(asd
->params
.css_param
.dvs2_coeff
);
1474 ia_css_dvs2_statistics_free(asd
->params
.dvs_stat
);
1475 asd
->params
.css_param
.dvs2_coeff
= NULL
;
1476 asd
->params
.dvs_stat
= NULL
;
1477 asd
->params
.dvs_hor_proj_bytes
= 0;
1478 asd
->params
.dvs_ver_proj_bytes
= 0;
1479 asd
->params
.dvs_hor_coef_bytes
= 0;
1480 asd
->params
.dvs_ver_coef_bytes
= 0;
1481 asd
->params
.dis_proj_data_valid
= false;
1482 list_for_each_entry_safe(dis_buf
, _dis_buf
,
1483 &asd
->dis_stats
, list
) {
1484 atomisp_css_free_dis_buffer(dis_buf
);
1485 list_del(&dis_buf
->list
);
1488 list_for_each_entry_safe(dis_buf
, _dis_buf
,
1489 &asd
->dis_stats_in_css
, list
) {
1490 atomisp_css_free_dis_buffer(dis_buf
);
1491 list_del(&dis_buf
->list
);
1495 if (asd
->params
.curr_grid_info
.s3a_grid
.enable
) {
1496 ia_css_3a_statistics_free(asd
->params
.s3a_user_stat
);
1497 asd
->params
.s3a_user_stat
= NULL
;
1498 asd
->params
.s3a_output_bytes
= 0;
1499 list_for_each_entry_safe(s3a_buf
, _s3a_buf
,
1500 &asd
->s3a_stats
, list
) {
1501 atomisp_css_free_3a_buffer(s3a_buf
);
1502 list_del(&s3a_buf
->list
);
1505 list_for_each_entry_safe(s3a_buf
, _s3a_buf
,
1506 &asd
->s3a_stats_in_css
, list
) {
1507 atomisp_css_free_3a_buffer(s3a_buf
);
1508 list_del(&s3a_buf
->list
);
1511 list_for_each_entry_safe(s3a_buf
, _s3a_buf
,
1512 &asd
->s3a_stats_ready
, list
) {
1513 atomisp_css_free_3a_buffer(s3a_buf
);
1514 list_del(&s3a_buf
->list
);
1519 if (asd
->params
.css_param
.dvs_6axis
) {
1520 ia_css_dvs2_6axis_config_free(asd
->params
.css_param
.dvs_6axis
);
1521 asd
->params
.css_param
.dvs_6axis
= NULL
;
1524 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
1525 list_for_each_entry_safe(md_buf
, _md_buf
,
1526 &asd
->metadata
[i
], list
) {
1527 atomisp_css_free_metadata_buffer(md_buf
);
1528 list_del(&md_buf
->list
);
1531 list_for_each_entry_safe(md_buf
, _md_buf
,
1532 &asd
->metadata_in_css
[i
], list
) {
1533 atomisp_css_free_metadata_buffer(md_buf
);
1534 list_del(&md_buf
->list
);
1537 list_for_each_entry_safe(md_buf
, _md_buf
,
1538 &asd
->metadata_ready
[i
], list
) {
1539 atomisp_css_free_metadata_buffer(md_buf
);
1540 list_del(&md_buf
->list
);
1544 asd
->params
.metadata_width_size
= 0;
1545 atomisp_free_metadata_output_buf(asd
);
1548 int atomisp_css_get_grid_info(struct atomisp_sub_device
*asd
,
1549 enum atomisp_css_pipe_id pipe_id
,
1552 struct ia_css_pipe_info p_info
;
1553 struct ia_css_grid_info old_info
;
1554 struct atomisp_device
*isp
= asd
->isp
;
1555 int stream_index
= atomisp_source_pad_to_stream_id(asd
, source_pad
);
1556 int md_width
= asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].
1557 stream_config
.metadata_config
.resolution
.width
;
1559 memset(&p_info
, 0, sizeof(struct ia_css_pipe_info
));
1560 memset(&old_info
, 0, sizeof(struct ia_css_grid_info
));
1562 if (ia_css_pipe_get_info(
1563 asd
->stream_env
[stream_index
].pipes
[pipe_id
],
1564 &p_info
) != IA_CSS_SUCCESS
) {
1565 dev_err(isp
->dev
, "ia_css_pipe_get_info failed\n");
1569 memcpy(&old_info
, &asd
->params
.curr_grid_info
,
1570 sizeof(struct ia_css_grid_info
));
1571 memcpy(&asd
->params
.curr_grid_info
, &p_info
.grid_info
,
1572 sizeof(struct ia_css_grid_info
));
1574 * Record which css pipe enables s3a_grid.
1575 * Currently would have one css pipe that need it
1577 if (asd
->params
.curr_grid_info
.s3a_grid
.enable
) {
1578 if (asd
->params
.s3a_enabled_pipe
!= CSS_PIPE_ID_NUM
)
1579 dev_dbg(isp
->dev
, "css pipe %d enabled s3a grid replaced by: %d.\n",
1580 asd
->params
.s3a_enabled_pipe
, pipe_id
);
1581 asd
->params
.s3a_enabled_pipe
= pipe_id
;
1584 /* If the grid info has not changed and the buffers for 3A and
1585 * DIS statistics buffers are allocated or buffer size would be zero
1586 * then no need to do anything. */
1587 if (((!memcmp(&old_info
, &asd
->params
.curr_grid_info
, sizeof(old_info
))
1588 && asd
->params
.s3a_user_stat
&& asd
->params
.dvs_stat
)
1589 || asd
->params
.curr_grid_info
.s3a_grid
.width
== 0
1590 || asd
->params
.curr_grid_info
.s3a_grid
.height
== 0)
1591 && asd
->params
.metadata_width_size
== md_width
) {
1593 "grid info change escape. memcmp=%d, s3a_user_stat=%d,"
1594 "dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1595 !memcmp(&old_info
, &asd
->params
.curr_grid_info
,
1597 !!asd
->params
.s3a_user_stat
, !!asd
->params
.dvs_stat
,
1598 asd
->params
.curr_grid_info
.s3a_grid
.width
,
1599 asd
->params
.curr_grid_info
.s3a_grid
.height
,
1600 asd
->params
.metadata_width_size
);
1603 asd
->params
.metadata_width_size
= md_width
;
1608 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device
*asd
)
1610 if (!asd
->params
.curr_grid_info
.s3a_grid
.width
||
1611 !asd
->params
.curr_grid_info
.s3a_grid
.height
)
1614 asd
->params
.s3a_user_stat
= ia_css_3a_statistics_allocate(
1615 &asd
->params
.curr_grid_info
.s3a_grid
);
1616 if (!asd
->params
.s3a_user_stat
)
1618 /* 3A statistics. These can be big, so we use vmalloc. */
1619 asd
->params
.s3a_output_bytes
=
1620 asd
->params
.curr_grid_info
.s3a_grid
.width
*
1621 asd
->params
.curr_grid_info
.s3a_grid
.height
*
1622 sizeof(*asd
->params
.s3a_user_stat
->data
);
1627 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device
*asd
)
1629 struct atomisp_css_dvs_grid_info
*dvs_grid
=
1630 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
1635 if (!dvs_grid
->enable
) {
1636 dev_dbg(asd
->isp
->dev
, "%s: dvs_grid not enabled.\n", __func__
);
1640 /* DIS coefficients. */
1641 asd
->params
.css_param
.dvs2_coeff
= ia_css_dvs2_coefficients_allocate(
1643 if (!asd
->params
.css_param
.dvs2_coeff
)
1646 asd
->params
.dvs_hor_coef_bytes
= dvs_grid
->num_hor_coefs
*
1647 sizeof(*asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.odd_real
);
1649 asd
->params
.dvs_ver_coef_bytes
= dvs_grid
->num_ver_coefs
*
1650 sizeof(*asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.odd_real
);
1652 /* DIS projections. */
1653 asd
->params
.dis_proj_data_valid
= false;
1654 asd
->params
.dvs_stat
= ia_css_dvs2_statistics_allocate(dvs_grid
);
1655 if (!asd
->params
.dvs_stat
)
1658 asd
->params
.dvs_hor_proj_bytes
=
1659 dvs_grid
->aligned_height
* dvs_grid
->aligned_width
*
1660 sizeof(*asd
->params
.dvs_stat
->hor_prod
.odd_real
);
1662 asd
->params
.dvs_ver_proj_bytes
=
1663 dvs_grid
->aligned_height
* dvs_grid
->aligned_width
*
1664 sizeof(*asd
->params
.dvs_stat
->ver_prod
.odd_real
);
1669 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device
*asd
)
1673 /* We allocate the cpu-side buffer used for communication with user
1675 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
1676 asd
->params
.metadata_user
[i
] = kvmalloc(
1677 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].
1678 stream_info
.metadata_info
.size
, GFP_KERNEL
);
1679 if (!asd
->params
.metadata_user
[i
]) {
1681 kvfree(asd
->params
.metadata_user
[i
]);
1682 asd
->params
.metadata_user
[i
] = NULL
;
1691 void atomisp_free_metadata_output_buf(struct atomisp_sub_device
*asd
)
1695 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
1696 if (asd
->params
.metadata_user
[i
]) {
1697 kvfree(asd
->params
.metadata_user
[i
]);
1698 asd
->params
.metadata_user
[i
] = NULL
;
1703 void atomisp_css_get_dis_statistics(struct atomisp_sub_device
*asd
,
1704 struct atomisp_css_buffer
*isp_css_buffer
,
1705 struct ia_css_isp_dvs_statistics_map
*dvs_map
)
1707 if (asd
->params
.dvs_stat
) {
1709 ia_css_translate_dvs2_statistics(
1710 asd
->params
.dvs_stat
, dvs_map
);
1712 ia_css_get_dvs2_statistics(asd
->params
.dvs_stat
,
1713 isp_css_buffer
->css_buffer
.data
.stats_dvs
);
1718 int atomisp_css_dequeue_event(struct atomisp_css_event
*current_event
)
1720 if (ia_css_dequeue_event(¤t_event
->event
) != IA_CSS_SUCCESS
)
1726 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device
*asd
,
1727 struct atomisp_css_event
*current_event
)
1731 * Pipe ID reported in CSS event is not correct for new system's
1735 ia_css_temp_pipe_to_pipe_id(current_event
->event
.pipe
,
1736 ¤t_event
->pipe
);
1737 if (asd
&& asd
->copy_mode
&&
1738 current_event
->pipe
== IA_CSS_PIPE_ID_CAPTURE
)
1739 current_event
->pipe
= IA_CSS_PIPE_ID_COPY
;
1742 int atomisp_css_isys_set_resolution(struct atomisp_sub_device
*asd
,
1743 enum atomisp_input_stream_id stream_id
,
1744 struct v4l2_mbus_framefmt
*ffmt
,
1747 struct ia_css_stream_config
*s_config
=
1748 &asd
->stream_env
[stream_id
].stream_config
;
1750 if (isys_stream
>= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
)
1753 s_config
->isys_config
[isys_stream
].input_res
.width
= ffmt
->width
;
1754 s_config
->isys_config
[isys_stream
].input_res
.height
= ffmt
->height
;
1758 int atomisp_css_input_set_resolution(struct atomisp_sub_device
*asd
,
1759 enum atomisp_input_stream_id stream_id
,
1760 struct v4l2_mbus_framefmt
*ffmt
)
1762 struct ia_css_stream_config
*s_config
=
1763 &asd
->stream_env
[stream_id
].stream_config
;
1765 s_config
->input_config
.input_res
.width
= ffmt
->width
;
1766 s_config
->input_config
.input_res
.height
= ffmt
->height
;
1770 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device
*asd
,
1771 enum atomisp_input_stream_id stream_id
,
1772 unsigned int bin_factor
)
1774 asd
->stream_env
[stream_id
]
1775 .stream_config
.sensor_binning_factor
= bin_factor
;
1778 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device
*asd
,
1779 enum atomisp_input_stream_id stream_id
,
1780 enum atomisp_css_bayer_order bayer_order
)
1782 struct ia_css_stream_config
*s_config
=
1783 &asd
->stream_env
[stream_id
].stream_config
;
1784 s_config
->input_config
.bayer_order
= bayer_order
;
1787 void atomisp_css_isys_set_link(struct atomisp_sub_device
*asd
,
1788 enum atomisp_input_stream_id stream_id
,
1792 struct ia_css_stream_config
*s_config
=
1793 &asd
->stream_env
[stream_id
].stream_config
;
1795 s_config
->isys_config
[isys_stream
].linked_isys_stream_id
= link
;
1798 void atomisp_css_isys_set_valid(struct atomisp_sub_device
*asd
,
1799 enum atomisp_input_stream_id stream_id
,
1803 struct ia_css_stream_config
*s_config
=
1804 &asd
->stream_env
[stream_id
].stream_config
;
1806 s_config
->isys_config
[isys_stream
].valid
= valid
;
1809 void atomisp_css_isys_set_format(struct atomisp_sub_device
*asd
,
1810 enum atomisp_input_stream_id stream_id
,
1811 enum atomisp_css_stream_format format
,
1815 struct ia_css_stream_config
*s_config
=
1816 &asd
->stream_env
[stream_id
].stream_config
;
1818 s_config
->isys_config
[isys_stream
].format
= format
;
1821 void atomisp_css_input_set_format(struct atomisp_sub_device
*asd
,
1822 enum atomisp_input_stream_id stream_id
,
1823 enum atomisp_css_stream_format format
)
1826 struct ia_css_stream_config
*s_config
=
1827 &asd
->stream_env
[stream_id
].stream_config
;
1829 s_config
->input_config
.format
= format
;
1832 int atomisp_css_set_default_isys_config(struct atomisp_sub_device
*asd
,
1833 enum atomisp_input_stream_id stream_id
,
1834 struct v4l2_mbus_framefmt
*ffmt
)
1837 struct ia_css_stream_config
*s_config
=
1838 &asd
->stream_env
[stream_id
].stream_config
;
1840 * Set all isys configs to not valid.
1841 * Currently we support only one stream per channel
1843 for (i
= IA_CSS_STREAM_ISYS_STREAM_0
;
1844 i
< IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
; i
++)
1845 s_config
->isys_config
[i
].valid
= false;
1847 atomisp_css_isys_set_resolution(asd
, stream_id
, ffmt
,
1848 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
);
1849 atomisp_css_isys_set_format(asd
, stream_id
,
1850 s_config
->input_config
.format
,
1851 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
);
1852 atomisp_css_isys_set_link(asd
, stream_id
, NO_LINK
,
1853 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
);
1854 atomisp_css_isys_set_valid(asd
, stream_id
, true,
1855 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
);
1860 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device
*asd
,
1861 enum atomisp_input_stream_id stream_id
,
1862 enum atomisp_css_stream_format input_format
)
1864 struct ia_css_stream_config
*s_config
=
1865 &asd
->stream_env
[stream_id
].stream_config
;
1867 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].input_res
.width
=
1868 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].input_res
.width
;
1870 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].input_res
.height
=
1871 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].input_res
.height
/ 2;
1873 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].linked_isys_stream_id
1874 = IA_CSS_STREAM_ISYS_STREAM_0
;
1875 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].format
=
1876 IA_CSS_STREAM_FORMAT_USER_DEF1
;
1877 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].format
=
1878 IA_CSS_STREAM_FORMAT_USER_DEF2
;
1879 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].valid
= true;
1883 void atomisp_css_isys_two_stream_cfg_update_stream1(
1884 struct atomisp_sub_device
*asd
,
1885 enum atomisp_input_stream_id stream_id
,
1886 enum atomisp_css_stream_format input_format
,
1887 unsigned int width
, unsigned int height
)
1889 struct ia_css_stream_config
*s_config
=
1890 &asd
->stream_env
[stream_id
].stream_config
;
1892 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].input_res
.width
=
1894 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].input_res
.height
=
1896 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].format
=
1898 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_0
].valid
= true;
1901 void atomisp_css_isys_two_stream_cfg_update_stream2(
1902 struct atomisp_sub_device
*asd
,
1903 enum atomisp_input_stream_id stream_id
,
1904 enum atomisp_css_stream_format input_format
,
1905 unsigned int width
, unsigned int height
)
1907 struct ia_css_stream_config
*s_config
=
1908 &asd
->stream_env
[stream_id
].stream_config
;
1910 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].input_res
.width
=
1912 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].input_res
.height
=
1914 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].linked_isys_stream_id
1915 = IA_CSS_STREAM_ISYS_STREAM_0
;
1916 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].format
=
1918 s_config
->isys_config
[IA_CSS_STREAM_ISYS_STREAM_1
].valid
= true;
1921 int atomisp_css_input_set_effective_resolution(
1922 struct atomisp_sub_device
*asd
,
1923 enum atomisp_input_stream_id stream_id
,
1924 unsigned int width
, unsigned int height
)
1926 struct ia_css_stream_config
*s_config
=
1927 &asd
->stream_env
[stream_id
].stream_config
;
1928 s_config
->input_config
.effective_res
.width
= width
;
1929 s_config
->input_config
.effective_res
.height
= height
;
1933 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device
*asd
,
1934 unsigned int dvs_w
, unsigned int dvs_h
)
1936 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1937 .pipe_configs
[IA_CSS_PIPE_ID_VIDEO
].dvs_envelope
.width
= dvs_w
;
1938 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1939 .pipe_configs
[IA_CSS_PIPE_ID_VIDEO
].dvs_envelope
.height
= dvs_h
;
1942 void atomisp_css_input_set_two_pixels_per_clock(
1943 struct atomisp_sub_device
*asd
,
1948 if (asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1949 .stream_config
.pixels_per_clock
== (two_ppc
? 2 : 1))
1952 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1953 .stream_config
.pixels_per_clock
= (two_ppc
? 2 : 1);
1954 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
1955 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1956 .update_pipe
[i
] = true;
1959 void atomisp_css_enable_raw_binning(struct atomisp_sub_device
*asd
,
1962 struct atomisp_stream_env
*stream_env
=
1963 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
1966 if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
)
1967 pipe
= IA_CSS_PIPE_ID_VIDEO
;
1969 pipe
= IA_CSS_PIPE_ID_PREVIEW
;
1971 stream_env
->pipe_extra_configs
[pipe
].enable_raw_binning
= enable
;
1972 stream_env
->update_pipe
[pipe
] = true;
1974 stream_env
->pipe_configs
[pipe
].output_info
[0].padded_width
=
1975 stream_env
->stream_config
.input_config
.effective_res
.width
;
1978 void atomisp_css_enable_dz(struct atomisp_sub_device
*asd
, bool enable
)
1982 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
1983 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
1984 .pipe_configs
[i
].enable_dz
= enable
;
1987 void atomisp_css_capture_set_mode(struct atomisp_sub_device
*asd
,
1988 enum atomisp_css_capture_mode mode
)
1990 struct atomisp_stream_env
*stream_env
=
1991 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
1993 if (stream_env
->pipe_configs
[IA_CSS_PIPE_ID_CAPTURE
]
1994 .default_capture_config
.mode
== mode
)
1997 stream_env
->pipe_configs
[IA_CSS_PIPE_ID_CAPTURE
].
1998 default_capture_config
.mode
= mode
;
1999 stream_env
->update_pipe
[IA_CSS_PIPE_ID_CAPTURE
] = true;
2002 void atomisp_css_input_set_mode(struct atomisp_sub_device
*asd
,
2003 enum atomisp_css_input_mode mode
)
2006 struct atomisp_device
*isp
= asd
->isp
;
2007 unsigned int size_mem_words
;
2009 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++)
2010 asd
->stream_env
[i
].stream_config
.mode
= mode
;
2012 if (isp
->inputs
[asd
->input_curr
].type
== TEST_PATTERN
) {
2013 struct ia_css_stream_config
*s_config
=
2014 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream_config
;
2015 s_config
->mode
= IA_CSS_INPUT_MODE_TPG
;
2016 s_config
->source
.tpg
.mode
= IA_CSS_TPG_MODE_CHECKERBOARD
;
2017 s_config
->source
.tpg
.x_mask
= (1 << 4) - 1;
2018 s_config
->source
.tpg
.x_delta
= -2;
2019 s_config
->source
.tpg
.y_mask
= (1 << 4) - 1;
2020 s_config
->source
.tpg
.y_delta
= 3;
2021 s_config
->source
.tpg
.xy_mask
= (1 << 8) - 1;
2025 if (mode
!= IA_CSS_INPUT_MODE_BUFFERED_SENSOR
)
2028 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
2030 * TODO: sensor needs to export the embedded_data_size_words
2031 * information to atomisp for each setting.
2032 * Here using a large safe value.
2034 struct ia_css_stream_config
*s_config
=
2035 &asd
->stream_env
[i
].stream_config
;
2037 if (s_config
->input_config
.input_res
.width
== 0)
2040 if (ia_css_mipi_frame_calculate_size(
2041 s_config
->input_config
.input_res
.width
,
2042 s_config
->input_config
.input_res
.height
,
2043 s_config
->input_config
.format
,
2046 &size_mem_words
) != IA_CSS_SUCCESS
) {
2047 if (intel_mid_identify_cpu() ==
2048 INTEL_MID_CPU_CHIP_TANGIER
)
2049 size_mem_words
= CSS_MIPI_FRAME_BUFFER_SIZE_2
;
2051 size_mem_words
= CSS_MIPI_FRAME_BUFFER_SIZE_1
;
2052 dev_warn(asd
->isp
->dev
,
2053 "ia_css_mipi_frame_calculate_size failed,"
2054 "applying pre-defined MIPI buffer size %u.\n",
2057 s_config
->mipi_buffer_config
.size_mem_words
= size_mem_words
;
2058 s_config
->mipi_buffer_config
.nof_mipi_buffers
= 2;
2062 void atomisp_css_capture_enable_online(struct atomisp_sub_device
*asd
,
2063 unsigned short stream_index
, bool enable
)
2065 struct atomisp_stream_env
*stream_env
=
2066 &asd
->stream_env
[stream_index
];
2068 if (stream_env
->stream_config
.online
== !!enable
)
2071 stream_env
->stream_config
.online
= !!enable
;
2072 stream_env
->update_pipe
[IA_CSS_PIPE_ID_CAPTURE
] = true;
2075 void atomisp_css_preview_enable_online(struct atomisp_sub_device
*asd
,
2076 unsigned short stream_index
, bool enable
)
2078 struct atomisp_stream_env
*stream_env
=
2079 &asd
->stream_env
[stream_index
];
2082 if (stream_env
->stream_config
.online
!= !!enable
) {
2083 stream_env
->stream_config
.online
= !!enable
;
2084 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
2085 stream_env
->update_pipe
[i
] = true;
2089 void atomisp_css_video_enable_online(struct atomisp_sub_device
*asd
,
2092 struct atomisp_stream_env
*stream_env
=
2093 &asd
->stream_env
[ATOMISP_INPUT_STREAM_VIDEO
];
2096 if (stream_env
->stream_config
.online
!= enable
) {
2097 stream_env
->stream_config
.online
= enable
;
2098 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
2099 stream_env
->update_pipe
[i
] = true;
2103 void atomisp_css_enable_continuous(struct atomisp_sub_device
*asd
,
2106 struct atomisp_stream_env
*stream_env
=
2107 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2111 * To SOC camera, there is only one YUVPP pipe in any case
2112 * including ZSL/SDV/continuous viewfinder, so always set
2113 * stream_config.continuous to 0.
2115 if (ATOMISP_USE_YUVPP(asd
)) {
2116 stream_env
->stream_config
.continuous
= 0;
2117 stream_env
->stream_config
.online
= 1;
2121 if (stream_env
->stream_config
.continuous
!= !!enable
) {
2122 stream_env
->stream_config
.continuous
= !!enable
;
2123 stream_env
->stream_config
.pack_raw_pixels
= true;
2124 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
2125 stream_env
->update_pipe
[i
] = true;
2129 void atomisp_css_enable_cvf(struct atomisp_sub_device
*asd
,
2132 struct atomisp_stream_env
*stream_env
=
2133 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2136 if (stream_env
->stream_config
.disable_cont_viewfinder
!= !enable
) {
2137 stream_env
->stream_config
.disable_cont_viewfinder
= !enable
;
2138 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
2139 stream_env
->update_pipe
[i
] = true;
2143 int atomisp_css_input_configure_port(
2144 struct atomisp_sub_device
*asd
,
2145 mipi_port_ID_t port
,
2146 unsigned int num_lanes
,
2147 unsigned int timeout
,
2148 unsigned int mipi_freq
,
2149 enum atomisp_css_stream_format metadata_format
,
2150 unsigned int metadata_width
,
2151 unsigned int metadata_height
)
2154 struct atomisp_stream_env
*stream_env
;
2156 * Calculate rx_count as follows:
2157 * Input: mipi_freq : CSI-2 bus frequency in Hz
2158 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2159 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2160 * max = 145e-9 + 10 * UI
2161 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2162 * rxcount = rxcount0 - 2 : adjust for better results
2163 * The formula below is simplified version of the above with
2164 * 10-bit fixed points for improved accuracy.
2166 const unsigned int rxcount
=
2167 min(((mipi_freq
/ 46000) - 1280) >> 10, 0xffU
) * 0x01010101U
;
2169 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
2170 stream_env
= &asd
->stream_env
[i
];
2171 stream_env
->stream_config
.source
.port
.port
= port
;
2172 stream_env
->stream_config
.source
.port
.num_lanes
= num_lanes
;
2173 stream_env
->stream_config
.source
.port
.timeout
= timeout
;
2175 stream_env
->stream_config
.source
.port
.rxcount
= rxcount
;
2176 stream_env
->stream_config
.
2177 metadata_config
.data_type
= metadata_format
;
2178 stream_env
->stream_config
.
2179 metadata_config
.resolution
.width
= metadata_width
;
2180 stream_env
->stream_config
.
2181 metadata_config
.resolution
.height
= metadata_height
;
2187 int atomisp_css_frame_allocate(struct atomisp_css_frame
**frame
,
2188 unsigned int width
, unsigned int height
,
2189 enum atomisp_css_frame_format format
,
2190 unsigned int padded_width
,
2191 unsigned int raw_bit_depth
)
2193 if (ia_css_frame_allocate(frame
, width
, height
, format
,
2194 padded_width
, raw_bit_depth
) != IA_CSS_SUCCESS
)
2200 int atomisp_css_frame_allocate_from_info(struct atomisp_css_frame
**frame
,
2201 const struct atomisp_css_frame_info
*info
)
2203 if (ia_css_frame_allocate_from_info(frame
, info
) != IA_CSS_SUCCESS
)
2209 void atomisp_css_frame_free(struct atomisp_css_frame
*frame
)
2211 ia_css_frame_free(frame
);
2214 int atomisp_css_frame_map(struct atomisp_css_frame
**frame
,
2215 const struct atomisp_css_frame_info
*info
,
2216 const void *data
, uint16_t attribute
,
2219 if (ia_css_frame_map(frame
, info
, data
, attribute
, context
)
2226 int atomisp_css_set_black_frame(struct atomisp_sub_device
*asd
,
2227 const struct atomisp_css_frame
*raw_black_frame
)
2229 if (sh_css_set_black_frame(
2230 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
2231 raw_black_frame
) != IA_CSS_SUCCESS
)
2237 int atomisp_css_allocate_continuous_frames(bool init_time
,
2238 struct atomisp_sub_device
*asd
)
2240 if (ia_css_alloc_continuous_frame_remain(
2241 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
)
2247 void atomisp_css_update_continuous_frames(struct atomisp_sub_device
*asd
)
2249 ia_css_update_continuous_frames(
2250 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
);
2253 int atomisp_css_stop(struct atomisp_sub_device
*asd
,
2254 enum atomisp_css_pipe_id pipe_id
, bool in_reset
)
2256 struct atomisp_device
*isp
= asd
->isp
;
2257 struct atomisp_s3a_buf
*s3a_buf
;
2258 struct atomisp_dis_buf
*dis_buf
;
2259 struct atomisp_metadata_buf
*md_buf
;
2260 unsigned long irqflags
;
2263 /* if is called in atomisp_reset(), force destroy stream */
2264 if (__destroy_streams(asd
, true))
2265 dev_err(isp
->dev
, "destroy stream failed.\n");
2267 /* if is called in atomisp_reset(), force destroy all pipes */
2268 if (__destroy_pipes(asd
, true))
2269 dev_err(isp
->dev
, "destroy pipes failed.\n");
2271 atomisp_init_raw_buffer_bitmap(asd
);
2274 * SP can not be stop if other streams are in use
2276 if (atomisp_streaming_count(isp
) == 0)
2280 struct atomisp_stream_env
*stream_env
;
2283 for (i
= 0; i
< ATOMISP_INPUT_STREAM_NUM
; i
++) {
2284 stream_env
= &asd
->stream_env
[i
];
2285 for (j
= 0; j
< IA_CSS_PIPE_ID_NUM
; j
++) {
2286 ia_css_pipe_config_defaults(
2287 &stream_env
->pipe_configs
[j
]);
2288 ia_css_pipe_extra_config_defaults(
2289 &stream_env
->pipe_extra_configs
[j
]);
2291 ia_css_stream_config_defaults(
2292 &stream_env
->stream_config
);
2294 atomisp_isp_parameters_clean_up(&asd
->params
.config
);
2295 asd
->params
.css_update_params_needed
= false;
2298 /* move stats buffers to free queue list */
2299 while (!list_empty(&asd
->s3a_stats_in_css
)) {
2300 s3a_buf
= list_entry(asd
->s3a_stats_in_css
.next
,
2301 struct atomisp_s3a_buf
, list
);
2302 list_del(&s3a_buf
->list
);
2303 list_add_tail(&s3a_buf
->list
, &asd
->s3a_stats
);
2305 while (!list_empty(&asd
->s3a_stats_ready
)) {
2306 s3a_buf
= list_entry(asd
->s3a_stats_ready
.next
,
2307 struct atomisp_s3a_buf
, list
);
2308 list_del(&s3a_buf
->list
);
2309 list_add_tail(&s3a_buf
->list
, &asd
->s3a_stats
);
2312 spin_lock_irqsave(&asd
->dis_stats_lock
, irqflags
);
2313 while (!list_empty(&asd
->dis_stats_in_css
)) {
2314 dis_buf
= list_entry(asd
->dis_stats_in_css
.next
,
2315 struct atomisp_dis_buf
, list
);
2316 list_del(&dis_buf
->list
);
2317 list_add_tail(&dis_buf
->list
, &asd
->dis_stats
);
2319 asd
->params
.dis_proj_data_valid
= false;
2320 spin_unlock_irqrestore(&asd
->dis_stats_lock
, irqflags
);
2322 for (i
= 0; i
< ATOMISP_METADATA_TYPE_NUM
; i
++) {
2323 while (!list_empty(&asd
->metadata_in_css
[i
])) {
2324 md_buf
= list_entry(asd
->metadata_in_css
[i
].next
,
2325 struct atomisp_metadata_buf
, list
);
2326 list_del(&md_buf
->list
);
2327 list_add_tail(&md_buf
->list
, &asd
->metadata
[i
]);
2329 while (!list_empty(&asd
->metadata_ready
[i
])) {
2330 md_buf
= list_entry(asd
->metadata_ready
[i
].next
,
2331 struct atomisp_metadata_buf
, list
);
2332 list_del(&md_buf
->list
);
2333 list_add_tail(&md_buf
->list
, &asd
->metadata
[i
]);
2337 atomisp_flush_params_queue(&asd
->video_out_capture
);
2338 atomisp_flush_params_queue(&asd
->video_out_vf
);
2339 atomisp_flush_params_queue(&asd
->video_out_preview
);
2340 atomisp_flush_params_queue(&asd
->video_out_video_capture
);
2341 atomisp_free_css_parameters(&asd
->params
.css_param
);
2342 memset(&asd
->params
.css_param
, 0, sizeof(asd
->params
.css_param
));
2346 int atomisp_css_continuous_set_num_raw_frames(
2347 struct atomisp_sub_device
*asd
,
2350 if (asd
->enable_raw_buffer_lock
->val
) {
2351 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2352 .stream_config
.init_num_cont_raw_buf
=
2353 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN
;
2354 if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
&&
2355 asd
->params
.video_dis_en
)
2356 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2357 .stream_config
.init_num_cont_raw_buf
+=
2358 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY
;
2360 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2361 .stream_config
.init_num_cont_raw_buf
=
2362 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES
;
2365 if (asd
->params
.video_dis_en
)
2366 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2367 .stream_config
.init_num_cont_raw_buf
+=
2368 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY
;
2370 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2371 .stream_config
.target_num_cont_raw_buf
= num_frames
;
2375 void atomisp_css_disable_vf_pp(struct atomisp_sub_device
*asd
,
2380 for (i
= 0; i
< IA_CSS_PIPE_ID_NUM
; i
++)
2381 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
2382 .pipe_extra_configs
[i
].disable_vf_pp
= !!disable
;
2385 static enum ia_css_pipe_mode
__pipe_id_to_pipe_mode(
2386 struct atomisp_sub_device
*asd
,
2387 enum ia_css_pipe_id pipe_id
)
2389 struct atomisp_device
*isp
= asd
->isp
;
2390 struct camera_mipi_info
*mipi_info
= atomisp_to_sensor_mipi_info(
2391 isp
->inputs
[asd
->input_curr
].camera
);
2394 case IA_CSS_PIPE_ID_COPY
:
2395 /* Currently only YUVPP mode supports YUV420_Legacy format.
2396 * Revert this when other pipe modes can support
2397 * YUV420_Legacy format.
2399 if (mipi_info
&& mipi_info
->input_format
==
2400 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY
)
2401 return IA_CSS_PIPE_MODE_YUVPP
;
2402 return IA_CSS_PIPE_MODE_COPY
;
2403 case IA_CSS_PIPE_ID_PREVIEW
:
2404 return IA_CSS_PIPE_MODE_PREVIEW
;
2405 case IA_CSS_PIPE_ID_CAPTURE
:
2406 return IA_CSS_PIPE_MODE_CAPTURE
;
2407 case IA_CSS_PIPE_ID_VIDEO
:
2408 return IA_CSS_PIPE_MODE_VIDEO
;
2409 case IA_CSS_PIPE_ID_ACC
:
2410 return IA_CSS_PIPE_MODE_ACC
;
2411 case IA_CSS_PIPE_ID_YUVPP
:
2412 return IA_CSS_PIPE_MODE_YUVPP
;
2415 return IA_CSS_PIPE_MODE_PREVIEW
;
2420 static void __configure_output(struct atomisp_sub_device
*asd
,
2421 unsigned int stream_index
,
2422 unsigned int width
, unsigned int height
,
2423 unsigned int min_width
,
2424 enum ia_css_frame_format format
,
2425 enum ia_css_pipe_id pipe_id
)
2427 struct atomisp_device
*isp
= asd
->isp
;
2428 struct atomisp_stream_env
*stream_env
=
2429 &asd
->stream_env
[stream_index
];
2430 struct ia_css_stream_config
*s_config
= &stream_env
->stream_config
;
2432 stream_env
->pipe_configs
[pipe_id
].mode
=
2433 __pipe_id_to_pipe_mode(asd
, pipe_id
);
2434 stream_env
->update_pipe
[pipe_id
] = true;
2436 stream_env
->pipe_configs
[pipe_id
].output_info
[0].res
.width
= width
;
2437 stream_env
->pipe_configs
[pipe_id
].output_info
[0].res
.height
= height
;
2438 stream_env
->pipe_configs
[pipe_id
].output_info
[0].format
= format
;
2439 stream_env
->pipe_configs
[pipe_id
].output_info
[0].padded_width
= min_width
;
2441 /* isp binary 2.2 specific setting*/
2442 if (width
> s_config
->input_config
.effective_res
.width
||
2443 height
> s_config
->input_config
.effective_res
.height
) {
2444 s_config
->input_config
.effective_res
.width
= width
;
2445 s_config
->input_config
.effective_res
.height
= height
;
2448 dev_dbg(isp
->dev
, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2449 pipe_id
, width
, height
, format
);
2452 static void __configure_video_preview_output(struct atomisp_sub_device
*asd
,
2453 unsigned int stream_index
,
2454 unsigned int width
, unsigned int height
,
2455 unsigned int min_width
,
2456 enum ia_css_frame_format format
,
2457 enum ia_css_pipe_id pipe_id
)
2459 struct atomisp_device
*isp
= asd
->isp
;
2460 struct atomisp_stream_env
*stream_env
=
2461 &asd
->stream_env
[stream_index
];
2462 struct ia_css_frame_info
*css_output_info
;
2463 struct ia_css_stream_config
*stream_config
= &stream_env
->stream_config
;
2465 stream_env
->pipe_configs
[pipe_id
].mode
=
2466 __pipe_id_to_pipe_mode(asd
, pipe_id
);
2467 stream_env
->update_pipe
[pipe_id
] = true;
2470 * second_output will be as video main output in SDV mode
2471 * with SOC camera. output will be as video main output in
2472 * normal video mode.
2474 if (asd
->continuous_mode
->val
)
2475 css_output_info
= &stream_env
->pipe_configs
[pipe_id
].
2476 output_info
[ATOMISP_CSS_OUTPUT_SECOND_INDEX
];
2478 css_output_info
= &stream_env
->pipe_configs
[pipe_id
].
2479 output_info
[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX
];
2481 css_output_info
->res
.width
= width
;
2482 css_output_info
->res
.height
= height
;
2483 css_output_info
->format
= format
;
2484 css_output_info
->padded_width
= min_width
;
2486 /* isp binary 2.2 specific setting*/
2487 if (width
> stream_config
->input_config
.effective_res
.width
||
2488 height
> stream_config
->input_config
.effective_res
.height
) {
2489 stream_config
->input_config
.effective_res
.width
= width
;
2490 stream_config
->input_config
.effective_res
.height
= height
;
2493 dev_dbg(isp
->dev
, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2494 pipe_id
, width
, height
, format
);
2498 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2499 * downscaling input resolution.
2501 static void __configure_capture_pp_input(struct atomisp_sub_device
*asd
,
2502 unsigned int width
, unsigned int height
,
2503 enum ia_css_pipe_id pipe_id
)
2505 struct atomisp_device
*isp
= asd
->isp
;
2506 struct atomisp_stream_env
*stream_env
=
2507 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2508 struct ia_css_stream_config
*stream_config
= &stream_env
->stream_config
;
2509 struct ia_css_pipe_config
*pipe_configs
=
2510 &stream_env
->pipe_configs
[pipe_id
];
2511 struct ia_css_pipe_extra_config
*pipe_extra_configs
=
2512 &stream_env
->pipe_extra_configs
[pipe_id
];
2513 unsigned int hor_ds_factor
= 0, ver_ds_factor
= 0;
2515 if (width
== 0 && height
== 0)
2518 if (width
* 9 / 10 < pipe_configs
->output_info
[0].res
.width
||
2519 height
* 9 / 10 < pipe_configs
->output_info
[0].res
.height
)
2521 /* here just copy the calculation in css */
2522 hor_ds_factor
= CEIL_DIV(width
>> 1,
2523 pipe_configs
->output_info
[0].res
.width
);
2524 ver_ds_factor
= CEIL_DIV(height
>> 1,
2525 pipe_configs
->output_info
[0].res
.height
);
2527 if ((asd
->isp
->media_dev
.hw_revision
<
2528 (ATOMISP_HW_REVISION_ISP2401
<< ATOMISP_HW_REVISION_SHIFT
) ||
2529 IS_CHT
) && hor_ds_factor
!= ver_ds_factor
) {
2530 dev_warn(asd
->isp
->dev
,
2531 "Cropping for capture due to FW limitation");
2535 pipe_configs
->mode
= __pipe_id_to_pipe_mode(asd
, pipe_id
);
2536 stream_env
->update_pipe
[pipe_id
] = true;
2538 pipe_extra_configs
->enable_yuv_ds
= true;
2540 pipe_configs
->capt_pp_in_res
.width
=
2541 stream_config
->input_config
.effective_res
.width
;
2542 pipe_configs
->capt_pp_in_res
.height
=
2543 stream_config
->input_config
.effective_res
.height
;
2545 dev_dbg(isp
->dev
, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2546 pipe_id
, width
, height
);
2550 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2551 * yuv downscaling, which needs addtional configurations.
2553 static void __configure_preview_pp_input(struct atomisp_sub_device
*asd
,
2554 unsigned int width
, unsigned int height
,
2555 enum ia_css_pipe_id pipe_id
)
2557 struct atomisp_device
*isp
= asd
->isp
;
2558 int out_width
, out_height
, yuv_ds_in_width
, yuv_ds_in_height
;
2559 struct atomisp_stream_env
*stream_env
=
2560 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2561 struct ia_css_stream_config
*stream_config
= &stream_env
->stream_config
;
2562 struct ia_css_pipe_config
*pipe_configs
=
2563 &stream_env
->pipe_configs
[pipe_id
];
2564 struct ia_css_pipe_extra_config
*pipe_extra_configs
=
2565 &stream_env
->pipe_extra_configs
[pipe_id
];
2566 struct ia_css_resolution
*bayer_ds_out_res
=
2567 &pipe_configs
->bayer_ds_out_res
;
2568 struct ia_css_resolution
*vf_pp_in_res
=
2569 &pipe_configs
->vf_pp_in_res
;
2570 struct ia_css_resolution
*effective_res
=
2571 &stream_config
->input_config
.effective_res
;
2573 const struct bayer_ds_factor bds_fct
[] = {{2, 1}, {3, 2}, {5, 4} };
2575 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2576 * columns to be shaded. Remove this factor to work around the CSS bug.
2577 * const unsigned int yuv_dec_fct[] = {4, 2};
2579 const unsigned int yuv_dec_fct
[] = { 2 };
2582 if (width
== 0 && height
== 0)
2585 pipe_configs
->mode
= __pipe_id_to_pipe_mode(asd
, pipe_id
);
2586 stream_env
->update_pipe
[pipe_id
] = true;
2588 out_width
= pipe_configs
->output_info
[0].res
.width
;
2589 out_height
= pipe_configs
->output_info
[0].res
.height
;
2592 * The ISP could do bayer downscaling, yuv decimation and yuv
2594 * 1: Bayer Downscaling: between effective resolution and
2596 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2597 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2599 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2600 * Rule for YUV Decimation: support factor 2, 4
2601 * Rule for YUV Downscaling: arbitary value below 2
2603 * General rule of factor distribution among these stages:
2604 * 1: try to do Bayer downscaling first if not in online mode.
2605 * 2: try to do maximum of 2 for YUV downscaling
2606 * 3: the remainling for YUV decimation
2609 * Do not configure bayer_ds_out_res if:
2610 * online == 1 or continuous == 0 or raw_binning = 0
2612 if (stream_config
->online
|| !stream_config
->continuous
||
2613 !pipe_extra_configs
->enable_raw_binning
) {
2614 bayer_ds_out_res
->width
= 0;
2615 bayer_ds_out_res
->height
= 0;
2617 bayer_ds_out_res
->width
= effective_res
->width
;
2618 bayer_ds_out_res
->height
= effective_res
->height
;
2620 for (i
= 0; i
< ARRAY_SIZE(bds_fct
); i
++) {
2621 if (effective_res
->width
>= out_width
*
2622 bds_fct
[i
].numerator
/ bds_fct
[i
].denominator
&&
2623 effective_res
->height
>= out_height
*
2624 bds_fct
[i
].numerator
/ bds_fct
[i
].denominator
) {
2625 bayer_ds_out_res
->width
=
2626 effective_res
->width
*
2627 bds_fct
[i
].denominator
/
2628 bds_fct
[i
].numerator
;
2629 bayer_ds_out_res
->height
=
2630 effective_res
->height
*
2631 bds_fct
[i
].denominator
/
2632 bds_fct
[i
].numerator
;
2638 * calculate YUV Decimation, YUV downscaling facor:
2639 * YUV Downscaling factor must not exceed 2.
2640 * YUV Decimation factor could be 2, 4.
2642 /* first decide the yuv_ds input resolution */
2643 if (bayer_ds_out_res
->width
== 0) {
2644 yuv_ds_in_width
= effective_res
->width
;
2645 yuv_ds_in_height
= effective_res
->height
;
2647 yuv_ds_in_width
= bayer_ds_out_res
->width
;
2648 yuv_ds_in_height
= bayer_ds_out_res
->height
;
2651 vf_pp_in_res
->width
= yuv_ds_in_width
;
2652 vf_pp_in_res
->height
= yuv_ds_in_height
;
2654 /* find out the yuv decimation factor */
2655 for (i
= 0; i
< ARRAY_SIZE(yuv_dec_fct
); i
++) {
2656 if (yuv_ds_in_width
>= out_width
* yuv_dec_fct
[i
] &&
2657 yuv_ds_in_height
>= out_height
* yuv_dec_fct
[i
]) {
2658 vf_pp_in_res
->width
= yuv_ds_in_width
/ yuv_dec_fct
[i
];
2659 vf_pp_in_res
->height
= yuv_ds_in_height
/ yuv_dec_fct
[i
];
2664 if (vf_pp_in_res
->width
== out_width
&&
2665 vf_pp_in_res
->height
== out_height
) {
2666 pipe_extra_configs
->enable_yuv_ds
= false;
2667 vf_pp_in_res
->width
= 0;
2668 vf_pp_in_res
->height
= 0;
2670 pipe_extra_configs
->enable_yuv_ds
= true;
2673 dev_dbg(isp
->dev
, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2674 pipe_id
, width
, height
);
2678 * For CSS2.1, offline video pipe could support bayer decimation, and
2679 * yuv downscaling, which needs addtional configurations.
2681 static void __configure_video_pp_input(struct atomisp_sub_device
*asd
,
2682 unsigned int width
, unsigned int height
,
2683 enum ia_css_pipe_id pipe_id
)
2685 struct atomisp_device
*isp
= asd
->isp
;
2686 int out_width
, out_height
;
2687 struct atomisp_stream_env
*stream_env
=
2688 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2689 struct ia_css_stream_config
*stream_config
= &stream_env
->stream_config
;
2690 struct ia_css_pipe_config
*pipe_configs
=
2691 &stream_env
->pipe_configs
[pipe_id
];
2692 struct ia_css_pipe_extra_config
*pipe_extra_configs
=
2693 &stream_env
->pipe_extra_configs
[pipe_id
];
2694 struct ia_css_resolution
*bayer_ds_out_res
=
2695 &pipe_configs
->bayer_ds_out_res
;
2696 struct ia_css_resolution
*effective_res
=
2697 &stream_config
->input_config
.effective_res
;
2699 const struct bayer_ds_factor bds_factors
[] = {
2700 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} };
2703 if (width
== 0 && height
== 0)
2706 pipe_configs
->mode
= __pipe_id_to_pipe_mode(asd
, pipe_id
);
2707 stream_env
->update_pipe
[pipe_id
] = true;
2709 pipe_extra_configs
->enable_yuv_ds
= false;
2712 * If DVS is enabled, video binary will take care the dvs envelope
2713 * and usually the bayer_ds_out_res should be larger than 120% of
2714 * destination resolution, the extra 20% will be cropped as DVS
2715 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2716 * destination. The ISP can still work, but DVS quality is not good.
2718 /* taking at least 10% as envelope */
2719 if (asd
->params
.video_dis_en
) {
2720 out_width
= pipe_configs
->output_info
[0].res
.width
* 110 / 100;
2721 out_height
= pipe_configs
->output_info
[0].res
.height
* 110 / 100;
2723 out_width
= pipe_configs
->output_info
[0].res
.width
;
2724 out_height
= pipe_configs
->output_info
[0].res
.height
;
2728 * calculate bayer decimate factor:
2729 * 1: only 1.5, 2, 4 and 8 get supported
2730 * 2: Do not configure bayer_ds_out_res if:
2731 * online == 1 or continuous == 0 or raw_binning = 0
2733 if (stream_config
->online
|| !stream_config
->continuous
) {
2734 bayer_ds_out_res
->width
= 0;
2735 bayer_ds_out_res
->height
= 0;
2739 pipe_extra_configs
->enable_raw_binning
= true;
2740 bayer_ds_out_res
->width
= effective_res
->width
;
2741 bayer_ds_out_res
->height
= effective_res
->height
;
2743 for (i
= 0; i
< sizeof(bds_factors
) / sizeof(struct bayer_ds_factor
);
2745 if (effective_res
->width
>= out_width
*
2746 bds_factors
[i
].numerator
/ bds_factors
[i
].denominator
&&
2747 effective_res
->height
>= out_height
*
2748 bds_factors
[i
].numerator
/ bds_factors
[i
].denominator
) {
2749 bayer_ds_out_res
->width
= effective_res
->width
*
2750 bds_factors
[i
].denominator
/
2751 bds_factors
[i
].numerator
;
2752 bayer_ds_out_res
->height
= effective_res
->height
*
2753 bds_factors
[i
].denominator
/
2754 bds_factors
[i
].numerator
;
2760 * DVS is cropped from BDS output, so we do not really need to set the
2761 * envelope to 20% of output resolution here. always set it to 12x12
2762 * per firmware requirement.
2764 pipe_configs
->dvs_envelope
.width
= 12;
2765 pipe_configs
->dvs_envelope
.height
= 12;
2768 if (pipe_id
== IA_CSS_PIPE_ID_YUVPP
)
2769 stream_config
->left_padding
= -1;
2771 stream_config
->left_padding
= 12;
2772 dev_dbg(isp
->dev
, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2773 pipe_id
, width
, height
);
2776 static void __configure_vf_output(struct atomisp_sub_device
*asd
,
2777 unsigned int width
, unsigned int height
,
2778 unsigned int min_width
,
2779 enum atomisp_css_frame_format format
,
2780 enum ia_css_pipe_id pipe_id
)
2782 struct atomisp_device
*isp
= asd
->isp
;
2783 struct atomisp_stream_env
*stream_env
=
2784 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2785 stream_env
->pipe_configs
[pipe_id
].mode
=
2786 __pipe_id_to_pipe_mode(asd
, pipe_id
);
2787 stream_env
->update_pipe
[pipe_id
] = true;
2789 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].res
.width
= width
;
2790 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].res
.height
= height
;
2791 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].format
= format
;
2792 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].padded_width
=
2795 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2796 pipe_id
, width
, height
, format
);
2799 static void __configure_video_vf_output(struct atomisp_sub_device
*asd
,
2800 unsigned int width
, unsigned int height
,
2801 unsigned int min_width
,
2802 enum atomisp_css_frame_format format
,
2803 enum ia_css_pipe_id pipe_id
)
2805 struct atomisp_device
*isp
= asd
->isp
;
2806 struct atomisp_stream_env
*stream_env
=
2807 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
2808 struct ia_css_frame_info
*css_output_info
;
2810 stream_env
->pipe_configs
[pipe_id
].mode
=
2811 __pipe_id_to_pipe_mode(asd
, pipe_id
);
2812 stream_env
->update_pipe
[pipe_id
] = true;
2815 * second_vf_output will be as video viewfinder in SDV mode
2816 * with SOC camera. vf_output will be as video viewfinder in
2817 * normal video mode.
2819 if (asd
->continuous_mode
->val
)
2820 css_output_info
= &stream_env
->pipe_configs
[pipe_id
].
2821 vf_output_info
[ATOMISP_CSS_OUTPUT_SECOND_INDEX
];
2823 css_output_info
= &stream_env
->pipe_configs
[pipe_id
].
2824 vf_output_info
[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX
];
2826 css_output_info
->res
.width
= width
;
2827 css_output_info
->res
.height
= height
;
2828 css_output_info
->format
= format
;
2829 css_output_info
->padded_width
= min_width
;
2831 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2832 pipe_id
, width
, height
, format
);
2835 static int __get_frame_info(struct atomisp_sub_device
*asd
,
2836 unsigned int stream_index
,
2837 struct atomisp_css_frame_info
*info
,
2838 enum frame_info_type type
,
2839 enum ia_css_pipe_id pipe_id
)
2841 struct atomisp_device
*isp
= asd
->isp
;
2842 enum ia_css_err ret
;
2843 struct ia_css_pipe_info p_info
;
2845 /* FIXME! No need to destroy/recreate all streams */
2846 if (__destroy_streams(asd
, true))
2847 dev_warn(isp
->dev
, "destroy stream failed.\n");
2849 if (__destroy_pipes(asd
, true))
2850 dev_warn(isp
->dev
, "destroy pipe failed.\n");
2852 if (__create_pipes(asd
))
2855 if (__create_streams(asd
))
2858 ret
= ia_css_pipe_get_info(
2859 asd
->stream_env
[stream_index
]
2860 .pipes
[pipe_id
], &p_info
);
2861 if (ret
== IA_CSS_SUCCESS
) {
2863 case ATOMISP_CSS_VF_FRAME
:
2864 *info
= p_info
.vf_output_info
[0];
2865 dev_dbg(isp
->dev
, "getting vf frame info.\n");
2867 case ATOMISP_CSS_SECOND_VF_FRAME
:
2868 *info
= p_info
.vf_output_info
[1];
2869 dev_dbg(isp
->dev
, "getting second vf frame info.\n");
2871 case ATOMISP_CSS_OUTPUT_FRAME
:
2872 *info
= p_info
.output_info
[0];
2873 dev_dbg(isp
->dev
, "getting main frame info.\n");
2875 case ATOMISP_CSS_SECOND_OUTPUT_FRAME
:
2876 *info
= p_info
.output_info
[1];
2877 dev_dbg(isp
->dev
, "getting second main frame info.\n");
2879 case ATOMISP_CSS_RAW_FRAME
:
2880 *info
= p_info
.raw_output_info
;
2881 dev_dbg(isp
->dev
, "getting raw frame info.\n");
2883 dev_dbg(isp
->dev
, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2884 info
->res
.width
, info
->res
.height
, p_info
.num_invalid_frames
);
2889 __destroy_pipes(asd
, true);
2893 unsigned int atomisp_get_pipe_index(struct atomisp_sub_device
*asd
,
2894 uint16_t source_pad
)
2896 struct atomisp_device
*isp
= asd
->isp
;
2898 * to SOC camera, use yuvpp pipe.
2900 if (ATOMISP_USE_YUVPP(asd
))
2901 return IA_CSS_PIPE_ID_YUVPP
;
2903 switch (source_pad
) {
2904 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO
:
2905 if (asd
->yuvpp_mode
)
2906 return IA_CSS_PIPE_ID_YUVPP
;
2908 return IA_CSS_PIPE_ID_COPY
;
2909 if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
2910 || asd
->vfpp
->val
== ATOMISP_VFPP_DISABLE_SCALER
)
2911 return IA_CSS_PIPE_ID_VIDEO
;
2913 return IA_CSS_PIPE_ID_CAPTURE
;
2914 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
:
2916 return IA_CSS_PIPE_ID_COPY
;
2917 return IA_CSS_PIPE_ID_CAPTURE
;
2918 case ATOMISP_SUBDEV_PAD_SOURCE_VF
:
2919 if (!atomisp_is_mbuscode_raw(
2920 asd
->fmt
[asd
->capture_pad
].fmt
.code
))
2921 return IA_CSS_PIPE_ID_CAPTURE
;
2922 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
:
2923 if (asd
->yuvpp_mode
)
2924 return IA_CSS_PIPE_ID_YUVPP
;
2926 return IA_CSS_PIPE_ID_COPY
;
2927 if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
)
2928 return IA_CSS_PIPE_ID_VIDEO
;
2930 return IA_CSS_PIPE_ID_PREVIEW
;
2933 "invalid source pad:%d, return default preview pipe index.\n",
2935 return IA_CSS_PIPE_ID_PREVIEW
;
2938 int atomisp_get_css_frame_info(struct atomisp_sub_device
*asd
,
2939 uint16_t source_pad
,
2940 struct atomisp_css_frame_info
*frame_info
)
2942 struct ia_css_pipe_info info
;
2943 int pipe_index
= atomisp_get_pipe_index(asd
, source_pad
);
2945 struct atomisp_device
*isp
= asd
->isp
;
2947 if (ATOMISP_SOC_CAMERA(asd
))
2948 stream_index
= atomisp_source_pad_to_stream_id(asd
, source_pad
);
2950 stream_index
= (pipe_index
== IA_CSS_PIPE_ID_YUVPP
) ?
2951 ATOMISP_INPUT_STREAM_VIDEO
:
2952 atomisp_source_pad_to_stream_id(asd
, source_pad
);
2955 if (IA_CSS_SUCCESS
!= ia_css_pipe_get_info(asd
->stream_env
[stream_index
]
2956 .pipes
[pipe_index
], &info
)) {
2957 dev_err(isp
->dev
, "ia_css_pipe_get_info FAILED");
2961 switch (source_pad
) {
2962 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE
:
2963 *frame_info
= info
.output_info
[0];
2965 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO
:
2966 if (ATOMISP_USE_YUVPP(asd
) && asd
->continuous_mode
->val
)
2968 output_info
[ATOMISP_CSS_OUTPUT_SECOND_INDEX
];
2971 output_info
[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX
];
2973 case ATOMISP_SUBDEV_PAD_SOURCE_VF
:
2974 if (stream_index
== ATOMISP_INPUT_STREAM_POSTVIEW
)
2975 *frame_info
= info
.output_info
[0];
2977 *frame_info
= info
.vf_output_info
[0];
2979 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW
:
2980 if (asd
->run_mode
->val
== ATOMISP_RUN_MODE_VIDEO
&&
2981 (pipe_index
== IA_CSS_PIPE_ID_VIDEO
||
2982 pipe_index
== IA_CSS_PIPE_ID_YUVPP
))
2983 if (ATOMISP_USE_YUVPP(asd
) && asd
->continuous_mode
->val
)
2985 vf_output_info
[ATOMISP_CSS_OUTPUT_SECOND_INDEX
];
2988 vf_output_info
[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX
];
2989 else if (ATOMISP_USE_YUVPP(asd
) && asd
->continuous_mode
->val
)
2991 info
.output_info
[ATOMISP_CSS_OUTPUT_SECOND_INDEX
];
2994 info
.output_info
[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX
];
3001 return frame_info
? 0 : -EINVAL
;
3004 int atomisp_css_copy_configure_output(struct atomisp_sub_device
*asd
,
3005 unsigned int stream_index
,
3006 unsigned int width
, unsigned int height
,
3007 unsigned int padded_width
,
3008 enum atomisp_css_frame_format format
)
3010 asd
->stream_env
[stream_index
].pipe_configs
[IA_CSS_PIPE_ID_COPY
].
3011 default_capture_config
.mode
=
3012 CSS_CAPTURE_MODE_RAW
;
3014 __configure_output(asd
, stream_index
, width
, height
, padded_width
,
3015 format
, IA_CSS_PIPE_ID_COPY
);
3019 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device
*asd
,
3020 unsigned int stream_index
,
3021 unsigned int width
, unsigned int height
,
3022 unsigned int padded_width
,
3023 enum atomisp_css_frame_format format
)
3025 asd
->stream_env
[stream_index
].pipe_configs
[IA_CSS_PIPE_ID_YUVPP
].
3026 default_capture_config
.mode
=
3027 CSS_CAPTURE_MODE_RAW
;
3029 __configure_output(asd
, stream_index
, width
, height
, padded_width
,
3030 format
, IA_CSS_PIPE_ID_YUVPP
);
3034 int atomisp_css_yuvpp_configure_viewfinder(
3035 struct atomisp_sub_device
*asd
,
3036 unsigned int stream_index
,
3037 unsigned int width
, unsigned int height
,
3038 unsigned int min_width
,
3039 enum atomisp_css_frame_format format
)
3041 struct atomisp_stream_env
*stream_env
=
3042 &asd
->stream_env
[stream_index
];
3043 enum ia_css_pipe_id pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3045 stream_env
->pipe_configs
[pipe_id
].mode
=
3046 __pipe_id_to_pipe_mode(asd
, pipe_id
);
3047 stream_env
->update_pipe
[pipe_id
] = true;
3049 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].res
.width
= width
;
3050 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].res
.height
= height
;
3051 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].format
= format
;
3052 stream_env
->pipe_configs
[pipe_id
].vf_output_info
[0].padded_width
=
3057 int atomisp_css_yuvpp_get_output_frame_info(
3058 struct atomisp_sub_device
*asd
,
3059 unsigned int stream_index
,
3060 struct atomisp_css_frame_info
*info
)
3062 return __get_frame_info(asd
, stream_index
, info
,
3063 ATOMISP_CSS_OUTPUT_FRAME
, IA_CSS_PIPE_ID_YUVPP
);
3066 int atomisp_css_yuvpp_get_viewfinder_frame_info(
3067 struct atomisp_sub_device
*asd
,
3068 unsigned int stream_index
,
3069 struct atomisp_css_frame_info
*info
)
3071 return __get_frame_info(asd
, stream_index
, info
,
3072 ATOMISP_CSS_VF_FRAME
, IA_CSS_PIPE_ID_YUVPP
);
3075 int atomisp_css_preview_configure_output(struct atomisp_sub_device
*asd
,
3076 unsigned int width
, unsigned int height
,
3077 unsigned int min_width
,
3078 enum atomisp_css_frame_format format
)
3081 * to SOC camera, use yuvpp pipe.
3083 if (ATOMISP_USE_YUVPP(asd
))
3084 __configure_video_preview_output(asd
, ATOMISP_INPUT_STREAM_GENERAL
, width
, height
,
3085 min_width
, format
, IA_CSS_PIPE_ID_YUVPP
);
3087 __configure_output(asd
, ATOMISP_INPUT_STREAM_GENERAL
, width
, height
,
3088 min_width
, format
, IA_CSS_PIPE_ID_PREVIEW
);
3092 int atomisp_css_capture_configure_output(struct atomisp_sub_device
*asd
,
3093 unsigned int width
, unsigned int height
,
3094 unsigned int min_width
,
3095 enum atomisp_css_frame_format format
)
3097 enum ia_css_pipe_id pipe_id
;
3100 * to SOC camera, use yuvpp pipe.
3102 if (ATOMISP_USE_YUVPP(asd
))
3103 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3105 pipe_id
= IA_CSS_PIPE_ID_CAPTURE
;
3107 __configure_output(asd
, ATOMISP_INPUT_STREAM_GENERAL
, width
, height
,
3108 min_width
, format
, pipe_id
);
3112 int atomisp_css_video_configure_output(struct atomisp_sub_device
*asd
,
3113 unsigned int width
, unsigned int height
,
3114 unsigned int min_width
,
3115 enum atomisp_css_frame_format format
)
3118 * to SOC camera, use yuvpp pipe.
3120 if (ATOMISP_USE_YUVPP(asd
))
3121 __configure_video_preview_output(asd
, ATOMISP_INPUT_STREAM_GENERAL
, width
, height
,
3122 min_width
, format
, IA_CSS_PIPE_ID_YUVPP
);
3124 __configure_output(asd
, ATOMISP_INPUT_STREAM_GENERAL
, width
, height
,
3125 min_width
, format
, IA_CSS_PIPE_ID_VIDEO
);
3129 int atomisp_css_video_configure_viewfinder(
3130 struct atomisp_sub_device
*asd
,
3131 unsigned int width
, unsigned int height
,
3132 unsigned int min_width
,
3133 enum atomisp_css_frame_format format
)
3136 * to SOC camera, video will use yuvpp pipe.
3138 if (ATOMISP_USE_YUVPP(asd
))
3139 __configure_video_vf_output(asd
, width
, height
, min_width
, format
,
3140 IA_CSS_PIPE_ID_YUVPP
);
3142 __configure_vf_output(asd
, width
, height
, min_width
, format
,
3143 IA_CSS_PIPE_ID_VIDEO
);
3147 int atomisp_css_capture_configure_viewfinder(
3148 struct atomisp_sub_device
*asd
,
3149 unsigned int width
, unsigned int height
,
3150 unsigned int min_width
,
3151 enum atomisp_css_frame_format format
)
3153 enum ia_css_pipe_id pipe_id
;
3156 * to SOC camera, video will use yuvpp pipe.
3158 if (ATOMISP_USE_YUVPP(asd
))
3159 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3161 pipe_id
= IA_CSS_PIPE_ID_CAPTURE
;
3163 __configure_vf_output(asd
, width
, height
, min_width
, format
,
3168 int atomisp_css_video_get_viewfinder_frame_info(
3169 struct atomisp_sub_device
*asd
,
3170 struct atomisp_css_frame_info
*info
)
3172 enum ia_css_pipe_id pipe_id
;
3173 enum frame_info_type frame_type
= ATOMISP_CSS_VF_FRAME
;
3175 if (ATOMISP_USE_YUVPP(asd
)) {
3176 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3177 if (asd
->continuous_mode
->val
)
3178 frame_type
= ATOMISP_CSS_SECOND_VF_FRAME
;
3180 pipe_id
= IA_CSS_PIPE_ID_VIDEO
;
3183 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3184 frame_type
, pipe_id
);
3187 int atomisp_css_capture_get_viewfinder_frame_info(
3188 struct atomisp_sub_device
*asd
,
3189 struct atomisp_css_frame_info
*info
)
3191 enum ia_css_pipe_id pipe_id
;
3193 if (ATOMISP_USE_YUVPP(asd
))
3194 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3196 pipe_id
= IA_CSS_PIPE_ID_CAPTURE
;
3198 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3199 ATOMISP_CSS_VF_FRAME
, pipe_id
);
3202 int atomisp_css_capture_get_output_raw_frame_info(
3203 struct atomisp_sub_device
*asd
,
3204 struct atomisp_css_frame_info
*info
)
3206 if (ATOMISP_USE_YUVPP(asd
))
3209 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3210 ATOMISP_CSS_RAW_FRAME
, IA_CSS_PIPE_ID_CAPTURE
);
3213 int atomisp_css_copy_get_output_frame_info(
3214 struct atomisp_sub_device
*asd
,
3215 unsigned int stream_index
,
3216 struct atomisp_css_frame_info
*info
)
3218 return __get_frame_info(asd
, stream_index
, info
,
3219 ATOMISP_CSS_OUTPUT_FRAME
, IA_CSS_PIPE_ID_COPY
);
3222 int atomisp_css_preview_get_output_frame_info(
3223 struct atomisp_sub_device
*asd
,
3224 struct atomisp_css_frame_info
*info
)
3226 enum ia_css_pipe_id pipe_id
;
3227 enum frame_info_type frame_type
= ATOMISP_CSS_OUTPUT_FRAME
;
3229 if (ATOMISP_USE_YUVPP(asd
)) {
3230 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3231 if (asd
->continuous_mode
->val
)
3232 frame_type
= ATOMISP_CSS_SECOND_OUTPUT_FRAME
;
3234 pipe_id
= IA_CSS_PIPE_ID_PREVIEW
;
3237 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3238 frame_type
, pipe_id
);
3241 int atomisp_css_capture_get_output_frame_info(
3242 struct atomisp_sub_device
*asd
,
3243 struct atomisp_css_frame_info
*info
)
3245 enum ia_css_pipe_id pipe_id
;
3247 if (ATOMISP_USE_YUVPP(asd
))
3248 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3250 pipe_id
= IA_CSS_PIPE_ID_CAPTURE
;
3252 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3253 ATOMISP_CSS_OUTPUT_FRAME
, pipe_id
);
3256 int atomisp_css_video_get_output_frame_info(
3257 struct atomisp_sub_device
*asd
,
3258 struct atomisp_css_frame_info
*info
)
3260 enum ia_css_pipe_id pipe_id
;
3261 enum frame_info_type frame_type
= ATOMISP_CSS_OUTPUT_FRAME
;
3263 if (ATOMISP_USE_YUVPP(asd
)) {
3264 pipe_id
= IA_CSS_PIPE_ID_YUVPP
;
3265 if (asd
->continuous_mode
->val
)
3266 frame_type
= ATOMISP_CSS_SECOND_OUTPUT_FRAME
;
3268 pipe_id
= IA_CSS_PIPE_ID_VIDEO
;
3271 return __get_frame_info(asd
, ATOMISP_INPUT_STREAM_GENERAL
, info
,
3272 frame_type
, pipe_id
);
3275 int atomisp_css_preview_configure_pp_input(
3276 struct atomisp_sub_device
*asd
,
3277 unsigned int width
, unsigned int height
)
3279 struct atomisp_stream_env
*stream_env
=
3280 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
3281 __configure_preview_pp_input(asd
, width
, height
,
3282 ATOMISP_USE_YUVPP(asd
) ?
3283 IA_CSS_PIPE_ID_YUVPP
: IA_CSS_PIPE_ID_PREVIEW
);
3285 if (width
> stream_env
->pipe_configs
[IA_CSS_PIPE_ID_CAPTURE
].
3286 capt_pp_in_res
.width
)
3287 __configure_capture_pp_input(asd
, width
, height
,
3288 ATOMISP_USE_YUVPP(asd
) ?
3289 IA_CSS_PIPE_ID_YUVPP
: IA_CSS_PIPE_ID_CAPTURE
);
3293 int atomisp_css_capture_configure_pp_input(
3294 struct atomisp_sub_device
*asd
,
3295 unsigned int width
, unsigned int height
)
3297 __configure_capture_pp_input(asd
, width
, height
,
3298 ATOMISP_USE_YUVPP(asd
) ?
3299 IA_CSS_PIPE_ID_YUVPP
: IA_CSS_PIPE_ID_CAPTURE
);
3303 int atomisp_css_video_configure_pp_input(
3304 struct atomisp_sub_device
*asd
,
3305 unsigned int width
, unsigned int height
)
3307 struct atomisp_stream_env
*stream_env
=
3308 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
3310 __configure_video_pp_input(asd
, width
, height
,
3311 ATOMISP_USE_YUVPP(asd
) ?
3312 IA_CSS_PIPE_ID_YUVPP
: IA_CSS_PIPE_ID_VIDEO
);
3314 if (width
> stream_env
->pipe_configs
[IA_CSS_PIPE_ID_CAPTURE
].
3315 capt_pp_in_res
.width
)
3316 __configure_capture_pp_input(asd
, width
, height
,
3317 ATOMISP_USE_YUVPP(asd
) ?
3318 IA_CSS_PIPE_ID_YUVPP
: IA_CSS_PIPE_ID_CAPTURE
);
3322 int atomisp_css_offline_capture_configure(struct atomisp_sub_device
*asd
,
3323 int num_captures
, unsigned int skip
, int offset
)
3325 enum ia_css_err ret
;
3328 dev_dbg(asd
->isp
->dev
, "%s num_capture:%d skip:%d offset:%d\n",
3329 __func__
, num_captures
, skip
, offset
);
3331 ret
= ia_css_stream_capture(
3332 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3333 num_captures
, skip
, offset
);
3334 if (ret
!= IA_CSS_SUCCESS
)
3340 int atomisp_css_exp_id_capture(struct atomisp_sub_device
*asd
, int exp_id
)
3342 enum ia_css_err ret
;
3344 ret
= ia_css_stream_capture_frame(
3345 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3347 if (ret
== IA_CSS_ERR_QUEUE_IS_FULL
) {
3348 /* capture cmd queue is full */
3350 } else if (ret
!= IA_CSS_SUCCESS
) {
3357 int atomisp_css_exp_id_unlock(struct atomisp_sub_device
*asd
, int exp_id
)
3359 enum ia_css_err ret
;
3361 ret
= ia_css_unlock_raw_frame(
3362 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3364 if (ret
== IA_CSS_ERR_QUEUE_IS_FULL
)
3366 else if (ret
!= IA_CSS_SUCCESS
)
3372 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device
*asd
,
3375 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
3376 .pipe_configs
[IA_CSS_PIPE_ID_CAPTURE
]
3377 .default_capture_config
.enable_xnr
= enable
;
3378 asd
->params
.capture_config
.enable_xnr
= enable
;
3379 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
3380 .update_pipe
[IA_CSS_PIPE_ID_CAPTURE
] = true;
3385 void atomisp_css_send_input_frame(struct atomisp_sub_device
*asd
,
3386 unsigned short *data
, unsigned int width
,
3387 unsigned int height
)
3389 ia_css_stream_send_input_frame(
3390 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3391 data
, width
, height
);
3394 bool atomisp_css_isp_has_started(void)
3396 return ia_css_isp_has_started();
3399 void atomisp_css_request_flash(struct atomisp_sub_device
*asd
)
3401 ia_css_stream_request_flash(
3402 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
);
3405 void atomisp_css_set_wb_config(struct atomisp_sub_device
*asd
,
3406 struct atomisp_css_wb_config
*wb_config
)
3408 asd
->params
.config
.wb_config
= wb_config
;
3411 void atomisp_css_set_ob_config(struct atomisp_sub_device
*asd
,
3412 struct atomisp_css_ob_config
*ob_config
)
3414 asd
->params
.config
.ob_config
= ob_config
;
3417 void atomisp_css_set_dp_config(struct atomisp_sub_device
*asd
,
3418 struct atomisp_css_dp_config
*dp_config
)
3420 asd
->params
.config
.dp_config
= dp_config
;
3423 void atomisp_css_set_de_config(struct atomisp_sub_device
*asd
,
3424 struct atomisp_css_de_config
*de_config
)
3426 asd
->params
.config
.de_config
= de_config
;
3429 void atomisp_css_set_dz_config(struct atomisp_sub_device
*asd
,
3430 struct atomisp_css_dz_config
*dz_config
)
3432 asd
->params
.config
.dz_config
= dz_config
;
3435 void atomisp_css_set_default_de_config(struct atomisp_sub_device
*asd
)
3437 asd
->params
.config
.de_config
= NULL
;
3440 void atomisp_css_set_ce_config(struct atomisp_sub_device
*asd
,
3441 struct atomisp_css_ce_config
*ce_config
)
3443 asd
->params
.config
.ce_config
= ce_config
;
3446 void atomisp_css_set_nr_config(struct atomisp_sub_device
*asd
,
3447 struct atomisp_css_nr_config
*nr_config
)
3449 asd
->params
.config
.nr_config
= nr_config
;
3452 void atomisp_css_set_ee_config(struct atomisp_sub_device
*asd
,
3453 struct atomisp_css_ee_config
*ee_config
)
3455 asd
->params
.config
.ee_config
= ee_config
;
3458 void atomisp_css_set_tnr_config(struct atomisp_sub_device
*asd
,
3459 struct atomisp_css_tnr_config
*tnr_config
)
3461 asd
->params
.config
.tnr_config
= tnr_config
;
3464 void atomisp_css_set_cc_config(struct atomisp_sub_device
*asd
,
3465 struct atomisp_css_cc_config
*cc_config
)
3467 asd
->params
.config
.cc_config
= cc_config
;
3470 void atomisp_css_set_macc_table(struct atomisp_sub_device
*asd
,
3471 struct atomisp_css_macc_table
*macc_table
)
3473 asd
->params
.config
.macc_table
= macc_table
;
3476 void atomisp_css_set_macc_config(struct atomisp_sub_device
*asd
,
3477 struct atomisp_css_macc_config
*macc_config
)
3479 asd
->params
.config
.macc_config
= macc_config
;
3482 void atomisp_css_set_ecd_config(struct atomisp_sub_device
*asd
,
3483 struct atomisp_css_ecd_config
*ecd_config
)
3485 asd
->params
.config
.ecd_config
= ecd_config
;
3488 void atomisp_css_set_ynr_config(struct atomisp_sub_device
*asd
,
3489 struct atomisp_css_ynr_config
*ynr_config
)
3491 asd
->params
.config
.ynr_config
= ynr_config
;
3494 void atomisp_css_set_fc_config(struct atomisp_sub_device
*asd
,
3495 struct atomisp_css_fc_config
*fc_config
)
3497 asd
->params
.config
.fc_config
= fc_config
;
3500 void atomisp_css_set_ctc_config(struct atomisp_sub_device
*asd
,
3501 struct atomisp_css_ctc_config
*ctc_config
)
3503 asd
->params
.config
.ctc_config
= ctc_config
;
3506 void atomisp_css_set_cnr_config(struct atomisp_sub_device
*asd
,
3507 struct atomisp_css_cnr_config
*cnr_config
)
3509 asd
->params
.config
.cnr_config
= cnr_config
;
3512 void atomisp_css_set_aa_config(struct atomisp_sub_device
*asd
,
3513 struct atomisp_css_aa_config
*aa_config
)
3515 asd
->params
.config
.aa_config
= aa_config
;
3518 void atomisp_css_set_baa_config(struct atomisp_sub_device
*asd
,
3519 struct atomisp_css_baa_config
*baa_config
)
3521 asd
->params
.config
.baa_config
= baa_config
;
3524 void atomisp_css_set_anr_config(struct atomisp_sub_device
*asd
,
3525 struct atomisp_css_anr_config
*anr_config
)
3527 asd
->params
.config
.anr_config
= anr_config
;
3530 void atomisp_css_set_xnr_config(struct atomisp_sub_device
*asd
,
3531 struct atomisp_css_xnr_config
*xnr_config
)
3533 asd
->params
.config
.xnr_config
= xnr_config
;
3536 void atomisp_css_set_yuv2rgb_cc_config(struct atomisp_sub_device
*asd
,
3537 struct atomisp_css_cc_config
*yuv2rgb_cc_config
)
3539 asd
->params
.config
.yuv2rgb_cc_config
= yuv2rgb_cc_config
;
3542 void atomisp_css_set_rgb2yuv_cc_config(struct atomisp_sub_device
*asd
,
3543 struct atomisp_css_cc_config
*rgb2yuv_cc_config
)
3545 asd
->params
.config
.rgb2yuv_cc_config
= rgb2yuv_cc_config
;
3548 void atomisp_css_set_xnr_table(struct atomisp_sub_device
*asd
,
3549 struct atomisp_css_xnr_table
*xnr_table
)
3551 asd
->params
.config
.xnr_table
= xnr_table
;
3554 void atomisp_css_set_r_gamma_table(struct atomisp_sub_device
*asd
,
3555 struct atomisp_css_rgb_gamma_table
*r_gamma_table
)
3557 asd
->params
.config
.r_gamma_table
= r_gamma_table
;
3560 void atomisp_css_set_g_gamma_table(struct atomisp_sub_device
*asd
,
3561 struct atomisp_css_rgb_gamma_table
*g_gamma_table
)
3563 asd
->params
.config
.g_gamma_table
= g_gamma_table
;
3566 void atomisp_css_set_b_gamma_table(struct atomisp_sub_device
*asd
,
3567 struct atomisp_css_rgb_gamma_table
*b_gamma_table
)
3569 asd
->params
.config
.b_gamma_table
= b_gamma_table
;
3572 void atomisp_css_set_gamma_table(struct atomisp_sub_device
*asd
,
3573 struct atomisp_css_gamma_table
*gamma_table
)
3575 asd
->params
.config
.gamma_table
= gamma_table
;
3578 void atomisp_css_set_ctc_table(struct atomisp_sub_device
*asd
,
3579 struct atomisp_css_ctc_table
*ctc_table
)
3582 uint16_t *vamem_ptr
= ctc_table
->data
.vamem_1
;
3583 int data_size
= IA_CSS_VAMEM_1_CTC_TABLE_SIZE
;
3586 /* workaround: if ctc_table is all 0, do not apply it */
3587 if (ctc_table
->vamem_type
== IA_CSS_VAMEM_TYPE_2
) {
3588 vamem_ptr
= ctc_table
->data
.vamem_2
;
3589 data_size
= IA_CSS_VAMEM_2_CTC_TABLE_SIZE
;
3592 for (i
= 0; i
< data_size
; i
++) {
3593 if (*(vamem_ptr
+ i
)) {
3600 asd
->params
.config
.ctc_table
= ctc_table
;
3602 dev_warn(asd
->isp
->dev
, "Bypass the invalid ctc_table.\n");
3605 void atomisp_css_set_anr_thres(struct atomisp_sub_device
*asd
,
3606 struct atomisp_css_anr_thres
*anr_thres
)
3608 asd
->params
.config
.anr_thres
= anr_thres
;
3611 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device
*asd
,
3612 struct atomisp_css_dvs_6axis
*dvs_6axis
)
3614 asd
->params
.config
.dvs_6axis_config
= dvs_6axis
;
3617 void atomisp_css_set_gc_config(struct atomisp_sub_device
*asd
,
3618 struct atomisp_css_gc_config
*gc_config
)
3620 asd
->params
.config
.gc_config
= gc_config
;
3623 void atomisp_css_set_3a_config(struct atomisp_sub_device
*asd
,
3624 struct atomisp_css_3a_config
*s3a_config
)
3626 asd
->params
.config
.s3a_config
= s3a_config
;
3629 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device
*asd
,
3630 struct atomisp_dis_vector
*vector
)
3632 if (!asd
->params
.config
.motion_vector
)
3633 asd
->params
.config
.motion_vector
= &asd
->params
.css_param
.motion_vector
;
3635 memset(asd
->params
.config
.motion_vector
,
3636 0, sizeof(struct ia_css_vector
));
3637 asd
->params
.css_param
.motion_vector
.x
= vector
->x
;
3638 asd
->params
.css_param
.motion_vector
.y
= vector
->y
;
3641 static int atomisp_compare_dvs_grid(struct atomisp_sub_device
*asd
,
3642 struct atomisp_dvs_grid_info
*atomgrid
)
3644 struct atomisp_css_dvs_grid_info
*cur
=
3645 atomisp_css_get_dvs_grid_info(&asd
->params
.curr_grid_info
);
3648 dev_err(asd
->isp
->dev
, "dvs grid not available!\n");
3652 if (sizeof(*cur
) != sizeof(*atomgrid
)) {
3653 dev_err(asd
->isp
->dev
, "dvs grid mis-match!\n");
3658 dev_err(asd
->isp
->dev
, "dvs not enabled!\n");
3662 return memcmp(atomgrid
, cur
, sizeof(*cur
));
3665 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device
*asd
,
3666 struct ia_css_dvs2_coefficients
*coefs
)
3668 asd
->params
.config
.dvs2_coefs
= coefs
;
3671 int atomisp_css_set_dis_coefs(struct atomisp_sub_device
*asd
,
3672 struct atomisp_dis_coefficients
*coefs
)
3674 if (atomisp_compare_dvs_grid(asd
, &coefs
->grid_info
) != 0)
3675 /* If the grid info in the argument differs from the current
3676 grid info, we tell the caller to reset the grid size and
3680 if (coefs
->hor_coefs
.odd_real
== NULL
||
3681 coefs
->hor_coefs
.odd_imag
== NULL
||
3682 coefs
->hor_coefs
.even_real
== NULL
||
3683 coefs
->hor_coefs
.even_imag
== NULL
||
3684 coefs
->ver_coefs
.odd_real
== NULL
||
3685 coefs
->ver_coefs
.odd_imag
== NULL
||
3686 coefs
->ver_coefs
.even_real
== NULL
||
3687 coefs
->ver_coefs
.even_imag
== NULL
||
3688 asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.odd_real
== NULL
||
3689 asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.odd_imag
== NULL
||
3690 asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.even_real
== NULL
||
3691 asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.even_imag
== NULL
||
3692 asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.odd_real
== NULL
||
3693 asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.odd_imag
== NULL
||
3694 asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.even_real
== NULL
||
3695 asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.even_imag
== NULL
)
3698 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.odd_real
,
3699 coefs
->hor_coefs
.odd_real
, asd
->params
.dvs_hor_coef_bytes
))
3701 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.odd_imag
,
3702 coefs
->hor_coefs
.odd_imag
, asd
->params
.dvs_hor_coef_bytes
))
3704 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.even_real
,
3705 coefs
->hor_coefs
.even_real
, asd
->params
.dvs_hor_coef_bytes
))
3707 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->hor_coefs
.even_imag
,
3708 coefs
->hor_coefs
.even_imag
, asd
->params
.dvs_hor_coef_bytes
))
3711 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.odd_real
,
3712 coefs
->ver_coefs
.odd_real
, asd
->params
.dvs_ver_coef_bytes
))
3714 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.odd_imag
,
3715 coefs
->ver_coefs
.odd_imag
, asd
->params
.dvs_ver_coef_bytes
))
3717 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.even_real
,
3718 coefs
->ver_coefs
.even_real
, asd
->params
.dvs_ver_coef_bytes
))
3720 if (copy_from_user(asd
->params
.css_param
.dvs2_coeff
->ver_coefs
.even_imag
,
3721 coefs
->ver_coefs
.even_imag
, asd
->params
.dvs_ver_coef_bytes
))
3724 asd
->params
.css_param
.update_flag
.dvs2_coefs
=
3725 (struct atomisp_dvs2_coefficients
*)
3726 asd
->params
.css_param
.dvs2_coeff
;
3728 /* asd->params.dis_proj_data_valid = false; */
3729 asd
->params
.css_update_params_needed
= true;
3734 void atomisp_css_set_zoom_factor(struct atomisp_sub_device
*asd
,
3737 struct atomisp_device
*isp
= asd
->isp
;
3739 if (zoom
== asd
->params
.css_param
.dz_config
.dx
&&
3740 zoom
== asd
->params
.css_param
.dz_config
.dy
) {
3741 dev_dbg(isp
->dev
, "same zoom scale. skipped.\n");
3745 memset(&asd
->params
.css_param
.dz_config
, 0,
3746 sizeof(struct ia_css_dz_config
));
3747 asd
->params
.css_param
.dz_config
.dx
= zoom
;
3748 asd
->params
.css_param
.dz_config
.dy
= zoom
;
3750 asd
->params
.css_param
.update_flag
.dz_config
=
3751 (struct atomisp_dz_config
*) &asd
->params
.css_param
.dz_config
;
3752 asd
->params
.css_update_params_needed
= true;
3755 void atomisp_css_set_formats_config(struct atomisp_sub_device
*asd
,
3756 struct atomisp_css_formats_config
*formats_config
)
3758 asd
->params
.config
.formats_config
= formats_config
;
3761 int atomisp_css_get_wb_config(struct atomisp_sub_device
*asd
,
3762 struct atomisp_wb_config
*config
)
3764 struct atomisp_css_wb_config wb_config
;
3765 struct ia_css_isp_config isp_config
;
3766 struct atomisp_device
*isp
= asd
->isp
;
3768 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3769 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3773 memset(&wb_config
, 0, sizeof(struct atomisp_css_wb_config
));
3774 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3775 isp_config
.wb_config
= &wb_config
;
3776 ia_css_stream_get_isp_config(
3777 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3779 memcpy(config
, &wb_config
, sizeof(*config
));
3784 int atomisp_css_get_ob_config(struct atomisp_sub_device
*asd
,
3785 struct atomisp_ob_config
*config
)
3787 struct atomisp_css_ob_config ob_config
;
3788 struct ia_css_isp_config isp_config
;
3789 struct atomisp_device
*isp
= asd
->isp
;
3791 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3792 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3796 memset(&ob_config
, 0, sizeof(struct atomisp_css_ob_config
));
3797 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3798 isp_config
.ob_config
= &ob_config
;
3799 ia_css_stream_get_isp_config(
3800 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3802 memcpy(config
, &ob_config
, sizeof(*config
));
3807 int atomisp_css_get_dp_config(struct atomisp_sub_device
*asd
,
3808 struct atomisp_dp_config
*config
)
3810 struct atomisp_css_dp_config dp_config
;
3811 struct ia_css_isp_config isp_config
;
3812 struct atomisp_device
*isp
= asd
->isp
;
3814 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3815 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3819 memset(&dp_config
, 0, sizeof(struct atomisp_css_dp_config
));
3820 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3821 isp_config
.dp_config
= &dp_config
;
3822 ia_css_stream_get_isp_config(
3823 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3825 memcpy(config
, &dp_config
, sizeof(*config
));
3830 int atomisp_css_get_de_config(struct atomisp_sub_device
*asd
,
3831 struct atomisp_de_config
*config
)
3833 struct atomisp_css_de_config de_config
;
3834 struct ia_css_isp_config isp_config
;
3835 struct atomisp_device
*isp
= asd
->isp
;
3837 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3838 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3842 memset(&de_config
, 0, sizeof(struct atomisp_css_de_config
));
3843 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3844 isp_config
.de_config
= &de_config
;
3845 ia_css_stream_get_isp_config(
3846 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3848 memcpy(config
, &de_config
, sizeof(*config
));
3853 int atomisp_css_get_nr_config(struct atomisp_sub_device
*asd
,
3854 struct atomisp_nr_config
*config
)
3856 struct atomisp_css_nr_config nr_config
;
3857 struct ia_css_isp_config isp_config
;
3858 struct atomisp_device
*isp
= asd
->isp
;
3860 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3861 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3865 memset(&nr_config
, 0, sizeof(struct atomisp_css_nr_config
));
3866 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3868 isp_config
.nr_config
= &nr_config
;
3869 ia_css_stream_get_isp_config(
3870 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3872 memcpy(config
, &nr_config
, sizeof(*config
));
3877 int atomisp_css_get_ee_config(struct atomisp_sub_device
*asd
,
3878 struct atomisp_ee_config
*config
)
3880 struct atomisp_css_ee_config ee_config
;
3881 struct ia_css_isp_config isp_config
;
3882 struct atomisp_device
*isp
= asd
->isp
;
3884 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3885 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3889 memset(&ee_config
, 0, sizeof(struct atomisp_css_ee_config
));
3890 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3891 isp_config
.ee_config
= &ee_config
;
3892 ia_css_stream_get_isp_config(
3893 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3895 memcpy(config
, &ee_config
, sizeof(*config
));
3900 int atomisp_css_get_tnr_config(struct atomisp_sub_device
*asd
,
3901 struct atomisp_tnr_config
*config
)
3903 struct atomisp_css_tnr_config tnr_config
;
3904 struct ia_css_isp_config isp_config
;
3905 struct atomisp_device
*isp
= asd
->isp
;
3907 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3908 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3912 memset(&tnr_config
, 0, sizeof(struct atomisp_css_tnr_config
));
3913 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3914 isp_config
.tnr_config
= &tnr_config
;
3915 ia_css_stream_get_isp_config(
3916 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3918 memcpy(config
, &tnr_config
, sizeof(*config
));
3923 int atomisp_css_get_ctc_table(struct atomisp_sub_device
*asd
,
3924 struct atomisp_ctc_table
*config
)
3926 struct atomisp_css_ctc_table
*tab
;
3927 struct ia_css_isp_config isp_config
;
3928 struct atomisp_device
*isp
= asd
->isp
;
3930 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3931 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3936 tab
= vzalloc(sizeof(struct atomisp_css_ctc_table
));
3940 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3941 isp_config
.ctc_table
= tab
;
3942 ia_css_stream_get_isp_config(
3943 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3945 memcpy(config
, tab
, sizeof(*tab
));
3951 int atomisp_css_get_gamma_table(struct atomisp_sub_device
*asd
,
3952 struct atomisp_gamma_table
*config
)
3954 struct atomisp_css_gamma_table
*tab
;
3955 struct ia_css_isp_config isp_config
;
3956 struct atomisp_device
*isp
= asd
->isp
;
3958 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3959 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3964 tab
= vzalloc(sizeof(struct atomisp_css_gamma_table
));
3968 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3969 isp_config
.gamma_table
= tab
;
3970 ia_css_stream_get_isp_config(
3971 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3973 memcpy(config
, tab
, sizeof(*tab
));
3979 int atomisp_css_get_gc_config(struct atomisp_sub_device
*asd
,
3980 struct atomisp_gc_config
*config
)
3982 struct atomisp_css_gc_config gc_config
;
3983 struct ia_css_isp_config isp_config
;
3984 struct atomisp_device
*isp
= asd
->isp
;
3986 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
3987 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
3991 memset(&gc_config
, 0, sizeof(struct atomisp_css_gc_config
));
3992 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
3993 isp_config
.gc_config
= &gc_config
;
3994 ia_css_stream_get_isp_config(
3995 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
3997 /* Get gamma correction params from current setup */
3998 memcpy(config
, &gc_config
, sizeof(*config
));
4003 int atomisp_css_get_3a_config(struct atomisp_sub_device
*asd
,
4004 struct atomisp_3a_config
*config
)
4006 struct atomisp_css_3a_config s3a_config
;
4007 struct ia_css_isp_config isp_config
;
4008 struct atomisp_device
*isp
= asd
->isp
;
4010 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
4011 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
4015 memset(&s3a_config
, 0, sizeof(struct atomisp_css_3a_config
));
4016 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
4017 isp_config
.s3a_config
= &s3a_config
;
4018 ia_css_stream_get_isp_config(
4019 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
4021 /* Get white balance from current setup */
4022 memcpy(config
, &s3a_config
, sizeof(*config
));
4027 int atomisp_css_get_formats_config(struct atomisp_sub_device
*asd
,
4028 struct atomisp_formats_config
*config
)
4030 struct atomisp_css_formats_config formats_config
;
4031 struct ia_css_isp_config isp_config
;
4032 struct atomisp_device
*isp
= asd
->isp
;
4034 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
4035 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
4039 memset(&formats_config
, 0, sizeof(formats_config
));
4040 memset(&isp_config
, 0, sizeof(isp_config
));
4041 isp_config
.formats_config
= &formats_config
;
4042 ia_css_stream_get_isp_config(
4043 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
4045 /* Get narrow gamma from current setup */
4046 memcpy(config
, &formats_config
, sizeof(*config
));
4051 int atomisp_css_get_zoom_factor(struct atomisp_sub_device
*asd
,
4054 struct ia_css_dz_config dz_config
; /**< Digital Zoom */
4055 struct ia_css_isp_config isp_config
;
4056 struct atomisp_device
*isp
= asd
->isp
;
4058 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
4059 dev_err(isp
->dev
, "%s called after streamoff, skipping.\n",
4063 memset(&dz_config
, 0, sizeof(struct ia_css_dz_config
));
4064 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
4065 isp_config
.dz_config
= &dz_config
;
4066 ia_css_stream_get_isp_config(
4067 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
4069 *zoom
= dz_config
.dx
;
4076 * Function to set/get image stablization statistics
4078 int atomisp_css_get_dis_stat(struct atomisp_sub_device
*asd
,
4079 struct atomisp_dis_statistics
*stats
)
4081 struct atomisp_device
*isp
= asd
->isp
;
4082 struct atomisp_dis_buf
*dis_buf
;
4083 unsigned long flags
;
4085 if (asd
->params
.dvs_stat
->hor_prod
.odd_real
== NULL
||
4086 asd
->params
.dvs_stat
->hor_prod
.odd_imag
== NULL
||
4087 asd
->params
.dvs_stat
->hor_prod
.even_real
== NULL
||
4088 asd
->params
.dvs_stat
->hor_prod
.even_imag
== NULL
||
4089 asd
->params
.dvs_stat
->ver_prod
.odd_real
== NULL
||
4090 asd
->params
.dvs_stat
->ver_prod
.odd_imag
== NULL
||
4091 asd
->params
.dvs_stat
->ver_prod
.even_real
== NULL
||
4092 asd
->params
.dvs_stat
->ver_prod
.even_imag
== NULL
)
4095 /* isp needs to be streaming to get DIS statistics */
4096 spin_lock_irqsave(&isp
->lock
, flags
);
4097 if (asd
->streaming
!= ATOMISP_DEVICE_STREAMING_ENABLED
) {
4098 spin_unlock_irqrestore(&isp
->lock
, flags
);
4101 spin_unlock_irqrestore(&isp
->lock
, flags
);
4103 if (atomisp_compare_dvs_grid(asd
, &stats
->dvs2_stat
.grid_info
) != 0)
4104 /* If the grid info in the argument differs from the current
4105 grid info, we tell the caller to reset the grid size and
4109 spin_lock_irqsave(&asd
->dis_stats_lock
, flags
);
4110 if (!asd
->params
.dis_proj_data_valid
|| list_empty(&asd
->dis_stats
)) {
4111 spin_unlock_irqrestore(&asd
->dis_stats_lock
, flags
);
4112 dev_err(isp
->dev
, "dis statistics is not valid.\n");
4116 dis_buf
= list_entry(asd
->dis_stats
.next
,
4117 struct atomisp_dis_buf
, list
);
4118 list_del_init(&dis_buf
->list
);
4119 spin_unlock_irqrestore(&asd
->dis_stats_lock
, flags
);
4121 if (dis_buf
->dvs_map
)
4122 ia_css_translate_dvs2_statistics(
4123 asd
->params
.dvs_stat
, dis_buf
->dvs_map
);
4125 ia_css_get_dvs2_statistics(asd
->params
.dvs_stat
,
4127 stats
->exp_id
= dis_buf
->dis_data
->exp_id
;
4129 spin_lock_irqsave(&asd
->dis_stats_lock
, flags
);
4130 list_add_tail(&dis_buf
->list
, &asd
->dis_stats
);
4131 spin_unlock_irqrestore(&asd
->dis_stats_lock
, flags
);
4133 if (copy_to_user(stats
->dvs2_stat
.ver_prod
.odd_real
,
4134 asd
->params
.dvs_stat
->ver_prod
.odd_real
,
4135 asd
->params
.dvs_ver_proj_bytes
))
4137 if (copy_to_user(stats
->dvs2_stat
.ver_prod
.odd_imag
,
4138 asd
->params
.dvs_stat
->ver_prod
.odd_imag
,
4139 asd
->params
.dvs_ver_proj_bytes
))
4141 if (copy_to_user(stats
->dvs2_stat
.ver_prod
.even_real
,
4142 asd
->params
.dvs_stat
->ver_prod
.even_real
,
4143 asd
->params
.dvs_ver_proj_bytes
))
4145 if (copy_to_user(stats
->dvs2_stat
.ver_prod
.even_imag
,
4146 asd
->params
.dvs_stat
->ver_prod
.even_imag
,
4147 asd
->params
.dvs_ver_proj_bytes
))
4149 if (copy_to_user(stats
->dvs2_stat
.hor_prod
.odd_real
,
4150 asd
->params
.dvs_stat
->hor_prod
.odd_real
,
4151 asd
->params
.dvs_hor_proj_bytes
))
4153 if (copy_to_user(stats
->dvs2_stat
.hor_prod
.odd_imag
,
4154 asd
->params
.dvs_stat
->hor_prod
.odd_imag
,
4155 asd
->params
.dvs_hor_proj_bytes
))
4157 if (copy_to_user(stats
->dvs2_stat
.hor_prod
.even_real
,
4158 asd
->params
.dvs_stat
->hor_prod
.even_real
,
4159 asd
->params
.dvs_hor_proj_bytes
))
4161 if (copy_to_user(stats
->dvs2_stat
.hor_prod
.even_imag
,
4162 asd
->params
.dvs_stat
->hor_prod
.even_imag
,
4163 asd
->params
.dvs_hor_proj_bytes
))
4169 struct atomisp_css_shading_table
*atomisp_css_shading_table_alloc(
4170 unsigned int width
, unsigned int height
)
4172 return ia_css_shading_table_alloc(width
, height
);
4175 void atomisp_css_set_shading_table(struct atomisp_sub_device
*asd
,
4176 struct atomisp_css_shading_table
*table
)
4178 asd
->params
.config
.shading_table
= table
;
4181 void atomisp_css_shading_table_free(struct atomisp_css_shading_table
*table
)
4183 ia_css_shading_table_free(table
);
4186 struct atomisp_css_morph_table
*atomisp_css_morph_table_allocate(
4187 unsigned int width
, unsigned int height
)
4189 return ia_css_morph_table_allocate(width
, height
);
4192 void atomisp_css_set_morph_table(struct atomisp_sub_device
*asd
,
4193 struct atomisp_css_morph_table
*table
)
4195 asd
->params
.config
.morph_table
= table
;
4198 void atomisp_css_get_morph_table(struct atomisp_sub_device
*asd
,
4199 struct atomisp_css_morph_table
*table
)
4201 struct ia_css_isp_config isp_config
;
4202 struct atomisp_device
*isp
= asd
->isp
;
4204 if (!asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
) {
4206 "%s called after streamoff, skipping.\n", __func__
);
4209 memset(table
, 0, sizeof(struct atomisp_css_morph_table
));
4210 memset(&isp_config
, 0, sizeof(struct ia_css_isp_config
));
4211 isp_config
.morph_table
= table
;
4212 ia_css_stream_get_isp_config(
4213 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
4217 void atomisp_css_morph_table_free(struct atomisp_css_morph_table
*table
)
4219 ia_css_morph_table_free(table
);
4222 void atomisp_css_set_cont_prev_start_time(struct atomisp_device
*isp
,
4223 unsigned int overlap
)
4225 /* CSS 2.0 doesn't support this API. */
4226 dev_dbg(isp
->dev
, "set cont prev start time is not supported.\n");
4230 void atomisp_css_acc_done(struct atomisp_sub_device
*asd
)
4232 complete(&asd
->acc
.acc_done
);
4235 int atomisp_css_wait_acc_finish(struct atomisp_sub_device
*asd
)
4238 struct atomisp_device
*isp
= asd
->isp
;
4240 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
4241 rt_mutex_unlock(&isp
->mutex
);
4242 if (wait_for_completion_interruptible_timeout(&asd
->acc
.acc_done
,
4243 ATOMISP_ISP_TIMEOUT_DURATION
) == 0) {
4244 dev_err(isp
->dev
, "<%s: completion timeout\n", __func__
);
4245 atomisp_css_debug_dump_sp_sw_debug_info();
4246 atomisp_css_debug_dump_debug_info(__func__
);
4249 rt_mutex_lock(&isp
->mutex
);
4254 /* Set the ACC binary arguments */
4255 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw
*acc_fw
)
4259 for (mem
= 0; mem
< ATOMISP_ACC_NR_MEMORY
; mem
++) {
4260 if (acc_fw
->args
[mem
].length
== 0)
4263 ia_css_isp_param_set_css_mem_init(&acc_fw
->fw
->mem_initializers
,
4264 IA_CSS_PARAM_CLASS_PARAM
, mem
,
4265 acc_fw
->args
[mem
].css_ptr
,
4266 acc_fw
->args
[mem
].length
);
4272 /* Load acc binary extension */
4273 int atomisp_css_load_acc_extension(struct atomisp_sub_device
*asd
,
4274 struct atomisp_css_fw_info
*fw
,
4275 enum atomisp_css_pipe_id pipe_id
,
4278 struct atomisp_css_fw_info
**hd
;
4281 hd
= &(asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
4282 .pipe_configs
[pipe_id
].acc_extension
);
4287 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
4288 .update_pipe
[pipe_id
] = true;
4292 /* Unload acc binary extension */
4293 void atomisp_css_unload_acc_extension(struct atomisp_sub_device
*asd
,
4294 struct atomisp_css_fw_info
*fw
,
4295 enum atomisp_css_pipe_id pipe_id
)
4297 struct atomisp_css_fw_info
**hd
;
4299 hd
= &(asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
4300 .pipe_configs
[pipe_id
].acc_extension
);
4301 while (*hd
&& *hd
!= fw
)
4304 dev_err(asd
->isp
->dev
, "did not find acc fw for removal\n");
4310 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
4311 .update_pipe
[pipe_id
] = true;
4314 int atomisp_css_create_acc_pipe(struct atomisp_sub_device
*asd
)
4316 struct atomisp_device
*isp
= asd
->isp
;
4317 struct ia_css_pipe_config
*pipe_config
;
4318 struct atomisp_stream_env
*stream_env
=
4319 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
4321 if (stream_env
->acc_stream
) {
4322 if (stream_env
->acc_stream_state
== CSS_STREAM_STARTED
) {
4323 if (ia_css_stream_stop(stream_env
->acc_stream
)
4324 != IA_CSS_SUCCESS
) {
4325 dev_err(isp
->dev
, "stop acc_stream failed.\n");
4330 if (ia_css_stream_destroy(stream_env
->acc_stream
)
4331 != IA_CSS_SUCCESS
) {
4332 dev_err(isp
->dev
, "destroy acc_stream failed.\n");
4335 stream_env
->acc_stream
= NULL
;
4338 pipe_config
= &stream_env
->pipe_configs
[CSS_PIPE_ID_ACC
];
4339 ia_css_pipe_config_defaults(pipe_config
);
4340 asd
->acc
.acc_stages
= kzalloc(MAX_ACC_STAGES
*
4341 sizeof(void *), GFP_KERNEL
);
4342 if (!asd
->acc
.acc_stages
)
4344 pipe_config
->acc_stages
= asd
->acc
.acc_stages
;
4345 pipe_config
->mode
= IA_CSS_PIPE_MODE_ACC
;
4346 pipe_config
->num_acc_stages
= 0;
4349 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
4350 * because pipe configuration will soon be changed by
4351 * atomisp_css_load_acc_binary()
4356 int atomisp_css_start_acc_pipe(struct atomisp_sub_device
*asd
)
4358 struct atomisp_device
*isp
= asd
->isp
;
4359 struct atomisp_stream_env
*stream_env
=
4360 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
4361 struct ia_css_pipe_config
*pipe_config
=
4362 &stream_env
->pipe_configs
[IA_CSS_PIPE_ID_ACC
];
4364 if (ia_css_pipe_create(pipe_config
,
4365 &stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
]) != IA_CSS_SUCCESS
) {
4366 dev_err(isp
->dev
, "%s: ia_css_pipe_create failed\n",
4371 memset(&stream_env
->acc_stream_config
, 0,
4372 sizeof(struct ia_css_stream_config
));
4373 if (ia_css_stream_create(&stream_env
->acc_stream_config
, 1,
4374 &stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
],
4375 &stream_env
->acc_stream
) != IA_CSS_SUCCESS
) {
4376 dev_err(isp
->dev
, "%s: create acc_stream error.\n", __func__
);
4379 stream_env
->acc_stream_state
= CSS_STREAM_CREATED
;
4381 init_completion(&asd
->acc
.acc_done
);
4382 asd
->acc
.pipeline
= stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
];
4384 atomisp_freq_scaling(isp
, ATOMISP_DFS_MODE_MAX
, false);
4386 if (ia_css_start_sp() != IA_CSS_SUCCESS
) {
4387 dev_err(isp
->dev
, "start sp error.\n");
4391 if (ia_css_stream_start(stream_env
->acc_stream
)
4392 != IA_CSS_SUCCESS
) {
4393 dev_err(isp
->dev
, "acc_stream start error.\n");
4397 stream_env
->acc_stream_state
= CSS_STREAM_STARTED
;
4401 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device
*asd
)
4403 struct atomisp_stream_env
*stream_env
=
4404 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
4405 if (stream_env
->acc_stream_state
== CSS_STREAM_STARTED
) {
4406 ia_css_stream_stop(stream_env
->acc_stream
);
4407 stream_env
->acc_stream_state
= CSS_STREAM_STOPPED
;
4412 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device
*asd
)
4414 struct atomisp_stream_env
*stream_env
=
4415 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
];
4416 if (stream_env
->acc_stream
) {
4417 if (ia_css_stream_destroy(stream_env
->acc_stream
)
4419 dev_warn(asd
->isp
->dev
,
4420 "destroy acc_stream failed.\n");
4421 stream_env
->acc_stream
= NULL
;
4424 if (stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
]) {
4425 if (ia_css_pipe_destroy(stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
])
4427 dev_warn(asd
->isp
->dev
,
4428 "destroy ACC pipe failed.\n");
4429 stream_env
->pipes
[IA_CSS_PIPE_ID_ACC
] = NULL
;
4430 stream_env
->update_pipe
[IA_CSS_PIPE_ID_ACC
] = false;
4431 ia_css_pipe_config_defaults(
4432 &stream_env
->pipe_configs
[IA_CSS_PIPE_ID_ACC
]);
4433 ia_css_pipe_extra_config_defaults(
4434 &stream_env
->pipe_extra_configs
[IA_CSS_PIPE_ID_ACC
]);
4436 asd
->acc
.pipeline
= NULL
;
4438 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4443 kfree(asd
->acc
.acc_stages
);
4444 asd
->acc
.acc_stages
= NULL
;
4446 atomisp_freq_scaling(asd
->isp
, ATOMISP_DFS_MODE_LOW
, false);
4449 int atomisp_css_load_acc_binary(struct atomisp_sub_device
*asd
,
4450 struct atomisp_css_fw_info
*fw
,
4453 struct ia_css_pipe_config
*pipe_config
=
4454 &asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
]
4455 .pipe_configs
[IA_CSS_PIPE_ID_ACC
];
4457 if (index
>= MAX_ACC_STAGES
) {
4458 dev_dbg(asd
->isp
->dev
, "%s: index(%d) out of range\n",
4463 pipe_config
->acc_stages
[index
] = fw
;
4464 pipe_config
->num_acc_stages
= index
+ 1;
4465 pipe_config
->acc_num_execs
= 1;
4470 static struct atomisp_sub_device
*__get_atomisp_subdev(
4471 struct ia_css_pipe
*css_pipe
,
4472 struct atomisp_device
*isp
,
4473 enum atomisp_input_stream_id
*stream_id
)
4476 struct atomisp_sub_device
*asd
;
4477 struct atomisp_stream_env
*stream_env
;
4479 for (i
= 0; i
< isp
->num_of_streams
; i
++) {
4481 if (asd
->streaming
== ATOMISP_DEVICE_STREAMING_DISABLED
&&
4484 for (j
= 0; j
< ATOMISP_INPUT_STREAM_NUM
; j
++) {
4485 stream_env
= &asd
->stream_env
[j
];
4486 for (k
= 0; k
< IA_CSS_PIPE_ID_NUM
; k
++) {
4487 if (stream_env
->pipes
[k
] &&
4488 stream_env
->pipes
[k
] == css_pipe
) {
4499 int atomisp_css_isr_thread(struct atomisp_device
*isp
,
4500 bool *frame_done_found
,
4501 bool *css_pipe_done
)
4503 enum atomisp_input_stream_id stream_id
= 0;
4504 struct atomisp_css_event current_event
;
4505 struct atomisp_sub_device
*asd
= &isp
->asd
[0];
4507 bool reset_wdt_timer
[MAX_STREAM_NUM
] = {false};
4511 while (!atomisp_css_dequeue_event(¤t_event
)) {
4512 if (current_event
.event
.type
==
4513 IA_CSS_EVENT_TYPE_FW_ASSERT
) {
4515 * Received FW assertion signal,
4516 * trigger WDT to recover
4518 dev_err(isp
->dev
, "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4520 current_event
.event
.fw_assert_module_id
,
4521 current_event
.event
.fw_assert_line_no
);
4522 for (i
= 0; i
< isp
->num_of_streams
; i
++)
4523 atomisp_wdt_stop(&isp
->asd
[i
], 0);
4525 atomisp_wdt(&isp
->asd
[0].wdt
);
4527 queue_work(isp
->wdt_work_queue
, &isp
->wdt_work
);
4530 } else if (current_event
.event
.type
== IA_CSS_EVENT_TYPE_FW_WARNING
) {
4531 dev_warn(isp
->dev
, "%s: ISP reports warning, code is %d, exp_id %d\n",
4532 __func__
, current_event
.event
.fw_warning
,
4533 current_event
.event
.exp_id
);
4537 asd
= __get_atomisp_subdev(current_event
.event
.pipe
,
4540 if (current_event
.event
.type
== CSS_EVENT_TIMER
)
4542 "event: Timer event.");
4544 dev_warn(isp
->dev
, "%s:no subdev.event:%d",
4546 current_event
.event
.type
);
4550 atomisp_css_temp_pipe_to_pipe_id(asd
, ¤t_event
);
4551 switch (current_event
.event
.type
) {
4552 case CSS_EVENT_OUTPUT_FRAME_DONE
:
4553 frame_done_found
[asd
->index
] = true;
4554 atomisp_buf_done(asd
, 0, CSS_BUFFER_TYPE_OUTPUT_FRAME
,
4555 current_event
.pipe
, true, stream_id
);
4557 reset_wdt_timer
[asd
->index
] = true; /* ISP running */
4560 case CSS_EVENT_SEC_OUTPUT_FRAME_DONE
:
4561 frame_done_found
[asd
->index
] = true;
4562 atomisp_buf_done(asd
, 0, CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
,
4563 current_event
.pipe
, true, stream_id
);
4565 reset_wdt_timer
[asd
->index
] = true; /* ISP running */
4568 case CSS_EVENT_3A_STATISTICS_DONE
:
4569 atomisp_buf_done(asd
, 0,
4570 CSS_BUFFER_TYPE_3A_STATISTICS
,
4574 case CSS_EVENT_METADATA_DONE
:
4575 atomisp_buf_done(asd
, 0,
4576 CSS_BUFFER_TYPE_METADATA
,
4580 case CSS_EVENT_VF_OUTPUT_FRAME_DONE
:
4581 atomisp_buf_done(asd
, 0,
4582 CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
,
4583 current_event
.pipe
, true, stream_id
);
4585 reset_wdt_timer
[asd
->index
] = true; /* ISP running */
4588 case CSS_EVENT_SEC_VF_OUTPUT_FRAME_DONE
:
4589 atomisp_buf_done(asd
, 0,
4590 CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME
,
4591 current_event
.pipe
, true, stream_id
);
4593 reset_wdt_timer
[asd
->index
] = true; /* ISP running */
4596 case CSS_EVENT_DIS_STATISTICS_DONE
:
4597 atomisp_buf_done(asd
, 0,
4598 CSS_BUFFER_TYPE_DIS_STATISTICS
,
4602 case CSS_EVENT_PIPELINE_DONE
:
4603 css_pipe_done
[asd
->index
] = true;
4605 case CSS_EVENT_ACC_STAGE_COMPLETE
:
4606 atomisp_acc_done(asd
, current_event
.event
.fw_handle
);
4609 dev_dbg(isp
->dev
, "unhandled css stored event: 0x%x\n",
4610 current_event
.event
.type
);
4615 /* If there are no buffers queued then
4616 * delete wdt timer. */
4617 for (i
= 0; i
< isp
->num_of_streams
; i
++) {
4621 if (asd
->streaming
!= ATOMISP_DEVICE_STREAMING_ENABLED
)
4623 if (!atomisp_buffers_queued(asd
))
4624 atomisp_wdt_stop(asd
, false);
4625 else if (reset_wdt_timer
[i
])
4626 /* SOF irq should not reset wdt timer. */
4627 atomisp_wdt_refresh(asd
,
4628 ATOMISP_WDT_KEEP_CURRENT_DELAY
);
4635 bool atomisp_css_valid_sof(struct atomisp_device
*isp
)
4639 /* Loop for each css stream */
4640 for (i
= 0; i
< isp
->num_of_streams
; i
++) {
4641 struct atomisp_sub_device
*asd
= &isp
->asd
[i
];
4642 /* Loop for each css vc stream */
4643 for (j
= 0; j
< ATOMISP_INPUT_STREAM_NUM
; j
++) {
4644 if (asd
->stream_env
[j
].stream
&&
4645 asd
->stream_env
[j
].stream_config
.mode
==
4646 IA_CSS_INPUT_MODE_BUFFERED_SENSOR
)
4654 int atomisp_css_debug_dump_isp_binary(void)
4656 ia_css_debug_dump_isp_binary();
4660 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced
)
4662 sh_css_dump_sp_raw_copy_linecount(reduced
);
4666 int atomisp_css_dump_blob_infor(void)
4668 struct ia_css_blob_descr
*bd
= sh_css_blob_info
;
4669 unsigned int i
, nm
= sh_css_num_binaries
;
4676 for (i
= 1; i
< sh_css_num_binaries
; i
++)
4677 dev_dbg(atomisp_dev
, "Num%d binary id is %d, name is %s\n", i
,
4678 bd
[i
-1].header
.info
.isp
.sp
.id
, bd
[i
-1].name
);
4683 void atomisp_css_set_isp_config_id(struct atomisp_sub_device
*asd
,
4684 uint32_t isp_config_id
)
4686 asd
->params
.config
.isp_config_id
= isp_config_id
;
4689 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device
*asd
,
4690 struct atomisp_css_frame
*output_frame
)
4692 asd
->params
.config
.output_frame
= output_frame
;
4695 int atomisp_get_css_dbgfunc(void)
4700 int atomisp_set_css_dbgfunc(struct atomisp_device
*isp
, int opt
)
4704 ret
= __set_css_print_env(isp
, opt
);
4710 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device
*asd
, bool enable
)
4712 ia_css_en_dz_capt_pipe(
4713 asd
->stream_env
[ATOMISP_INPUT_STREAM_GENERAL
].stream
,
4717 struct atomisp_css_dvs_grid_info
*atomisp_css_get_dvs_grid_info(
4718 struct atomisp_css_grid_info
*grid_info
)
4723 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4724 return &grid_info
->dvs_grid
.dvs_grid_info
;
4726 return &grid_info
->dvs_grid
;