2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include <linux/slab.h>
18 #include <linux/vmalloc.h>
21 #include "sh_css_hrt.h" /* only for file 2 MIPI */
22 #include "ia_css_buffer.h"
23 #include "ia_css_binary.h"
24 #include "sh_css_internal.h"
25 #include "sh_css_mipi.h"
26 #include "sh_css_sp.h" /* sh_css_sp_group */
27 #if !defined(HAS_NO_INPUT_SYSTEM)
28 #include "ia_css_isys.h"
30 #include "ia_css_frame.h"
31 #include "sh_css_defs.h"
32 #include "sh_css_firmware.h"
33 #include "sh_css_params.h"
34 #include "sh_css_params_internal.h"
35 #include "sh_css_param_shading.h"
36 #include "ia_css_refcount.h"
37 #include "ia_css_rmgr.h"
38 #include "ia_css_debug.h"
39 #include "ia_css_debug_pipe.h"
40 #include "ia_css_device_access.h"
41 #include "device_access.h"
42 #include "sh_css_legacy.h"
43 #include "ia_css_pipeline.h"
44 #include "ia_css_stream.h"
45 #include "sh_css_stream_format.h"
46 #include "ia_css_pipe.h"
47 #include "ia_css_util.h"
48 #include "ia_css_pipe_util.h"
49 #include "ia_css_pipe_binarydesc.h"
50 #include "ia_css_pipe_stagedesc.h"
51 #ifdef USE_INPUT_SYSTEM_VERSION_2
52 #include "ia_css_isys.h"
55 #include "memory_access.h"
57 #include "assert_support.h"
58 #include "math_support.h"
59 #include "sw_event_global.h" /* Event IDs.*/
60 #if !defined(HAS_NO_INPUT_FORMATTER)
61 #include "ia_css_ifmtr.h"
63 #if !defined(HAS_NO_INPUT_SYSTEM)
64 #include "input_system.h"
66 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
67 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
68 #include "gdc_device.h" /* HRT_GDC_N */
69 #include "dma.h" /* dma_set_max_burst_size() */
70 #include "irq.h" /* virq */
71 #include "sp.h" /* cnd_sp_irq_enable() */
72 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
73 #include "gp_device.h" /* gp_device_reg_store() */
74 #define __INLINE_GPIO__
76 #include "timed_ctrl.h"
77 #include "platform_support.h" /* hrt_sleep(), inline */
78 #include "ia_css_inputfifo.h"
79 #define WITH_PC_MONITORING 0
81 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
83 #if WITH_PC_MONITORING
84 #define MULTIPLE_SAMPLES 1
85 #define NOF_SAMPLES 60
86 #include "linux/kthread.h"
87 #include "linux/sched.h"
88 #include "linux/delay.h"
89 #include "sh_css_metrics.h"
90 static int thread_alive
;
91 #endif /* WITH_PC_MONITORING */
93 #include "ia_css_spctrl.h"
94 #include "ia_css_version_data.h"
95 #include "sh_css_struct.h"
96 #include "ia_css_bufq.h"
97 #include "ia_css_timer.h" /* clock_value_t */
99 #include "isp/modes/interface/input_buf.isp.h"
101 /* Name of the sp program: should not be built-in */
102 #define SP_PROG_NAME "sp"
103 /* Size of Refcount List */
104 #define REFCOUNT_SIZE 1000
106 /* for JPEG, we don't know the length of the image upfront,
107 * but since we support sensor upto 16MP, we take this as
110 #define JPEG_BYTES (16 * 1024 * 1024)
112 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
113 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
115 #define DEFAULT_PLANES { {0, 0, 0, 0} }
117 struct sh_css my_css
;
119 int (*sh_css_printf
) (const char *fmt
, va_list args
) = NULL
;
121 /* modes of work: stream_create and stream_destroy will update the save/restore data
122 only when in working mode, not suspend/resume
124 enum ia_sh_css_modes
{
125 sh_css_mode_none
= 0,
131 /* a stream seed, to save and restore the stream data.
132 the stream seed contains all the data required to "grow" the seed again after it was closed.
134 struct sh_css_stream_seed
{
135 struct ia_css_stream
**orig_stream
; /* pointer to restore the original handle */
136 struct ia_css_stream
*stream
; /* handle, used as ID too.*/
137 struct ia_css_stream_config stream_config
; /* stream config struct */
139 struct ia_css_pipe
*pipes
[IA_CSS_PIPE_ID_NUM
]; /* pipe handles */
140 struct ia_css_pipe
**orig_pipes
[IA_CSS_PIPE_ID_NUM
]; /* pointer to restore original handle */
141 struct ia_css_pipe_config pipe_config
[IA_CSS_PIPE_ID_NUM
]; /* pipe config structs */
144 #define MAX_ACTIVE_STREAMS 5
145 /* A global struct for save/restore to hold all the data that should sustain power-down:
146 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
149 enum ia_sh_css_modes mode
;
150 uint32_t mmu_base
; /* the last mmu_base */
151 enum ia_css_irq_type irq_type
;
152 struct sh_css_stream_seed stream_seeds
[MAX_ACTIVE_STREAMS
];
153 struct ia_css_fw
*loaded_fw
; /* fw struct previously loaded */
154 struct ia_css_env driver_env
; /* driver-supplied env copy */
157 static bool my_css_save_initialized
; /* if my_css_save was initialized */
158 static struct sh_css_save my_css_save
;
160 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
161 this array is temporary and will be replaced by resource manager*/
162 /* Taking the biggest Size for number of Elements */
163 #define MAX_HMM_BUFFER_NUM \
164 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
166 struct sh_css_hmm_buffer_record
{
168 enum ia_css_buffer_type type
;
169 struct ia_css_rmgr_vbuf_handle
*h_vbuf
;
170 hrt_address kernel_ptr
;
173 static struct sh_css_hmm_buffer_record hmm_buffer_record
[MAX_HMM_BUFFER_NUM
];
175 #define GPIO_FLASH_PIN_MASK (1 << HIVE_GPIO_STROBE_TRIGGER_PIN)
177 static bool fw_explicitly_loaded
= false;
183 static enum ia_css_err
184 allocate_delay_frames(struct ia_css_pipe
*pipe
);
186 static enum ia_css_err
187 sh_css_pipe_start(struct ia_css_stream
*stream
);
191 * @brief Stop all "ia_css_pipe" instances in the target
192 * "ia_css_stream" instance.
194 * @param[in] stream Point to the target "ia_css_stream" instance.
197 * - IA_CSS_SUCCESS, if the "stop" requests have been sucessfully sent out.
198 * - CSS error code, otherwise.
202 * This API sends the "stop" requests to the "ia_css_pipe"
203 * instances in the same "ia_css_stream" instance. It will
204 * return without waiting for all "ia_css_pipe" instatnces
207 static enum ia_css_err
208 sh_css_pipes_stop(struct ia_css_stream
*stream
);
211 * @brief Check if all "ia_css_pipe" instances in the target
212 * "ia_css_stream" instance have stopped.
214 * @param[in] stream Point to the target "ia_css_stream" instance.
217 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
218 * instance have ben stopped.
219 * - false, otherwise.
222 sh_css_pipes_have_stopped(struct ia_css_stream
*stream
);
224 static enum ia_css_err
225 ia_css_pipe_check_format(struct ia_css_pipe
*pipe
, enum ia_css_frame_format format
);
227 static enum ia_css_err
228 check_pipe_resolutions(const struct ia_css_pipe
*pipe
);
232 static enum ia_css_err
233 ia_css_pipe_load_extension(struct ia_css_pipe
*pipe
,
234 struct ia_css_fw_info
*firmware
);
237 ia_css_pipe_unload_extension(struct ia_css_pipe
*pipe
,
238 struct ia_css_fw_info
*firmware
);
240 ia_css_reset_defaults(struct sh_css
* css
);
243 sh_css_init_host_sp_control_vars(void);
245 static enum ia_css_err
set_num_primary_stages(unsigned int *num
, enum ia_css_pipe_version version
);
248 need_capture_pp(const struct ia_css_pipe
*pipe
);
251 need_yuv_scaler_stage(const struct ia_css_pipe
*pipe
);
253 static enum ia_css_err
ia_css_pipe_create_cas_scaler_desc_single_output(
254 struct ia_css_frame_info
*cas_scaler_in_info
,
255 struct ia_css_frame_info
*cas_scaler_out_info
,
256 struct ia_css_frame_info
*cas_scaler_vf_info
,
257 struct ia_css_cas_binary_descr
*descr
);
259 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
*descr
);
262 need_downscaling(const struct ia_css_resolution in_res
,
263 const struct ia_css_resolution out_res
);
265 static bool need_capt_ldc(const struct ia_css_pipe
*pipe
);
267 static enum ia_css_err
268 sh_css_pipe_load_binaries(struct ia_css_pipe
*pipe
);
271 enum ia_css_err
sh_css_pipe_get_viewfinder_frame_info(
272 struct ia_css_pipe
*pipe
,
273 struct ia_css_frame_info
*info
,
276 static enum ia_css_err
277 sh_css_pipe_get_output_frame_info(struct ia_css_pipe
*pipe
,
278 struct ia_css_frame_info
*info
,
281 static enum ia_css_err
282 capture_start(struct ia_css_pipe
*pipe
);
284 static enum ia_css_err
285 video_start(struct ia_css_pipe
*pipe
);
287 static enum ia_css_err
288 preview_start(struct ia_css_pipe
*pipe
);
290 static enum ia_css_err
291 yuvpp_start(struct ia_css_pipe
*pipe
);
293 static bool copy_on_sp(struct ia_css_pipe
*pipe
);
295 static enum ia_css_err
296 init_vf_frameinfo_defaults(struct ia_css_pipe
*pipe
,
297 struct ia_css_frame
*vf_frame
, unsigned int idx
);
299 static enum ia_css_err
300 init_in_frameinfo_memory_defaults(struct ia_css_pipe
*pipe
,
301 struct ia_css_frame
*frame
, enum ia_css_frame_format format
);
303 static enum ia_css_err
304 init_out_frameinfo_defaults(struct ia_css_pipe
*pipe
,
305 struct ia_css_frame
*out_frame
, unsigned int idx
);
307 static enum ia_css_err
308 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline
*pipeline
,
311 static enum ia_css_err
312 alloc_continuous_frames(
313 struct ia_css_pipe
*pipe
, bool init_time
);
316 pipe_global_init(void);
318 static enum ia_css_err
319 pipe_generate_pipe_num(const struct ia_css_pipe
*pipe
, unsigned int *pipe_number
);
322 pipe_release_pipe_num(unsigned int pipe_num
);
324 static enum ia_css_err
325 create_host_pipeline_structure(struct ia_css_stream
*stream
);
327 static enum ia_css_err
328 create_host_pipeline(struct ia_css_stream
*stream
);
330 static enum ia_css_err
331 create_host_preview_pipeline(struct ia_css_pipe
*pipe
);
333 static enum ia_css_err
334 create_host_video_pipeline(struct ia_css_pipe
*pipe
);
336 static enum ia_css_err
337 create_host_copy_pipeline(struct ia_css_pipe
*pipe
,
338 unsigned max_input_width
,
339 struct ia_css_frame
*out_frame
);
341 static enum ia_css_err
342 create_host_isyscopy_capture_pipeline(struct ia_css_pipe
*pipe
);
344 static enum ia_css_err
345 create_host_capture_pipeline(struct ia_css_pipe
*pipe
);
347 static enum ia_css_err
348 create_host_yuvpp_pipeline(struct ia_css_pipe
*pipe
);
350 static enum ia_css_err
351 create_host_acc_pipeline(struct ia_css_pipe
*pipe
);
354 sh_css_get_sw_interrupt_value(unsigned int irq
);
356 static struct ia_css_binary
*ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe
*pipe
);
358 static struct ia_css_binary
*
359 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe
*pipe
);
361 static struct ia_css_binary
*
362 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe
*pipe
);
365 sh_css_hmm_buffer_record_init(void);
368 sh_css_hmm_buffer_record_uninit(void);
371 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record
*buffer_record
);
373 static struct sh_css_hmm_buffer_record
374 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle
*h_vbuf
,
375 enum ia_css_buffer_type type
,
376 hrt_address kernel_ptr
);
378 static struct sh_css_hmm_buffer_record
379 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr
,
380 enum ia_css_buffer_type type
);
383 ia_css_get_acc_configs(
384 struct ia_css_pipe
*pipe
,
385 struct ia_css_isp_config
*config
);
388 #if CONFIG_ON_FRAME_ENQUEUE()
389 static enum ia_css_err
set_config_on_frame_enqueue(struct ia_css_frame_info
*info
, struct frame_data_wrapper
*frame
);
392 #ifdef USE_INPUT_SYSTEM_VERSION_2401
393 static unsigned int get_crop_lines_for_bayer_order(const struct ia_css_stream_config
*config
);
394 static unsigned int get_crop_columns_for_bayer_order(const struct ia_css_stream_config
*config
);
395 static void get_pipe_extra_pixel(struct ia_css_pipe
*pipe
,
396 unsigned int *extra_row
, unsigned int *extra_column
);
400 #ifdef USE_INPUT_SYSTEM_VERSION_2401
401 static enum ia_css_err
402 aspect_ratio_crop_init(struct ia_css_stream
*curr_stream
,
403 struct ia_css_pipe
*pipes
[],
404 bool *do_crop_status
);
407 aspect_ratio_crop_check(bool enabled
, struct ia_css_pipe
*curr_pipe
);
409 static enum ia_css_err
410 aspect_ratio_crop(struct ia_css_pipe
*curr_pipe
,
411 struct ia_css_resolution
*effective_res
);
416 sh_css_pipe_free_shading_table(struct ia_css_pipe
*pipe
)
418 assert(pipe
!= NULL
);
420 IA_CSS_ERROR("NULL input parameter");
424 if (pipe
->shading_table
)
425 ia_css_shading_table_free(pipe
->shading_table
);
426 pipe
->shading_table
= NULL
;
429 static enum ia_css_frame_format yuv420_copy_formats
[] = {
430 IA_CSS_FRAME_FORMAT_NV12
,
431 IA_CSS_FRAME_FORMAT_NV21
,
432 IA_CSS_FRAME_FORMAT_YV12
,
433 IA_CSS_FRAME_FORMAT_YUV420
,
434 IA_CSS_FRAME_FORMAT_YUV420_16
,
435 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8
,
436 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
439 static enum ia_css_frame_format yuv422_copy_formats
[] = {
440 IA_CSS_FRAME_FORMAT_NV12
,
441 IA_CSS_FRAME_FORMAT_NV16
,
442 IA_CSS_FRAME_FORMAT_NV21
,
443 IA_CSS_FRAME_FORMAT_NV61
,
444 IA_CSS_FRAME_FORMAT_YV12
,
445 IA_CSS_FRAME_FORMAT_YV16
,
446 IA_CSS_FRAME_FORMAT_YUV420
,
447 IA_CSS_FRAME_FORMAT_YUV420_16
,
448 IA_CSS_FRAME_FORMAT_YUV422
,
449 IA_CSS_FRAME_FORMAT_YUV422_16
,
450 IA_CSS_FRAME_FORMAT_UYVY
,
451 IA_CSS_FRAME_FORMAT_YUYV
454 /* Verify whether the selected output format is can be produced
455 * by the copy binary given the stream format.
457 static enum ia_css_err
458 verify_copy_out_frame_format(struct ia_css_pipe
*pipe
)
460 enum ia_css_frame_format out_fmt
= pipe
->output_info
[0].format
;
461 unsigned int i
, found
= 0;
463 assert(pipe
!= NULL
);
464 assert(pipe
->stream
!= NULL
);
466 switch (pipe
->stream
->config
.input_config
.format
) {
467 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY
:
468 case IA_CSS_STREAM_FORMAT_YUV420_8
:
469 for (i
=0; i
<ARRAY_SIZE(yuv420_copy_formats
) && !found
; i
++)
470 found
= (out_fmt
== yuv420_copy_formats
[i
]);
472 case IA_CSS_STREAM_FORMAT_YUV420_10
:
473 case IA_CSS_STREAM_FORMAT_YUV420_16
:
474 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_YUV420_16
);
476 case IA_CSS_STREAM_FORMAT_YUV422_8
:
477 for (i
=0; i
<ARRAY_SIZE(yuv422_copy_formats
) && !found
; i
++)
478 found
= (out_fmt
== yuv422_copy_formats
[i
]);
480 case IA_CSS_STREAM_FORMAT_YUV422_10
:
481 case IA_CSS_STREAM_FORMAT_YUV422_16
:
482 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_YUV422_16
||
483 out_fmt
== IA_CSS_FRAME_FORMAT_YUV420_16
);
485 case IA_CSS_STREAM_FORMAT_RGB_444
:
486 case IA_CSS_STREAM_FORMAT_RGB_555
:
487 case IA_CSS_STREAM_FORMAT_RGB_565
:
488 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_RGBA888
||
489 out_fmt
== IA_CSS_FRAME_FORMAT_RGB565
);
491 case IA_CSS_STREAM_FORMAT_RGB_666
:
492 case IA_CSS_STREAM_FORMAT_RGB_888
:
493 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_RGBA888
||
494 out_fmt
== IA_CSS_FRAME_FORMAT_YUV420
);
496 case IA_CSS_STREAM_FORMAT_RAW_6
:
497 case IA_CSS_STREAM_FORMAT_RAW_7
:
498 case IA_CSS_STREAM_FORMAT_RAW_8
:
499 case IA_CSS_STREAM_FORMAT_RAW_10
:
500 case IA_CSS_STREAM_FORMAT_RAW_12
:
501 case IA_CSS_STREAM_FORMAT_RAW_14
:
502 case IA_CSS_STREAM_FORMAT_RAW_16
:
503 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_RAW
) ||
504 (out_fmt
== IA_CSS_FRAME_FORMAT_RAW_PACKED
);
506 case IA_CSS_STREAM_FORMAT_BINARY_8
:
507 found
= (out_fmt
== IA_CSS_FRAME_FORMAT_BINARY_8
);
513 return IA_CSS_ERR_INVALID_ARGUMENTS
;
514 return IA_CSS_SUCCESS
;
518 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream
*stream
)
523 bpp
= ia_css_util_input_format_bpp(stream
->config
.input_config
.format
,
524 stream
->config
.pixels_per_clock
== 2);
529 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
530 static enum ia_css_err
531 sh_css_config_input_network(struct ia_css_stream
*stream
)
533 unsigned int fmt_type
;
534 struct ia_css_pipe
*pipe
= stream
->last_pipe
;
535 struct ia_css_binary
*binary
= NULL
;
536 enum ia_css_err err
= IA_CSS_SUCCESS
;
538 assert(stream
!= NULL
);
539 assert(pipe
!= NULL
);
541 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
542 "sh_css_config_input_network() enter:\n");
544 if (pipe
->pipeline
.stages
)
545 binary
= pipe
->pipeline
.stages
->binary
;
547 err
= ia_css_isys_convert_stream_format_to_mipi_format(
548 stream
->config
.input_config
.format
,
549 stream
->csi_rx_config
.comp
,
551 if (err
!= IA_CSS_SUCCESS
)
553 sh_css_sp_program_input_circuit(fmt_type
,
554 stream
->config
.channel_id
,
555 stream
->config
.mode
);
557 if ((binary
&& (binary
->online
|| stream
->config
.continuous
)) ||
558 pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
) {
559 err
= ia_css_ifmtr_configure(&stream
->config
,
561 if (err
!= IA_CSS_SUCCESS
)
565 if (stream
->config
.mode
== IA_CSS_INPUT_MODE_TPG
||
566 stream
->config
.mode
== IA_CSS_INPUT_MODE_PRBS
) {
567 unsigned int hblank_cycles
= 100,
572 width
= (stream
->config
.input_config
.input_res
.width
) / (1 + (stream
->config
.pixels_per_clock
== 2));
573 height
= stream
->config
.input_config
.input_res
.height
;
574 vblank_cycles
= vblank_lines
* (width
+ hblank_cycles
);
575 sh_css_sp_configure_sync_gen(width
, height
, hblank_cycles
,
577 #if defined(IS_ISP_2400_SYSTEM)
578 if (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_TPG
) {
579 /* TODO: move define to proper file in tools */
580 #define GP_ISEL_TPG_MODE 0x90058
581 ia_css_device_store_uint32(GP_ISEL_TPG_MODE
, 0);
585 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
586 "sh_css_config_input_network() leave:\n");
587 return IA_CSS_SUCCESS
;
589 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
590 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
591 enum ia_css_stream_format format
,
592 unsigned int pixels_per_line
)
597 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY
:
599 * The frame format layout is shown below.
601 * Line 0: UYY0 UYY0 ... UYY0
602 * Line 1: VYY0 VYY0 ... VYY0
603 * Line 2: UYY0 UYY0 ... UYY0
604 * Line 3: VYY0 VYY0 ... VYY0
606 * Line (n-2): UYY0 UYY0 ... UYY0
607 * Line (n-1): VYY0 VYY0 ... VYY0
609 * In this frame format, the even-line is
610 * as wide as the odd-line.
611 * The 0 is introduced by the input system
614 rval
= pixels_per_line
* 2;
616 case IA_CSS_STREAM_FORMAT_YUV420_8
:
617 case IA_CSS_STREAM_FORMAT_YUV420_10
:
618 case IA_CSS_STREAM_FORMAT_YUV420_16
:
620 * The frame format layout is shown below.
622 * Line 0: YYYY YYYY ... YYYY
623 * Line 1: UYVY UYVY ... UYVY UYVY
624 * Line 2: YYYY YYYY ... YYYY
625 * Line 3: UYVY UYVY ... UYVY UYVY
627 * Line (n-2): YYYY YYYY ... YYYY
628 * Line (n-1): UYVY UYVY ... UYVY UYVY
630 * In this frame format, the odd-line is twice
631 * wider than the even-line.
633 rval
= pixels_per_line
* 2;
635 case IA_CSS_STREAM_FORMAT_YUV422_8
:
636 case IA_CSS_STREAM_FORMAT_YUV422_10
:
637 case IA_CSS_STREAM_FORMAT_YUV422_16
:
639 * The frame format layout is shown below.
641 * Line 0: UYVY UYVY ... UYVY
642 * Line 1: UYVY UYVY ... UYVY
643 * Line 2: UYVY UYVY ... UYVY
644 * Line 3: UYVY UYVY ... UYVY
646 * Line (n-2): UYVY UYVY ... UYVY
647 * Line (n-1): UYVY UYVY ... UYVY
649 * In this frame format, the even-line is
650 * as wide as the odd-line.
652 rval
= pixels_per_line
* 2;
654 case IA_CSS_STREAM_FORMAT_RGB_444
:
655 case IA_CSS_STREAM_FORMAT_RGB_555
:
656 case IA_CSS_STREAM_FORMAT_RGB_565
:
657 case IA_CSS_STREAM_FORMAT_RGB_666
:
658 case IA_CSS_STREAM_FORMAT_RGB_888
:
660 * The frame format layout is shown below.
662 * Line 0: ABGR ABGR ... ABGR
663 * Line 1: ABGR ABGR ... ABGR
664 * Line 2: ABGR ABGR ... ABGR
665 * Line 3: ABGR ABGR ... ABGR
667 * Line (n-2): ABGR ABGR ... ABGR
668 * Line (n-1): ABGR ABGR ... ABGR
670 * In this frame format, the even-line is
671 * as wide as the odd-line.
673 rval
= pixels_per_line
* 4;
675 case IA_CSS_STREAM_FORMAT_RAW_6
:
676 case IA_CSS_STREAM_FORMAT_RAW_7
:
677 case IA_CSS_STREAM_FORMAT_RAW_8
:
678 case IA_CSS_STREAM_FORMAT_RAW_10
:
679 case IA_CSS_STREAM_FORMAT_RAW_12
:
680 case IA_CSS_STREAM_FORMAT_RAW_14
:
681 case IA_CSS_STREAM_FORMAT_RAW_16
:
682 case IA_CSS_STREAM_FORMAT_BINARY_8
:
683 case IA_CSS_STREAM_FORMAT_USER_DEF1
:
684 case IA_CSS_STREAM_FORMAT_USER_DEF2
:
685 case IA_CSS_STREAM_FORMAT_USER_DEF3
:
686 case IA_CSS_STREAM_FORMAT_USER_DEF4
:
687 case IA_CSS_STREAM_FORMAT_USER_DEF5
:
688 case IA_CSS_STREAM_FORMAT_USER_DEF6
:
689 case IA_CSS_STREAM_FORMAT_USER_DEF7
:
690 case IA_CSS_STREAM_FORMAT_USER_DEF8
:
692 * The frame format layout is shown below.
694 * Line 0: Pixel Pixel ... Pixel
695 * Line 1: Pixel Pixel ... Pixel
696 * Line 2: Pixel Pixel ... Pixel
697 * Line 3: Pixel Pixel ... Pixel
699 * Line (n-2): Pixel Pixel ... Pixel
700 * Line (n-1): Pixel Pixel ... Pixel
702 * In this frame format, the even-line is
703 * as wide as the odd-line.
705 rval
= pixels_per_line
;
715 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
716 struct ia_css_stream_config
*stream_cfg
,
717 ia_css_isys_descr_t
*isys_stream_descr
)
722 switch (stream_cfg
->mode
) {
723 case IA_CSS_INPUT_MODE_TPG
:
725 if (stream_cfg
->source
.tpg
.id
== IA_CSS_TPG_ID0
) {
726 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT0_ID
;
727 } else if (stream_cfg
->source
.tpg
.id
== IA_CSS_TPG_ID1
) {
728 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT1_ID
;
729 } else if (stream_cfg
->source
.tpg
.id
== IA_CSS_TPG_ID2
) {
730 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT2_ID
;
734 case IA_CSS_INPUT_MODE_PRBS
:
736 if (stream_cfg
->source
.prbs
.id
== IA_CSS_PRBS_ID0
) {
737 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT0_ID
;
738 } else if (stream_cfg
->source
.prbs
.id
== IA_CSS_PRBS_ID1
) {
739 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT1_ID
;
740 } else if (stream_cfg
->source
.prbs
.id
== IA_CSS_PRBS_ID2
) {
741 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_PIXELGEN_PORT2_ID
;
745 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR
:
747 if (stream_cfg
->source
.port
.port
== IA_CSS_CSI2_PORT0
) {
748 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_CSI_PORT0_ID
;
749 } else if (stream_cfg
->source
.port
.port
== IA_CSS_CSI2_PORT1
) {
750 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_CSI_PORT1_ID
;
751 } else if (stream_cfg
->source
.port
.port
== IA_CSS_CSI2_PORT2
) {
752 isys_stream_descr
->input_port_id
= INPUT_SYSTEM_CSI_PORT2_ID
;
764 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
765 struct ia_css_stream_config
*stream_cfg
,
766 ia_css_isys_descr_t
*isys_stream_descr
)
771 switch (stream_cfg
->mode
) {
772 case IA_CSS_INPUT_MODE_TPG
:
774 isys_stream_descr
->mode
= INPUT_SYSTEM_SOURCE_TYPE_TPG
;
777 case IA_CSS_INPUT_MODE_PRBS
:
779 isys_stream_descr
->mode
= INPUT_SYSTEM_SOURCE_TYPE_PRBS
;
782 case IA_CSS_INPUT_MODE_SENSOR
:
783 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR
:
785 isys_stream_descr
->mode
= INPUT_SYSTEM_SOURCE_TYPE_SENSOR
;
796 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
797 struct ia_css_stream_config
*stream_cfg
,
798 ia_css_isys_descr_t
*isys_stream_descr
,
804 switch (stream_cfg
->mode
) {
805 case IA_CSS_INPUT_MODE_TPG
:
806 if (stream_cfg
->source
.tpg
.mode
== IA_CSS_TPG_MODE_RAMP
) {
807 isys_stream_descr
->tpg_port_attr
.mode
= PIXELGEN_TPG_MODE_RAMP
;
808 } else if (stream_cfg
->source
.tpg
.mode
== IA_CSS_TPG_MODE_CHECKERBOARD
) {
809 isys_stream_descr
->tpg_port_attr
.mode
= PIXELGEN_TPG_MODE_CHBO
;
810 } else if (stream_cfg
->source
.tpg
.mode
== IA_CSS_TPG_MODE_MONO
) {
811 isys_stream_descr
->tpg_port_attr
.mode
= PIXELGEN_TPG_MODE_MONO
;
818 * - Make "color_cfg" as part of "ia_css_tpg_config".
820 isys_stream_descr
->tpg_port_attr
.color_cfg
.R1
= 51;
821 isys_stream_descr
->tpg_port_attr
.color_cfg
.G1
= 102;
822 isys_stream_descr
->tpg_port_attr
.color_cfg
.B1
= 255;
823 isys_stream_descr
->tpg_port_attr
.color_cfg
.R2
= 0;
824 isys_stream_descr
->tpg_port_attr
.color_cfg
.G2
= 100;
825 isys_stream_descr
->tpg_port_attr
.color_cfg
.B2
= 160;
827 isys_stream_descr
->tpg_port_attr
.mask_cfg
.h_mask
= stream_cfg
->source
.tpg
.x_mask
;
828 isys_stream_descr
->tpg_port_attr
.mask_cfg
.v_mask
= stream_cfg
->source
.tpg
.y_mask
;
829 isys_stream_descr
->tpg_port_attr
.mask_cfg
.hv_mask
= stream_cfg
->source
.tpg
.xy_mask
;
831 isys_stream_descr
->tpg_port_attr
.delta_cfg
.h_delta
= stream_cfg
->source
.tpg
.x_delta
;
832 isys_stream_descr
->tpg_port_attr
.delta_cfg
.v_delta
= stream_cfg
->source
.tpg
.y_delta
;
836 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
838 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.hblank_cycles
= 100;
839 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.vblank_cycles
= 100;
840 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.pixels_per_clock
= stream_cfg
->pixels_per_clock
;
841 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.nr_of_frames
= (uint32_t) ~(0x0);
842 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.pixels_per_line
= stream_cfg
->isys_config
[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
].input_res
.width
;
843 isys_stream_descr
->tpg_port_attr
.sync_gen_cfg
.lines_per_frame
= stream_cfg
->isys_config
[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
].input_res
.height
;
846 case IA_CSS_INPUT_MODE_PRBS
:
848 isys_stream_descr
->prbs_port_attr
.seed0
= stream_cfg
->source
.prbs
.seed
;
849 isys_stream_descr
->prbs_port_attr
.seed1
= stream_cfg
->source
.prbs
.seed1
;
853 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
855 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.hblank_cycles
= 100;
856 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.vblank_cycles
= 100;
857 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.pixels_per_clock
= stream_cfg
->pixels_per_clock
;
858 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.nr_of_frames
= (uint32_t) ~(0x0);
859 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.pixels_per_line
= stream_cfg
->isys_config
[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
].input_res
.width
;
860 isys_stream_descr
->prbs_port_attr
.sync_gen_cfg
.lines_per_frame
= stream_cfg
->isys_config
[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX
].input_res
.height
;
863 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR
:
866 unsigned int fmt_type
;
868 err
= ia_css_isys_convert_stream_format_to_mipi_format(
869 stream_cfg
->isys_config
[isys_stream_idx
].format
,
872 if (err
!= IA_CSS_SUCCESS
)
875 isys_stream_descr
->csi_port_attr
.active_lanes
= stream_cfg
->source
.port
.num_lanes
;
876 isys_stream_descr
->csi_port_attr
.fmt_type
= fmt_type
;
877 isys_stream_descr
->csi_port_attr
.ch_id
= stream_cfg
->channel_id
;
878 #ifdef USE_INPUT_SYSTEM_VERSION_2401
879 isys_stream_descr
->online
= stream_cfg
->online
;
881 err
|= ia_css_isys_convert_compressed_format(
882 &stream_cfg
->source
.port
.compression
,
884 if (err
!= IA_CSS_SUCCESS
)
888 isys_stream_descr
->metadata
.enable
= false;
889 if (stream_cfg
->metadata_config
.resolution
.height
> 0) {
890 err
= ia_css_isys_convert_stream_format_to_mipi_format(
891 stream_cfg
->metadata_config
.data_type
,
894 if (err
!= IA_CSS_SUCCESS
)
896 isys_stream_descr
->metadata
.fmt_type
= fmt_type
;
897 isys_stream_descr
->metadata
.bits_per_pixel
=
898 ia_css_util_input_format_bpp(stream_cfg
->metadata_config
.data_type
, true);
899 isys_stream_descr
->metadata
.pixels_per_line
= stream_cfg
->metadata_config
.resolution
.width
;
900 isys_stream_descr
->metadata
.lines_per_frame
= stream_cfg
->metadata_config
.resolution
.height
;
901 #ifdef USE_INPUT_SYSTEM_VERSION_2401
902 /* For new input system, number of str2mmio requests must be even.
903 * So we round up number of metadata lines to be even. */
904 if (isys_stream_descr
->metadata
.lines_per_frame
> 0)
905 isys_stream_descr
->metadata
.lines_per_frame
+=
906 (isys_stream_descr
->metadata
.lines_per_frame
& 1);
908 isys_stream_descr
->metadata
.align_req_in_bytes
=
909 ia_css_csi2_calculate_input_system_alignment(stream_cfg
->metadata_config
.data_type
);
910 isys_stream_descr
->metadata
.enable
= true;
923 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
924 struct ia_css_stream_config
*stream_cfg
,
925 ia_css_isys_descr_t
*isys_stream_descr
,
928 unsigned int bits_per_subpixel
;
929 unsigned int max_subpixels_per_line
;
930 unsigned int lines_per_frame
;
931 unsigned int align_req_in_bytes
;
932 enum ia_css_stream_format fmt_type
;
934 fmt_type
= stream_cfg
->isys_config
[isys_stream_idx
].format
;
935 if ((stream_cfg
->mode
== IA_CSS_INPUT_MODE_SENSOR
||
936 stream_cfg
->mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
) &&
937 stream_cfg
->source
.port
.compression
.type
!= IA_CSS_CSI2_COMPRESSION_TYPE_NONE
) {
939 if (stream_cfg
->source
.port
.compression
.uncompressed_bits_per_pixel
==
940 UNCOMPRESSED_BITS_PER_PIXEL_10
) {
941 fmt_type
= IA_CSS_STREAM_FORMAT_RAW_10
;
943 else if (stream_cfg
->source
.port
.compression
.uncompressed_bits_per_pixel
==
944 UNCOMPRESSED_BITS_PER_PIXEL_12
) {
945 fmt_type
= IA_CSS_STREAM_FORMAT_RAW_12
;
952 sh_css_stream_format_2_bits_per_subpixel(fmt_type
);
953 if (bits_per_subpixel
== 0)
956 max_subpixels_per_line
=
957 csi2_protocol_calculate_max_subpixels_per_line(fmt_type
,
958 stream_cfg
->isys_config
[isys_stream_idx
].input_res
.width
);
959 if (max_subpixels_per_line
== 0)
962 lines_per_frame
= stream_cfg
->isys_config
[isys_stream_idx
].input_res
.height
;
963 if (lines_per_frame
== 0)
966 align_req_in_bytes
= ia_css_csi2_calculate_input_system_alignment(fmt_type
);
968 /* HW needs subpixel info for their settings */
969 isys_stream_descr
->input_port_resolution
.bits_per_pixel
= bits_per_subpixel
;
970 isys_stream_descr
->input_port_resolution
.pixels_per_line
= max_subpixels_per_line
;
971 isys_stream_descr
->input_port_resolution
.lines_per_frame
= lines_per_frame
;
972 isys_stream_descr
->input_port_resolution
.align_req_in_bytes
= align_req_in_bytes
;
977 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
978 struct ia_css_stream_config
*stream_cfg
,
980 ia_css_isys_descr_t
*isys_stream_descr
,
985 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
986 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
987 rc
= sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg
, isys_stream_descr
);
988 rc
&= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg
, isys_stream_descr
);
989 rc
&= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg
, isys_stream_descr
, isys_stream_idx
);
990 rc
&= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(stream_cfg
, isys_stream_descr
, isys_stream_idx
);
992 isys_stream_descr
->raw_packed
= stream_cfg
->pack_raw_pixels
;
993 isys_stream_descr
->linked_isys_stream_id
= (int8_t) stream_cfg
->isys_config
[isys_stream_idx
].linked_isys_stream_id
;
995 * Early polling is required for timestamp accuracy in certain case.
996 * The ISYS HW polling is started on
997 * ia_css_isys_stream_capture_indication() instead of
998 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
999 * capture takes longer than getting an ISYS frame
1001 * Only 2401 relevant ??
1003 isys_stream_descr
->polling_mode
1004 = early_polling
? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1005 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME
;
1006 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
1007 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1012 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1013 struct ia_css_binary
*binary
,
1014 ia_css_isys_descr_t
*isys_stream_descr
)
1019 isys_stream_descr
->output_port_attr
.left_padding
= binary
->left_padding
;
1020 isys_stream_descr
->output_port_attr
.max_isp_input_width
= binary
->info
->sp
.input
.max_width
;
1025 static enum ia_css_err
1026 sh_css_config_input_network(struct ia_css_stream
*stream
)
1029 ia_css_isys_descr_t isys_stream_descr
;
1030 unsigned int sp_thread_id
;
1031 struct sh_css_sp_pipeline_terminal
*sp_pipeline_input_terminal
;
1032 struct ia_css_pipe
*pipe
= NULL
;
1033 struct ia_css_binary
*binary
= NULL
;
1035 uint32_t isys_stream_id
;
1036 bool early_polling
= false;
1038 assert(stream
!= NULL
);
1039 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
1040 "sh_css_config_input_network() enter 0x%p:\n", stream
);
1042 if (stream
->config
.continuous
== true) {
1043 if (stream
->last_pipe
->config
.mode
== IA_CSS_PIPE_MODE_CAPTURE
) {
1044 pipe
= stream
->last_pipe
;
1045 } else if (stream
->last_pipe
->config
.mode
== IA_CSS_PIPE_MODE_YUVPP
) {
1046 pipe
= stream
->last_pipe
;
1047 } else if (stream
->last_pipe
->config
.mode
== IA_CSS_PIPE_MODE_PREVIEW
) {
1048 pipe
= stream
->last_pipe
->pipe_settings
.preview
.copy_pipe
;
1049 } else if (stream
->last_pipe
->config
.mode
== IA_CSS_PIPE_MODE_VIDEO
) {
1050 pipe
= stream
->last_pipe
->pipe_settings
.video
.copy_pipe
;
1053 pipe
= stream
->last_pipe
;
1054 if (stream
->last_pipe
->config
.mode
== IA_CSS_PIPE_MODE_CAPTURE
) {
1056 * We need to poll the ISYS HW in capture_indication itself
1057 * for "non-continous" capture usecase for getting accurate
1058 * isys frame capture timestamps.
1059 * This is because the capturepipe propcessing takes longer
1060 * to execute than the input system frame capture.
1063 early_polling
= true;
1067 assert(pipe
!= NULL
);
1069 return IA_CSS_ERR_INTERNAL_ERROR
;
1071 if (pipe
->pipeline
.stages
!= NULL
)
1072 if (pipe
->pipeline
.stages
->binary
!= NULL
)
1073 binary
= pipe
->pipeline
.stages
->binary
;
1078 /* this was being done in ifmtr in 2400.
1079 * online and cont bypass the init_in_frameinfo_memory_defaults
1080 * so need to do it here
1082 ia_css_get_crop_offsets(pipe
, &binary
->in_frame_info
);
1085 /* get the SP thread id */
1086 rc
= ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &sp_thread_id
);
1088 return IA_CSS_ERR_INTERNAL_ERROR
;
1089 /* get the target input terminal */
1090 sp_pipeline_input_terminal
= &(sh_css_sp_group
.pipe_io
[sp_thread_id
].input
);
1092 for (i
= 0; i
< IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
; i
++) {
1093 /* initialization */
1094 memset((void*)(&isys_stream_descr
), 0, sizeof(ia_css_isys_descr_t
));
1095 sp_pipeline_input_terminal
->context
.virtual_input_system_stream
[i
].valid
= 0;
1096 sp_pipeline_input_terminal
->ctrl
.virtual_input_system_stream_cfg
[i
].valid
= 0;
1098 if (!stream
->config
.isys_config
[i
].valid
)
1101 /* translate the stream configuration to the Input System (2401) configuration */
1102 rc
= sh_css_translate_stream_cfg_to_isys_stream_descr(
1105 &(isys_stream_descr
), i
);
1107 if (stream
->config
.online
) {
1108 rc
&= sh_css_translate_binary_info_to_input_system_output_port_attr(
1110 &(isys_stream_descr
));
1114 return IA_CSS_ERR_INTERNAL_ERROR
;
1116 isys_stream_id
= ia_css_isys_generate_stream_id(sp_thread_id
, i
);
1118 /* create the virtual Input System (2401) */
1119 rc
= ia_css_isys_stream_create(
1120 &(isys_stream_descr
),
1121 &(sp_pipeline_input_terminal
->context
.virtual_input_system_stream
[i
]),
1124 return IA_CSS_ERR_INTERNAL_ERROR
;
1126 /* calculate the configuration of the virtual Input System (2401) */
1127 rc
= ia_css_isys_stream_calculate_cfg(
1128 &(sp_pipeline_input_terminal
->context
.virtual_input_system_stream
[i
]),
1129 &(isys_stream_descr
),
1130 &(sp_pipeline_input_terminal
->ctrl
.virtual_input_system_stream_cfg
[i
]));
1132 ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal
->context
.virtual_input_system_stream
[i
]));
1133 return IA_CSS_ERR_INTERNAL_ERROR
;
1137 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
1138 "sh_css_config_input_network() leave:\n");
1140 return IA_CSS_SUCCESS
;
1143 static inline struct ia_css_pipe
*stream_get_last_pipe(
1144 struct ia_css_stream
*stream
)
1146 struct ia_css_pipe
*last_pipe
= NULL
;
1148 last_pipe
= stream
->last_pipe
;
1153 static inline struct ia_css_pipe
*stream_get_copy_pipe(
1154 struct ia_css_stream
*stream
)
1156 struct ia_css_pipe
*copy_pipe
= NULL
;
1157 struct ia_css_pipe
*last_pipe
= NULL
;
1158 enum ia_css_pipe_id pipe_id
;
1160 last_pipe
= stream_get_last_pipe(stream
);
1162 if ((stream
!= NULL
) &&
1163 (last_pipe
!= NULL
) &&
1164 (stream
->config
.continuous
)) {
1166 pipe_id
= last_pipe
->mode
;
1168 case IA_CSS_PIPE_ID_PREVIEW
:
1169 copy_pipe
= last_pipe
->pipe_settings
.preview
.copy_pipe
;
1171 case IA_CSS_PIPE_ID_VIDEO
:
1172 copy_pipe
= last_pipe
->pipe_settings
.video
.copy_pipe
;
1183 static inline struct ia_css_pipe
*stream_get_target_pipe(
1184 struct ia_css_stream
*stream
)
1186 struct ia_css_pipe
*target_pipe
;
1188 /* get the pipe that consumes the stream */
1189 if (stream
->config
.continuous
) {
1190 target_pipe
= stream_get_copy_pipe(stream
);
1192 target_pipe
= stream_get_last_pipe(stream
);
1198 static enum ia_css_err
stream_csi_rx_helper(
1199 struct ia_css_stream
*stream
,
1200 enum ia_css_err (*func
)(enum ia_css_csi2_port
, uint32_t))
1202 enum ia_css_err retval
= IA_CSS_ERR_INTERNAL_ERROR
;
1203 uint32_t sp_thread_id
, stream_id
;
1205 struct ia_css_pipe
*target_pipe
= NULL
;
1207 if ((stream
== NULL
) || (stream
->config
.mode
!= IA_CSS_INPUT_MODE_BUFFERED_SENSOR
))
1210 target_pipe
= stream_get_target_pipe(stream
);
1212 if (target_pipe
== NULL
)
1215 rc
= ia_css_pipeline_get_sp_thread_id(
1216 ia_css_pipe_get_pipe_num(target_pipe
),
1222 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1225 if (stream
->config
.isys_config
[stream_id
].valid
) {
1226 uint32_t isys_stream_id
= ia_css_isys_generate_stream_id(sp_thread_id
, stream_id
);
1227 retval
= func(stream
->config
.source
.port
.port
, isys_stream_id
);
1230 } while ((retval
== IA_CSS_SUCCESS
) &&
1231 (stream_id
< IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
));
1237 static inline enum ia_css_err
stream_register_with_csi_rx(
1238 struct ia_css_stream
*stream
)
1240 return stream_csi_rx_helper(stream
, ia_css_isys_csi_rx_register_stream
);
1243 static inline enum ia_css_err
stream_unregister_with_csi_rx(
1244 struct ia_css_stream
*stream
)
1246 return stream_csi_rx_helper(stream
, ia_css_isys_csi_rx_unregister_stream
);
1250 #if WITH_PC_MONITORING
1251 static struct task_struct
*my_kthread
; /* Handle for the monitoring thread */
1252 static int sh_binary_running
; /* Enable sampling in the thread */
1254 static void print_pc_histo(char *core_name
, struct sh_css_pc_histogram
*hist
)
1257 unsigned cnt_run
= 0;
1258 unsigned cnt_stall
= 0;
1263 sh_css_print("%s histogram length = %d\n", core_name
, hist
->length
);
1264 sh_css_print("%s PC\trun\tstall\n", core_name
);
1266 for (i
= 0; i
< hist
->length
; i
++) {
1267 if ((hist
->run
[i
] == 0) && (hist
->run
[i
] == hist
->stall
[i
]))
1269 sh_css_print("%s %d\t%d\t%d\n",
1270 core_name
, i
, hist
->run
[i
], hist
->stall
[i
]);
1271 cnt_run
+= hist
->run
[i
];
1272 cnt_stall
+= hist
->stall
[i
];
1275 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, "
1276 "hist->length = %d\n",
1277 core_name
, cnt_run
, cnt_stall
, hist
->length
);
1280 static void print_pc_histogram(void)
1282 struct ia_css_binary_metrics
*metrics
;
1284 for (metrics
= sh_css_metrics
.binary_metrics
;
1286 metrics
= metrics
->next
) {
1287 if (metrics
->mode
== IA_CSS_BINARY_MODE_PREVIEW
||
1288 metrics
->mode
== IA_CSS_BINARY_MODE_VF_PP
) {
1289 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1294 sh_css_print(" pc_histogram for binary %d\n", metrics
->id
);
1295 print_pc_histo(" ISP", &metrics
->isp_histogram
);
1296 print_pc_histo(" SP", &metrics
->sp_histogram
);
1297 sh_css_print("print_pc_histogram() done for binay->id = %d, "
1298 "done.\n", metrics
->id
);
1301 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1304 static int pc_monitoring(void *data
)
1310 if (sh_binary_running
) {
1311 sh_css_metrics_sample_pcs();
1312 #if MULTIPLE_SAMPLES
1313 for (i
= 0; i
< NOF_SAMPLES
; i
++)
1314 sh_css_metrics_sample_pcs();
1317 usleep_range(10, 50);
1322 static void spying_thread_create(void)
1324 my_kthread
= kthread_run(pc_monitoring
, NULL
, "sh_pc_monitor");
1325 sh_css_metrics_enable_pc_histogram(1);
1328 static void input_frame_info(struct ia_css_frame_info frame_info
)
1330 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, "
1331 "frame->info.res.height = %d, format = %d\n",
1332 frame_info
.res
.width
, frame_info
.res
.height
, frame_info
.format
);
1334 #endif /* WITH_PC_MONITORING */
1337 start_binary(struct ia_css_pipe
*pipe
,
1338 struct ia_css_binary
*binary
)
1340 struct ia_css_stream
*stream
;
1342 assert(pipe
!= NULL
);
1343 /* Acceleration uses firmware, the binary thus can be NULL */
1344 /* assert(binary != NULL); */
1348 #if !defined(HAS_NO_INPUT_SYSTEM)
1349 stream
= pipe
->stream
;
1356 sh_css_metrics_start_binary(&binary
->metrics
);
1358 #if WITH_PC_MONITORING
1359 sh_css_print("PC_MONITORING: %s() -- binary id = %d , "
1360 "enable_dvs_envelope = %d\n",
1361 __func__
, binary
->info
->sp
.id
,
1362 binary
->info
->sp
.enable
.dvs_envelope
);
1363 input_frame_info(binary
->in_frame_info
);
1365 if (binary
&& binary
->info
->sp
.pipeline
.mode
== IA_CSS_BINARY_MODE_VIDEO
)
1366 sh_binary_running
= true;
1369 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1370 if (stream
->reconfigure_css_rx
) {
1371 ia_css_isys_rx_configure(&pipe
->stream
->csi_rx_config
,
1372 pipe
->stream
->config
.mode
);
1373 stream
->reconfigure_css_rx
= false;
1378 /* start the copy function on the SP */
1379 static enum ia_css_err
1380 start_copy_on_sp(struct ia_css_pipe
*pipe
,
1381 struct ia_css_frame
*out_frame
)
1385 assert(pipe
!= NULL
);
1386 assert(pipe
->stream
!= NULL
);
1388 if ((pipe
== NULL
) || (pipe
->stream
== NULL
))
1389 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1391 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1392 if (pipe
->stream
->reconfigure_css_rx
)
1393 ia_css_isys_rx_disable();
1396 if (pipe
->stream
->config
.input_config
.format
!= IA_CSS_STREAM_FORMAT_BINARY_8
)
1397 return IA_CSS_ERR_INTERNAL_ERROR
;
1398 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe
), out_frame
, pipe
->stream
->config
.pixels_per_clock
== 2);
1400 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1401 if (pipe
->stream
->reconfigure_css_rx
) {
1402 ia_css_isys_rx_configure(&pipe
->stream
->csi_rx_config
, pipe
->stream
->config
.mode
);
1403 pipe
->stream
->reconfigure_css_rx
= false;
1407 return IA_CSS_SUCCESS
;
1410 void sh_css_binary_args_reset(struct sh_css_binary_args
*args
)
1415 for (i
= 0; i
< NUM_VIDEO_TNR_FRAMES
; i
++)
1417 for (i
= 0; i
< NUM_TNR_FRAMES
; i
++)
1419 args
->tnr_frames
[i
] = NULL
;
1420 for (i
= 0; i
< MAX_NUM_VIDEO_DELAY_FRAMES
; i
++)
1421 args
->delay_frames
[i
] = NULL
;
1422 args
->in_frame
= NULL
;
1423 for (i
= 0; i
< IA_CSS_BINARY_MAX_OUTPUT_PORTS
; i
++)
1424 args
->out_frame
[i
] = NULL
;
1425 args
->out_vf_frame
= NULL
;
1426 args
->copy_vf
= false;
1427 args
->copy_output
= true;
1428 args
->vf_downscale_log2
= 0;
1431 static void start_pipe(
1432 struct ia_css_pipe
*me
,
1433 enum sh_css_pipe_config_override copy_ovrd
,
1434 enum ia_css_input_mode input_mode
)
1436 #if defined(HAS_NO_INPUT_SYSTEM)
1440 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1441 me
, copy_ovrd
, input_mode
);
1443 assert(me
!= NULL
); /* all callers are in this file and call with non null argument */
1445 sh_css_sp_init_pipeline(&me
->pipeline
,
1447 (uint8_t)ia_css_pipe_get_pipe_num(me
),
1448 me
->config
.default_capture_config
.enable_xnr
!= 0,
1449 me
->stream
->config
.pixels_per_clock
== 2,
1450 me
->stream
->config
.continuous
,
1452 me
->required_bds_factor
,
1455 &me
->stream
->config
.metadata_config
,
1456 &me
->stream
->info
.metadata_info
1457 #if !defined(HAS_NO_INPUT_SYSTEM)
1458 ,(input_mode
==IA_CSS_INPUT_MODE_MEMORY
) ?
1460 me
->stream
->config
.source
.port
.port
1463 ,&me
->config
.internal_frame_origin_bqs_on_sctbl
,
1464 me
->stream
->isp_params_configs
1468 if (me
->config
.mode
!= IA_CSS_PIPE_MODE_COPY
) {
1469 struct ia_css_pipeline_stage
*stage
;
1470 stage
= me
->pipeline
.stages
;
1472 me
->pipeline
.current_stage
= stage
;
1473 start_binary(me
, stage
->binary
);
1476 IA_CSS_LEAVE_PRIVATE("void");
1480 sh_css_invalidate_shading_tables(struct ia_css_stream
*stream
)
1483 assert(stream
!= NULL
);
1485 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
1486 "sh_css_invalidate_shading_tables() enter:\n");
1488 for (i
=0; i
<stream
->num_pipes
; i
++) {
1489 assert(stream
->pipes
[i
] != NULL
);
1490 sh_css_pipe_free_shading_table(stream
->pipes
[i
]);
1493 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
1494 "sh_css_invalidate_shading_tables() leave: return_void\n");
1499 enable_interrupts(enum ia_css_irq_type irq_type
)
1501 #ifdef USE_INPUT_SYSTEM_VERSION_2
1502 mipi_port_ID_t port
;
1504 bool enable_pulse
= irq_type
!= IA_CSS_IRQ_TYPE_EDGE
;
1505 IA_CSS_ENTER_PRIVATE("");
1506 /* Enable IRQ on the SP which signals that SP goes to idle
1507 * (aka ready state) */
1508 cnd_sp_irq_enable(SP0_ID
, true);
1509 /* Set the IRQ device 0 to either level or pulse */
1510 irq_enable_pulse(IRQ0_ID
, enable_pulse
);
1512 cnd_virq_enable_channel(virq_sp
, true);
1514 /* Enable SW interrupt 0, this is used to signal ISYS events */
1515 cnd_virq_enable_channel(
1516 (virq_id_t
)(IRQ_SW_CHANNEL0_ID
+ IRQ_SW_CHANNEL_OFFSET
),
1518 /* Enable SW interrupt 1, this is used to signal PSYS events */
1519 cnd_virq_enable_channel(
1520 (virq_id_t
)(IRQ_SW_CHANNEL1_ID
+ IRQ_SW_CHANNEL_OFFSET
),
1522 #if !defined(HAS_IRQ_MAP_VERSION_2)
1523 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1524 cnd_virq_enable_channel(
1525 (virq_id_t
)(IRQ_SW_CHANNEL2_ID
+ IRQ_SW_CHANNEL_OFFSET
),
1530 #ifdef USE_INPUT_SYSTEM_VERSION_2
1531 for (port
= 0; port
< N_MIPI_PORT_ID
; port
++)
1532 ia_css_isys_rx_enable_all_interrupts(port
);
1535 IA_CSS_LEAVE_PRIVATE("");
1540 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info
*fw
,
1541 const char * program
,
1542 ia_css_spctrl_cfg
*spctrl_cfg
)
1544 if((fw
== NULL
)||(spctrl_cfg
== NULL
))
1546 spctrl_cfg
->sp_entry
= 0;
1547 spctrl_cfg
->program_name
= (char *)(program
);
1549 spctrl_cfg
->ddr_data_offset
= fw
->blob
.data_source
;
1550 spctrl_cfg
->dmem_data_addr
= fw
->blob
.data_target
;
1551 spctrl_cfg
->dmem_bss_addr
= fw
->blob
.bss_target
;
1552 spctrl_cfg
->data_size
= fw
->blob
.data_size
;
1553 spctrl_cfg
->bss_size
= fw
->blob
.bss_size
;
1555 spctrl_cfg
->spctrl_config_dmem_addr
= fw
->info
.sp
.init_dmem_data
;
1556 spctrl_cfg
->spctrl_state_dmem_addr
= fw
->info
.sp
.sw_state
;
1558 spctrl_cfg
->code_size
= fw
->blob
.size
;
1559 spctrl_cfg
->code
= fw
->blob
.code
;
1560 spctrl_cfg
->sp_entry
= fw
->info
.sp
.sp_entry
; /* entry function ptr on SP */
1565 ia_css_unload_firmware(void)
1567 if (sh_css_num_binaries
)
1569 /* we have already loaded before so get rid of the old stuff */
1570 ia_css_binary_uninit();
1571 sh_css_unload_firmware();
1573 fw_explicitly_loaded
= false;
1577 ia_css_reset_defaults(struct sh_css
* css
)
1579 struct sh_css default_css
;
1581 /* Reset everything to zero */
1582 memset(&default_css
, 0, sizeof(default_css
));
1584 /* Initialize the non zero values*/
1585 default_css
.check_system_idle
= true;
1586 default_css
.num_cont_raw_frames
= NUM_CONTINUOUS_FRAMES
;
1588 /* All should be 0: but memset does it already.
1589 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1592 default_css
.irq_type
= IA_CSS_IRQ_TYPE_EDGE
;
1594 /*Set the defaults to the output */
1599 ia_css_check_firmware_version(const struct ia_css_fw
*fw
)
1601 bool retval
= false;
1604 retval
= sh_css_check_firmware_version(fw
->data
);
1610 ia_css_load_firmware(const struct ia_css_env
*env
,
1611 const struct ia_css_fw
*fw
)
1613 enum ia_css_err err
;
1616 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1618 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1620 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_load_firmware() enter\n");
1622 /* make sure we initialize my_css */
1623 if (my_css
.flush
!= env
->cpu_mem_env
.flush
) {
1624 ia_css_reset_defaults(&my_css
);
1625 my_css
.flush
= env
->cpu_mem_env
.flush
;
1628 ia_css_unload_firmware(); /* in case we are called twice */
1629 err
= sh_css_load_firmware(fw
->data
, fw
->bytes
);
1630 if (err
== IA_CSS_SUCCESS
) {
1631 err
= ia_css_binary_init_infos();
1632 if (err
== IA_CSS_SUCCESS
)
1633 fw_explicitly_loaded
= true;
1636 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_load_firmware() leave \n");
1641 ia_css_init(const struct ia_css_env
*env
,
1642 const struct ia_css_fw
*fw
,
1643 uint32_t mmu_l1_base
,
1644 enum ia_css_irq_type irq_type
)
1646 enum ia_css_err err
;
1647 ia_css_spctrl_cfg spctrl_cfg
;
1649 void (*flush_func
)(struct ia_css_acc_fw
*fw
);
1650 hrt_data select
, enable
;
1653 * The C99 standard does not specify the exact object representation of structs;
1654 * the representation is compiler dependent.
1656 * The structs that are communicated between host and SP/ISP should have the
1657 * exact same object representation. The compiler that is used to compile the
1658 * firmware is hivecc.
1660 * To check if a different compiler, used to compile a host application, uses
1661 * another object representation, macros are defined specifying the size of
1662 * the structs as expected by the firmware.
1664 * A host application shall verify that a sizeof( ) of the struct is equal to
1665 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1666 * equal, functionality will break.
1668 /* Check struct sh_css_ddr_address_map */
1669 COMPILATION_ERROR_IF( sizeof(struct sh_css_ddr_address_map
) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT
);
1670 /* Check struct host_sp_queues */
1671 COMPILATION_ERROR_IF( sizeof(struct host_sp_queues
) != SIZE_OF_HOST_SP_QUEUES_STRUCT
);
1672 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_desc_s
) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT
);
1673 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_elem_s
) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT
);
1675 /* Check struct host_sp_communication */
1676 COMPILATION_ERROR_IF( sizeof(struct host_sp_communication
) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT
);
1677 COMPILATION_ERROR_IF( sizeof(struct sh_css_event_irq_mask
) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT
);
1679 /* Check struct sh_css_hmm_buffer */
1680 COMPILATION_ERROR_IF( sizeof(struct sh_css_hmm_buffer
) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT
);
1681 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_3a_statistics
) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT
);
1682 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_dvs_statistics
) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT
);
1683 COMPILATION_ERROR_IF( sizeof(struct ia_css_metadata
) != SIZE_OF_IA_CSS_METADATA_STRUCT
);
1685 /* Check struct ia_css_init_dmem_cfg */
1686 COMPILATION_ERROR_IF( sizeof(struct ia_css_sp_init_dmem_cfg
) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT
);
1688 if (fw
== NULL
&& !fw_explicitly_loaded
)
1689 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1691 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1693 sh_css_printf
= env
->print_env
.debug_print
;
1695 IA_CSS_ENTER("void");
1697 flush_func
= env
->cpu_mem_env
.flush
;
1700 ia_css_pipeline_init();
1701 ia_css_queue_map_init();
1703 ia_css_device_access_init(&env
->hw_access_env
);
1705 select
= gpio_reg_load(GPIO0_ID
, _gpio_block_reg_do_select
)
1706 & (~GPIO_FLASH_PIN_MASK
);
1707 enable
= gpio_reg_load(GPIO0_ID
, _gpio_block_reg_do_e
)
1708 | GPIO_FLASH_PIN_MASK
;
1709 sh_css_mmu_set_page_table_base_index(mmu_l1_base
);
1711 my_css_save
.mmu_base
= mmu_l1_base
;
1713 ia_css_save_mmu_base_addr(mmu_l1_base
);
1716 ia_css_reset_defaults(&my_css
);
1718 my_css_save
.driver_env
= *env
;
1719 my_css
.flush
= flush_func
;
1721 err
= ia_css_rmgr_init();
1722 if (err
!= IA_CSS_SUCCESS
) {
1723 IA_CSS_LEAVE_ERR(err
);
1728 IA_CSS_LOG("init: %d", my_css_save_initialized
);
1730 ia_css_save_restore_data_init();
1734 if (!my_css_save_initialized
)
1736 my_css_save_initialized
= true;
1737 my_css_save
.mode
= sh_css_mode_working
;
1738 memset(my_css_save
.stream_seeds
, 0, sizeof(struct sh_css_stream_seed
) * MAX_ACTIVE_STREAMS
);
1739 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized
, my_css_save
.mode
);
1745 /* In case this has been programmed already, update internal
1746 data structure ... DEPRECATED */
1747 my_css
.page_table_base_index
= mmu_get_page_table_base_index(MMU0_ID
);
1750 my_css
.irq_type
= irq_type
;
1752 my_css_save
.irq_type
= irq_type
;
1754 ia_css_save_irq_type(irq_type
);
1756 enable_interrupts(my_css
.irq_type
);
1758 /* configure GPIO to output mode */
1759 gpio_reg_store(GPIO0_ID
, _gpio_block_reg_do_select
, select
);
1760 gpio_reg_store(GPIO0_ID
, _gpio_block_reg_do_e
, enable
);
1761 gpio_reg_store(GPIO0_ID
, _gpio_block_reg_do_0
, 0);
1763 err
= ia_css_refcount_init(REFCOUNT_SIZE
);
1764 if (err
!= IA_CSS_SUCCESS
) {
1765 IA_CSS_LEAVE_ERR(err
);
1768 err
= sh_css_params_init();
1769 if (err
!= IA_CSS_SUCCESS
) {
1770 IA_CSS_LEAVE_ERR(err
);
1775 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1776 err
= sh_css_load_firmware(fw
->data
, fw
->bytes
);
1777 if (err
!= IA_CSS_SUCCESS
) {
1778 IA_CSS_LEAVE_ERR(err
);
1781 err
= ia_css_binary_init_infos();
1782 if (err
!= IA_CSS_SUCCESS
) {
1783 IA_CSS_LEAVE_ERR(err
);
1786 fw_explicitly_loaded
= false;
1788 my_css_save
.loaded_fw
= (struct ia_css_fw
*)fw
;
1791 if(!sh_css_setup_spctrl_config(&sh_css_sp_fw
,SP_PROG_NAME
,&spctrl_cfg
))
1792 return IA_CSS_ERR_INTERNAL_ERROR
;
1794 err
= ia_css_spctrl_load_fw(SP0_ID
, &spctrl_cfg
);
1795 if (err
!= IA_CSS_SUCCESS
) {
1796 IA_CSS_LEAVE_ERR(err
);
1800 #if WITH_PC_MONITORING
1801 if (!thread_alive
) {
1803 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1805 spying_thread_create();
1808 if (!sh_css_hrt_system_is_idle()) {
1809 IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE
);
1810 return IA_CSS_ERR_SYSTEM_NOT_IDLE
;
1812 /* can be called here, queuing works, but:
1813 - when sp is started later, it will wipe queued items
1814 so for now we leave it for later and make sure
1815 updates are not called to frequently.
1816 sh_css_init_buffer_queues();
1819 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1820 #if defined(USE_INPUT_SYSTEM_VERSION_2)
1821 gp_device_reg_store(GP_DEVICE0_ID
, _REG_GP_SWITCH_ISYS2401_ADDR
, 0);
1822 #elif defined (USE_INPUT_SYSTEM_VERSION_2401)
1823 gp_device_reg_store(GP_DEVICE0_ID
, _REG_GP_SWITCH_ISYS2401_ADDR
, 1);
1827 #if !defined(HAS_NO_INPUT_SYSTEM)
1828 dma_set_max_burst_size(DMA0_ID
, HIVE_DMA_BUS_DDR_CONN
,
1829 ISP_DMA_MAX_BURST_LENGTH
);
1831 if(ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR
)
1832 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
1835 sh_css_params_map_and_store_default_gdc_lut();
1837 IA_CSS_LEAVE_ERR(err
);
1841 enum ia_css_err
ia_css_suspend(void)
1844 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_suspend() enter\n");
1845 my_css_save
.mode
= sh_css_mode_suspend
;
1846 for(i
=0;i
<MAX_ACTIVE_STREAMS
;i
++)
1847 if (my_css_save
.stream_seeds
[i
].stream
!= NULL
)
1849 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "==*> unloading seed %d (%p)\n", i
, my_css_save
.stream_seeds
[i
].stream
);
1850 ia_css_stream_unload(my_css_save
.stream_seeds
[i
].stream
);
1852 my_css_save
.mode
= sh_css_mode_working
;
1855 for(i
=0;i
<MAX_ACTIVE_STREAMS
;i
++)
1856 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "==*> after 1: seed %d (%p)\n", i
, my_css_save
.stream_seeds
[i
].stream
);
1857 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_suspend() leave\n");
1858 return IA_CSS_SUCCESS
;
1865 enum ia_css_err err
;
1866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_resume() enter: void\n");
1868 err
= ia_css_init(&(my_css_save
.driver_env
), my_css_save
.loaded_fw
, my_css_save
.mmu_base
, my_css_save
.irq_type
);
1869 if (err
!= IA_CSS_SUCCESS
)
1871 err
= ia_css_start_sp();
1872 if (err
!= IA_CSS_SUCCESS
)
1874 my_css_save
.mode
= sh_css_mode_resume
;
1875 for(i
=0;i
<MAX_ACTIVE_STREAMS
;i
++)
1877 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "==*> seed stream %p\n", my_css_save
.stream_seeds
[i
].stream
);
1878 if (my_css_save
.stream_seeds
[i
].stream
!= NULL
)
1880 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "==*> loading seed %d\n", i
);
1881 err
= ia_css_stream_load(my_css_save
.stream_seeds
[i
].stream
);
1882 if (err
!= IA_CSS_SUCCESS
)
1886 ia_css_stream_unload(my_css_save
.stream_seeds
[j
].stream
);
1889 err
= ia_css_stream_start(my_css_save
.stream_seeds
[i
].stream
);
1890 if (err
!= IA_CSS_SUCCESS
)
1894 ia_css_stream_stop(my_css_save
.stream_seeds
[j
].stream
);
1895 ia_css_stream_unload(my_css_save
.stream_seeds
[j
].stream
);
1899 *my_css_save
.stream_seeds
[i
].orig_stream
= my_css_save
.stream_seeds
[i
].stream
;
1900 for(j
=0;j
<my_css_save
.stream_seeds
[i
].num_pipes
;j
++)
1901 *(my_css_save
.stream_seeds
[i
].orig_pipes
[j
]) = my_css_save
.stream_seeds
[i
].pipes
[j
];
1904 my_css_save
.mode
= sh_css_mode_working
;
1905 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_resume() leave: return_void\n");
1906 return IA_CSS_SUCCESS
;
1910 ia_css_enable_isys_event_queue(bool enable
)
1912 if (sh_css_sp_is_running())
1913 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
1914 sh_css_sp_enable_isys_event_queue(enable
);
1915 return IA_CSS_SUCCESS
;
1918 void *sh_css_malloc(size_t size
)
1920 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_malloc() enter: size=%zu\n",size
);
1921 /* FIXME: This first test can probably go away */
1924 if (size
> PAGE_SIZE
)
1925 return vmalloc(size
);
1926 return kmalloc(size
, GFP_KERNEL
);
1929 void *sh_css_calloc(size_t N
, size_t size
)
1933 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_calloc() enter: N=%zu, size=%zu\n",N
,size
);
1935 /* FIXME: this test can probably go away */
1937 p
= sh_css_malloc(N
*size
);
1945 void sh_css_free(void *ptr
)
1947 if (is_vmalloc_addr(ptr
))
1953 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1955 sh_css_flush(struct ia_css_acc_fw
*fw
)
1957 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_flush() enter:\n");
1958 if ((fw
!= NULL
) && (my_css
.flush
!= NULL
))
1962 /* Mapping sp threads. Currently, this is done when a stream is created and
1963 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1964 * doing it from stream_create since we could run out of sp threads due to
1965 * allocation on inactive pipelines. */
1966 static enum ia_css_err
1967 map_sp_threads(struct ia_css_stream
*stream
, bool map
)
1969 struct ia_css_pipe
*main_pipe
= NULL
;
1970 struct ia_css_pipe
*copy_pipe
= NULL
;
1971 struct ia_css_pipe
*capture_pipe
= NULL
;
1972 struct ia_css_pipe
*acc_pipe
= NULL
;
1973 enum ia_css_err err
= IA_CSS_SUCCESS
;
1974 enum ia_css_pipe_id pipe_id
;
1976 assert(stream
!= NULL
);
1977 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1978 stream
, map
? "true" : "false");
1980 if (stream
== NULL
) {
1981 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
1982 return IA_CSS_ERR_INVALID_ARGUMENTS
;
1985 main_pipe
= stream
->last_pipe
;
1986 pipe_id
= main_pipe
->mode
;
1988 ia_css_pipeline_map(main_pipe
->pipe_num
, map
);
1991 case IA_CSS_PIPE_ID_PREVIEW
:
1992 copy_pipe
= main_pipe
->pipe_settings
.preview
.copy_pipe
;
1993 capture_pipe
= main_pipe
->pipe_settings
.preview
.capture_pipe
;
1994 acc_pipe
= main_pipe
->pipe_settings
.preview
.acc_pipe
;
1997 case IA_CSS_PIPE_ID_VIDEO
:
1998 copy_pipe
= main_pipe
->pipe_settings
.video
.copy_pipe
;
1999 capture_pipe
= main_pipe
->pipe_settings
.video
.capture_pipe
;
2002 case IA_CSS_PIPE_ID_CAPTURE
:
2003 case IA_CSS_PIPE_ID_ACC
:
2009 ia_css_pipeline_map(acc_pipe
->pipe_num
, map
);
2013 ia_css_pipeline_map(capture_pipe
->pipe_num
, map
);
2016 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
2018 ia_css_pipeline_map(copy_pipe
->pipe_num
, map
);
2020 /* DH regular multi pipe - not continuous mode: map the next pipes too */
2021 if (!stream
->config
.continuous
) {
2023 for (i
= 1; i
< stream
->num_pipes
; i
++)
2024 ia_css_pipeline_map(stream
->pipes
[i
]->pipe_num
, map
);
2027 IA_CSS_LEAVE_ERR_PRIVATE(err
);
2031 /* creates a host pipeline skeleton for all pipes in a stream. Called during
2033 static enum ia_css_err
2034 create_host_pipeline_structure(struct ia_css_stream
*stream
)
2036 struct ia_css_pipe
*copy_pipe
= NULL
, *capture_pipe
= NULL
;
2037 struct ia_css_pipe
*acc_pipe
= NULL
;
2038 enum ia_css_pipe_id pipe_id
;
2039 struct ia_css_pipe
*main_pipe
= NULL
;
2040 enum ia_css_err err
= IA_CSS_SUCCESS
;
2041 unsigned int copy_pipe_delay
= 0,
2042 capture_pipe_delay
= 0;
2044 assert(stream
!= NULL
);
2045 IA_CSS_ENTER_PRIVATE("stream = %p", stream
);
2047 if (stream
== NULL
) {
2048 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
2049 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2052 main_pipe
= stream
->last_pipe
;
2053 assert(main_pipe
!= NULL
);
2054 if (main_pipe
== NULL
) {
2055 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
2056 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2059 pipe_id
= main_pipe
->mode
;
2062 case IA_CSS_PIPE_ID_PREVIEW
:
2063 copy_pipe
= main_pipe
->pipe_settings
.preview
.copy_pipe
;
2064 copy_pipe_delay
= main_pipe
->dvs_frame_delay
;
2065 capture_pipe
= main_pipe
->pipe_settings
.preview
.capture_pipe
;
2066 capture_pipe_delay
= IA_CSS_FRAME_DELAY_0
;
2067 acc_pipe
= main_pipe
->pipe_settings
.preview
.acc_pipe
;
2068 err
= ia_css_pipeline_create(&main_pipe
->pipeline
, main_pipe
->mode
, main_pipe
->pipe_num
, main_pipe
->dvs_frame_delay
);
2071 case IA_CSS_PIPE_ID_VIDEO
:
2072 copy_pipe
= main_pipe
->pipe_settings
.video
.copy_pipe
;
2073 copy_pipe_delay
= main_pipe
->dvs_frame_delay
;
2074 capture_pipe
= main_pipe
->pipe_settings
.video
.capture_pipe
;
2075 capture_pipe_delay
= IA_CSS_FRAME_DELAY_0
;
2076 err
= ia_css_pipeline_create(&main_pipe
->pipeline
, main_pipe
->mode
, main_pipe
->pipe_num
, main_pipe
->dvs_frame_delay
);
2079 case IA_CSS_PIPE_ID_CAPTURE
:
2080 capture_pipe
= main_pipe
;
2081 capture_pipe_delay
= main_pipe
->dvs_frame_delay
;
2084 case IA_CSS_PIPE_ID_YUVPP
:
2085 err
= ia_css_pipeline_create(&main_pipe
->pipeline
, main_pipe
->mode
,
2086 main_pipe
->pipe_num
, main_pipe
->dvs_frame_delay
);
2089 case IA_CSS_PIPE_ID_ACC
:
2090 err
= ia_css_pipeline_create(&main_pipe
->pipeline
, main_pipe
->mode
, main_pipe
->pipe_num
, main_pipe
->dvs_frame_delay
);
2094 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
2097 if ((IA_CSS_SUCCESS
== err
) && copy_pipe
) {
2098 err
= ia_css_pipeline_create(©_pipe
->pipeline
,
2100 copy_pipe
->pipe_num
,
2104 if ((IA_CSS_SUCCESS
== err
) && capture_pipe
) {
2105 err
= ia_css_pipeline_create(&capture_pipe
->pipeline
,
2107 capture_pipe
->pipe_num
,
2108 capture_pipe_delay
);
2111 if ((IA_CSS_SUCCESS
== err
) && acc_pipe
) {
2112 err
= ia_css_pipeline_create(&acc_pipe
->pipeline
, acc_pipe
->mode
, acc_pipe
->pipe_num
, main_pipe
->dvs_frame_delay
);
2115 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2116 if (!stream
->config
.continuous
) {
2118 for (i
= 1; i
< stream
->num_pipes
&& IA_CSS_SUCCESS
== err
; i
++) {
2119 main_pipe
= stream
->pipes
[i
];
2120 err
= ia_css_pipeline_create(&main_pipe
->pipeline
,
2122 main_pipe
->pipe_num
,
2123 main_pipe
->dvs_frame_delay
);
2127 IA_CSS_LEAVE_ERR_PRIVATE(err
);
2131 /* creates a host pipeline for all pipes in a stream. Called during
2133 static enum ia_css_err
2134 create_host_pipeline(struct ia_css_stream
*stream
)
2136 struct ia_css_pipe
*copy_pipe
= NULL
, *capture_pipe
= NULL
;
2137 struct ia_css_pipe
*acc_pipe
= NULL
;
2138 enum ia_css_pipe_id pipe_id
;
2139 struct ia_css_pipe
*main_pipe
= NULL
;
2140 enum ia_css_err err
= IA_CSS_SUCCESS
;
2141 unsigned max_input_width
= 0;
2143 IA_CSS_ENTER_PRIVATE("stream = %p", stream
);
2144 if (stream
== NULL
) {
2145 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
2146 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2149 main_pipe
= stream
->last_pipe
;
2150 pipe_id
= main_pipe
->mode
;
2152 /* No continuous frame allocation for capture pipe. It uses the
2153 * "main" pipe's frames. */
2154 if ((pipe_id
== IA_CSS_PIPE_ID_PREVIEW
) ||
2155 (pipe_id
== IA_CSS_PIPE_ID_VIDEO
)) {
2156 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2157 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2158 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2159 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2160 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2162 if (stream
->config
.continuous
||
2163 (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
&& stream
->config
.mode
!= IA_CSS_INPUT_MODE_MEMORY
)) {
2164 err
= alloc_continuous_frames(main_pipe
, true);
2165 if (err
!= IA_CSS_SUCCESS
)
2171 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2172 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2173 if (pipe_id
!= IA_CSS_PIPE_ID_ACC
) {
2174 err
= allocate_mipi_frames(main_pipe
, &stream
->info
);
2175 if (err
!= IA_CSS_SUCCESS
)
2178 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2179 if ((pipe_id
!= IA_CSS_PIPE_ID_ACC
) &&
2180 (main_pipe
->config
.mode
!= IA_CSS_PIPE_MODE_COPY
)) {
2181 err
= allocate_mipi_frames(main_pipe
, &stream
->info
);
2182 if (err
!= IA_CSS_SUCCESS
)
2188 case IA_CSS_PIPE_ID_PREVIEW
:
2189 copy_pipe
= main_pipe
->pipe_settings
.preview
.copy_pipe
;
2190 capture_pipe
= main_pipe
->pipe_settings
.preview
.capture_pipe
;
2191 acc_pipe
= main_pipe
->pipe_settings
.preview
.acc_pipe
;
2193 main_pipe
->pipe_settings
.preview
.preview_binary
.info
->sp
.input
.max_width
;
2195 err
= create_host_preview_pipeline(main_pipe
);
2196 if (err
!= IA_CSS_SUCCESS
)
2201 case IA_CSS_PIPE_ID_VIDEO
:
2202 copy_pipe
= main_pipe
->pipe_settings
.video
.copy_pipe
;
2203 capture_pipe
= main_pipe
->pipe_settings
.video
.capture_pipe
;
2205 main_pipe
->pipe_settings
.video
.video_binary
.info
->sp
.input
.max_width
;
2207 err
= create_host_video_pipeline(main_pipe
);
2208 if (err
!= IA_CSS_SUCCESS
)
2213 case IA_CSS_PIPE_ID_CAPTURE
:
2214 capture_pipe
= main_pipe
;
2218 case IA_CSS_PIPE_ID_YUVPP
:
2219 err
= create_host_yuvpp_pipeline(main_pipe
);
2220 if (err
!= IA_CSS_SUCCESS
)
2225 case IA_CSS_PIPE_ID_ACC
:
2226 err
= create_host_acc_pipeline(main_pipe
);
2227 if (err
!= IA_CSS_SUCCESS
)
2232 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
2234 if (err
!= IA_CSS_SUCCESS
)
2238 err
= create_host_copy_pipeline(copy_pipe
, max_input_width
,
2239 main_pipe
->continuous_frames
[0]);
2240 if (err
!= IA_CSS_SUCCESS
)
2245 err
= create_host_capture_pipeline(capture_pipe
);
2246 if (err
!= IA_CSS_SUCCESS
)
2251 err
= create_host_acc_pipeline(acc_pipe
);
2252 if (err
!= IA_CSS_SUCCESS
)
2256 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2257 if (!stream
->config
.continuous
) {
2259 for (i
= 1; i
< stream
->num_pipes
&& IA_CSS_SUCCESS
== err
; i
++) {
2260 switch (stream
->pipes
[i
]->mode
) {
2261 case IA_CSS_PIPE_ID_PREVIEW
:
2262 err
= create_host_preview_pipeline(stream
->pipes
[i
]);
2264 case IA_CSS_PIPE_ID_VIDEO
:
2265 err
= create_host_video_pipeline(stream
->pipes
[i
]);
2267 case IA_CSS_PIPE_ID_CAPTURE
:
2268 err
= create_host_capture_pipeline(stream
->pipes
[i
]);
2270 case IA_CSS_PIPE_ID_YUVPP
:
2271 err
= create_host_yuvpp_pipeline(stream
->pipes
[i
]);
2273 case IA_CSS_PIPE_ID_ACC
:
2274 err
= create_host_acc_pipeline(stream
->pipes
[i
]);
2277 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
2279 if (err
!= IA_CSS_SUCCESS
)
2285 IA_CSS_LEAVE_ERR_PRIVATE(err
);
2289 static enum ia_css_err
2290 init_pipe_defaults(enum ia_css_pipe_mode mode
,
2291 struct ia_css_pipe
*pipe
,
2294 static struct ia_css_pipe default_pipe
= IA_CSS_DEFAULT_PIPE
;
2295 static struct ia_css_preview_settings prev
= IA_CSS_DEFAULT_PREVIEW_SETTINGS
;
2296 static struct ia_css_capture_settings capt
= IA_CSS_DEFAULT_CAPTURE_SETTINGS
;
2297 static struct ia_css_video_settings video
= IA_CSS_DEFAULT_VIDEO_SETTINGS
;
2298 static struct ia_css_yuvpp_settings yuvpp
= IA_CSS_DEFAULT_YUVPP_SETTINGS
;
2301 IA_CSS_ERROR("NULL pipe parameter");
2302 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2305 /* Initialize pipe to pre-defined defaults */
2306 *pipe
= default_pipe
;
2308 /* TODO: JB should not be needed, but temporary backward reference */
2310 case IA_CSS_PIPE_MODE_PREVIEW
:
2311 pipe
->mode
= IA_CSS_PIPE_ID_PREVIEW
;
2312 pipe
->pipe_settings
.preview
= prev
;
2314 case IA_CSS_PIPE_MODE_CAPTURE
:
2316 pipe
->mode
= IA_CSS_PIPE_ID_COPY
;
2318 pipe
->mode
= IA_CSS_PIPE_ID_CAPTURE
;
2320 pipe
->pipe_settings
.capture
= capt
;
2322 case IA_CSS_PIPE_MODE_VIDEO
:
2323 pipe
->mode
= IA_CSS_PIPE_ID_VIDEO
;
2324 pipe
->pipe_settings
.video
= video
;
2326 case IA_CSS_PIPE_MODE_ACC
:
2327 pipe
->mode
= IA_CSS_PIPE_ID_ACC
;
2329 case IA_CSS_PIPE_MODE_COPY
:
2330 pipe
->mode
= IA_CSS_PIPE_ID_CAPTURE
;
2332 case IA_CSS_PIPE_MODE_YUVPP
:
2333 pipe
->mode
= IA_CSS_PIPE_ID_YUVPP
;
2334 pipe
->pipe_settings
.yuvpp
= yuvpp
;
2337 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2340 return IA_CSS_SUCCESS
;
2344 pipe_global_init(void)
2348 my_css
.pipe_counter
= 0;
2349 for (i
= 0; i
< IA_CSS_PIPELINE_NUM_MAX
; i
++) {
2350 my_css
.all_pipes
[i
] = NULL
;
2354 static enum ia_css_err
2355 pipe_generate_pipe_num(const struct ia_css_pipe
*pipe
, unsigned int *pipe_number
)
2357 const uint8_t INVALID_PIPE_NUM
= (uint8_t)~(0);
2358 uint8_t pipe_num
= INVALID_PIPE_NUM
;
2362 IA_CSS_ERROR("NULL pipe parameter");
2363 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2366 /* Assign a new pipe_num .... search for empty place */
2367 for (i
= 0; i
< IA_CSS_PIPELINE_NUM_MAX
; i
++) {
2368 if (my_css
.all_pipes
[i
] == NULL
) {
2369 /*position is reserved */
2370 my_css
.all_pipes
[i
] = (struct ia_css_pipe
*)pipe
;
2375 if (pipe_num
== INVALID_PIPE_NUM
) {
2376 /* Max number of pipes already allocated */
2377 IA_CSS_ERROR("Max number of pipes already created");
2378 return IA_CSS_ERR_RESOURCE_EXHAUSTED
;
2381 my_css
.pipe_counter
++;
2383 IA_CSS_LOG("pipe_num (%d)", pipe_num
);
2385 *pipe_number
= pipe_num
;
2386 return IA_CSS_SUCCESS
;
2390 pipe_release_pipe_num(unsigned int pipe_num
)
2392 my_css
.all_pipes
[pipe_num
] = NULL
;
2393 my_css
.pipe_counter
--;
2394 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
2395 "pipe_release_pipe_num (%d)\n", pipe_num
);
2398 static enum ia_css_err
2399 create_pipe(enum ia_css_pipe_mode mode
,
2400 struct ia_css_pipe
**pipe
,
2403 enum ia_css_err err
= IA_CSS_SUCCESS
;
2404 struct ia_css_pipe
*me
;
2407 IA_CSS_ERROR("NULL pipe parameter");
2408 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2411 me
= kmalloc(sizeof(*me
), GFP_KERNEL
);
2413 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
2415 err
= init_pipe_defaults(mode
, me
, copy_pipe
);
2416 if (err
!= IA_CSS_SUCCESS
) {
2421 err
= pipe_generate_pipe_num(me
, &(me
->pipe_num
));
2422 if (err
!= IA_CSS_SUCCESS
) {
2428 return IA_CSS_SUCCESS
;
2431 struct ia_css_pipe
*
2432 find_pipe_by_num(uint32_t pipe_num
)
2435 for (i
= 0; i
< IA_CSS_PIPELINE_NUM_MAX
; i
++){
2436 if (my_css
.all_pipes
[i
] &&
2437 ia_css_pipe_get_pipe_num(my_css
.all_pipes
[i
]) == pipe_num
) {
2438 return my_css
.all_pipes
[i
];
2444 static void sh_css_pipe_free_acc_binaries (
2445 struct ia_css_pipe
*pipe
)
2447 struct ia_css_pipeline
*pipeline
;
2448 struct ia_css_pipeline_stage
*stage
;
2450 assert(pipe
!= NULL
);
2452 IA_CSS_ERROR("NULL input pointer");
2455 pipeline
= &pipe
->pipeline
;
2457 /* loop through the stages and unload them */
2458 for (stage
= pipeline
->stages
; stage
; stage
= stage
->next
) {
2459 struct ia_css_fw_info
*firmware
= (struct ia_css_fw_info
*)
2462 ia_css_pipe_unload_extension(pipe
, firmware
);
2467 ia_css_pipe_destroy(struct ia_css_pipe
*pipe
)
2469 enum ia_css_err err
= IA_CSS_SUCCESS
;
2470 IA_CSS_ENTER("pipe = %p", pipe
);
2473 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
2474 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2477 if (pipe
->stream
!= NULL
) {
2478 IA_CSS_LOG("ia_css_stream_destroy not called!");
2479 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
2480 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2483 switch (pipe
->config
.mode
) {
2484 case IA_CSS_PIPE_MODE_PREVIEW
:
2485 /* need to take into account that this function is also called
2486 on the internal copy pipe */
2487 if (pipe
->mode
== IA_CSS_PIPE_ID_PREVIEW
) {
2488 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES
,
2489 pipe
->continuous_frames
);
2490 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES
,
2491 pipe
->cont_md_buffers
);
2492 if (pipe
->pipe_settings
.preview
.copy_pipe
) {
2493 err
= ia_css_pipe_destroy(pipe
->pipe_settings
.preview
.copy_pipe
);
2494 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_pipe_destroy(): "
2495 "destroyed internal copy pipe err=%d\n", err
);
2499 case IA_CSS_PIPE_MODE_VIDEO
:
2500 if (pipe
->mode
== IA_CSS_PIPE_ID_VIDEO
) {
2501 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES
,
2502 pipe
->continuous_frames
);
2503 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES
,
2504 pipe
->cont_md_buffers
);
2505 if (pipe
->pipe_settings
.video
.copy_pipe
) {
2506 err
= ia_css_pipe_destroy(pipe
->pipe_settings
.video
.copy_pipe
);
2507 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_pipe_destroy(): "
2508 "destroyed internal copy pipe err=%d\n", err
);
2512 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES
, pipe
->pipe_settings
.video
.tnr_frames
);
2514 ia_css_frame_free_multiple(NUM_TNR_FRAMES
, pipe
->pipe_settings
.video
.tnr_frames
);
2516 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES
, pipe
->pipe_settings
.video
.delay_frames
);
2518 case IA_CSS_PIPE_MODE_CAPTURE
:
2519 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES
, pipe
->pipe_settings
.capture
.delay_frames
);
2521 case IA_CSS_PIPE_MODE_ACC
:
2522 sh_css_pipe_free_acc_binaries(pipe
);
2524 case IA_CSS_PIPE_MODE_COPY
:
2526 case IA_CSS_PIPE_MODE_YUVPP
:
2530 sh_css_params_free_gdc_lut(pipe
->scaler_pp_lut
);
2531 pipe
->scaler_pp_lut
= mmgr_NULL
;
2533 my_css
.active_pipes
[ia_css_pipe_get_pipe_num(pipe
)] = NULL
;
2534 sh_css_pipe_free_shading_table(pipe
);
2536 ia_css_pipeline_destroy(&pipe
->pipeline
);
2537 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe
));
2539 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2540 if (pipe
->config
.acc_extension
) {
2541 ia_css_pipe_unload_extension(pipe
, pipe
->config
.acc_extension
);
2544 IA_CSS_LEAVE("err = %d", err
);
2551 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_uninit() enter: void\n");
2552 #if WITH_PC_MONITORING
2553 sh_css_print("PC_MONITORING: %s() -- started\n", __func__
);
2554 print_pc_histogram();
2557 sh_css_params_free_default_gdc_lut();
2560 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2561 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2562 /* cleanup generic data */
2563 sh_css_params_uninit();
2564 ia_css_refcount_uninit();
2566 ia_css_rmgr_uninit();
2568 #if !defined(HAS_NO_INPUT_FORMATTER)
2569 /* needed for reprogramming the inputformatter after power cycle of css */
2570 ifmtr_set_if_blocking_mode_reset
= true;
2573 if (fw_explicitly_loaded
== false) {
2574 ia_css_unload_firmware();
2576 ia_css_spctrl_unload_fw(SP0_ID
);
2577 sh_css_sp_set_sp_running(false);
2578 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2579 /* check and free any remaining mipi frames */
2580 free_mipi_frames(NULL
);
2583 sh_css_sp_reset_global_vars();
2585 #if !defined(HAS_NO_INPUT_SYSTEM)
2586 ia_css_isys_uninit();
2589 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_uninit() leave: return_void\n");
2592 #if defined(HAS_IRQ_MAP_VERSION_2)
2593 enum ia_css_err
ia_css_irq_translate(
2594 unsigned int *irq_infos
)
2597 enum hrt_isp_css_irq_status status
= hrt_isp_css_irq_status_more_irqs
;
2598 unsigned int infos
= 0;
2600 /* irq_infos can be NULL, but that would make the function useless */
2601 /* assert(irq_infos != NULL); */
2602 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_irq_translate() enter: irq_infos=%p\n",irq_infos
);
2604 while (status
== hrt_isp_css_irq_status_more_irqs
) {
2605 status
= virq_get_channel_id(&irq
);
2606 if (status
== hrt_isp_css_irq_status_error
)
2607 return IA_CSS_ERR_INTERNAL_ERROR
;
2609 #if WITH_PC_MONITORING
2610 sh_css_print("PC_MONITORING: %s() irq = %d, "
2611 "sh_binary_running set to 0\n", __func__
, irq
);
2612 sh_binary_running
= 0 ;
2617 /* When SP goes to idle, info is available in the
2619 infos
|= IA_CSS_IRQ_INFO_EVENTS_READY
;
2623 #if !defined(HAS_NO_INPUT_SYSTEM)
2625 infos
|= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF
;
2628 infos
|= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF
;
2631 infos
|= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR
;
2634 #if !defined(HAS_NO_INPUT_FORMATTER)
2636 infos
|= IA_CSS_IRQ_INFO_IF_ERROR
;
2640 infos
|= IA_CSS_IRQ_INFO_DMA_ERROR
;
2643 infos
|= sh_css_get_sw_interrupt_value(0);
2646 infos
|= sh_css_get_sw_interrupt_value(1);
2647 /* pqiao TODO: also assumption here */
2657 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_irq_translate() "
2658 "leave: irq_infos=%u\n", infos
);
2660 return IA_CSS_SUCCESS
;
2663 enum ia_css_err
ia_css_irq_enable(
2664 enum ia_css_irq_info info
,
2667 virq_id_t irq
= N_virq_id
;
2668 IA_CSS_ENTER("info=%d, enable=%d", info
, enable
);
2671 #if !defined(HAS_NO_INPUT_FORMATTER)
2672 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF
:
2673 irq
= virq_isys_sof
;
2675 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF
:
2676 irq
= virq_isys_eof
;
2678 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR
:
2679 irq
= virq_isys_csi
;
2682 #if !defined(HAS_NO_INPUT_FORMATTER)
2683 case IA_CSS_IRQ_INFO_IF_ERROR
:
2684 irq
= virq_ifmt0_id
;
2687 case IA_CSS_IRQ_INFO_DMA_ERROR
:
2690 case IA_CSS_IRQ_INFO_SW_0
:
2691 irq
= virq_sw_pin_0
;
2693 case IA_CSS_IRQ_INFO_SW_1
:
2694 irq
= virq_sw_pin_1
;
2697 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
2698 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2701 cnd_virq_enable_channel(irq
, enable
);
2703 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS
);
2704 return IA_CSS_SUCCESS
;
2708 #error "sh_css.c: IRQ MAP must be one of \
2709 {IRQ_MAP_VERSION_2}"
2713 sh_css_get_sw_interrupt_value(unsigned int irq
)
2715 unsigned int irq_value
;
2716 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_get_sw_interrupt_value() enter: irq=%d\n",irq
);
2717 irq_value
= sh_css_sp_get_sw_interrupt_value(irq
);
2718 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n",irq_value
);
2722 /* configure and load the copy binary, the next binary is used to
2723 determine whether the copy binary needs to do left padding. */
2724 static enum ia_css_err
load_copy_binary(
2725 struct ia_css_pipe
*pipe
,
2726 struct ia_css_binary
*copy_binary
,
2727 struct ia_css_binary
*next_binary
)
2729 struct ia_css_frame_info copy_out_info
, copy_in_info
, copy_vf_info
;
2730 unsigned int left_padding
;
2731 enum ia_css_err err
;
2732 struct ia_css_binary_descr copy_descr
;
2734 /* next_binary can be NULL */
2735 assert(pipe
!= NULL
);
2736 assert(copy_binary
!= NULL
);
2737 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
2738 "load_copy_binary() enter:\n");
2740 if (next_binary
!= NULL
) {
2741 copy_out_info
= next_binary
->in_frame_info
;
2742 left_padding
= next_binary
->left_padding
;
2744 copy_out_info
= pipe
->output_info
[0];
2745 copy_vf_info
= pipe
->vf_output_info
[0];
2746 ia_css_frame_info_set_format(©_vf_info
, IA_CSS_FRAME_FORMAT_YUV_LINE
);
2750 ia_css_pipe_get_copy_binarydesc(pipe
, ©_descr
,
2751 ©_in_info
, ©_out_info
, (next_binary
!= NULL
) ? NULL
: NULL
/*TODO: ©_vf_info*/);
2752 err
= ia_css_binary_find(©_descr
, copy_binary
);
2753 if (err
!= IA_CSS_SUCCESS
)
2755 copy_binary
->left_padding
= left_padding
;
2756 return IA_CSS_SUCCESS
;
2759 static enum ia_css_err
2760 alloc_continuous_frames(
2761 struct ia_css_pipe
*pipe
, bool init_time
)
2763 enum ia_css_err err
= IA_CSS_SUCCESS
;
2764 struct ia_css_frame_info ref_info
;
2765 enum ia_css_pipe_id pipe_id
;
2767 unsigned int i
, idx
;
2768 unsigned int num_frames
;
2769 struct ia_css_pipe
*capture_pipe
= NULL
;
2771 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe
, init_time
);
2773 if ((pipe
== NULL
) || (pipe
->stream
== NULL
)) {
2774 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
2775 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2778 pipe_id
= pipe
->mode
;
2779 continuous
= pipe
->stream
->config
.continuous
;
2783 num_frames
= pipe
->stream
->config
.init_num_cont_raw_buf
;
2784 pipe
->stream
->continuous_pipe
= pipe
;
2786 num_frames
= pipe
->stream
->config
.target_num_cont_raw_buf
;
2788 num_frames
= NUM_ONLINE_INIT_CONTINUOUS_FRAMES
;
2791 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
) {
2792 ref_info
= pipe
->pipe_settings
.preview
.preview_binary
.in_frame_info
;
2793 } else if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
) {
2794 ref_info
= pipe
->pipe_settings
.video
.video_binary
.in_frame_info
;
2797 /* should not happen */
2798 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
2799 return IA_CSS_ERR_INTERNAL_ERROR
;
2802 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2803 /* For CSI2+, the continuous frame will hold the full input frame */
2804 ref_info
.res
.width
= pipe
->stream
->config
.input_config
.input_res
.width
;
2805 ref_info
.res
.height
= pipe
->stream
->config
.input_config
.input_res
.height
;
2807 /* Ensure padded width is aligned for 2401 */
2808 ref_info
.padded_width
= CEIL_MUL(ref_info
.res
.width
, 2 * ISP_VEC_NELEMS
);
2811 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2812 if (pipe
->stream
->config
.pack_raw_pixels
) {
2813 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
2814 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2815 ref_info
.format
= IA_CSS_FRAME_FORMAT_RAW_PACKED
;
2819 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
2820 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2821 ref_info
.format
= IA_CSS_FRAME_FORMAT_RAW
;
2824 /* Write format back to binary */
2825 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
) {
2826 pipe
->pipe_settings
.preview
.preview_binary
.in_frame_info
.format
= ref_info
.format
;
2827 capture_pipe
= pipe
->pipe_settings
.preview
.capture_pipe
;
2828 } else if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
) {
2829 pipe
->pipe_settings
.video
.video_binary
.in_frame_info
.format
= ref_info
.format
;
2830 capture_pipe
= pipe
->pipe_settings
.video
.capture_pipe
;
2832 /* should not happen */
2833 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
2834 return IA_CSS_ERR_INTERNAL_ERROR
;
2840 idx
= pipe
->stream
->config
.init_num_cont_raw_buf
;
2842 for (i
= idx
; i
< NUM_CONTINUOUS_FRAMES
; i
++) {
2843 /* free previous frame */
2844 if (pipe
->continuous_frames
[i
]) {
2845 ia_css_frame_free(pipe
->continuous_frames
[i
]);
2846 pipe
->continuous_frames
[i
] = NULL
;
2848 /* free previous metadata buffer */
2849 ia_css_metadata_free(pipe
->cont_md_buffers
[i
]);
2850 pipe
->cont_md_buffers
[i
] = NULL
;
2852 /* check if new frame needed */
2853 if (i
< num_frames
) {
2854 /* allocate new frame */
2855 err
= ia_css_frame_allocate_from_info(
2856 &pipe
->continuous_frames
[i
],
2858 if (err
!= IA_CSS_SUCCESS
) {
2859 IA_CSS_LEAVE_ERR_PRIVATE(err
);
2862 /* allocate metadata buffer */
2863 pipe
->cont_md_buffers
[i
] = ia_css_metadata_allocate(
2864 &pipe
->stream
->info
.metadata_info
);
2867 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
2868 return IA_CSS_SUCCESS
;
2872 ia_css_alloc_continuous_frame_remain(struct ia_css_stream
*stream
)
2875 return IA_CSS_ERR_INVALID_ARGUMENTS
;
2876 return alloc_continuous_frames(stream
->continuous_pipe
, false);
2879 static enum ia_css_err
2880 load_preview_binaries(struct ia_css_pipe
*pipe
)
2882 struct ia_css_frame_info prev_in_info
,
2886 struct ia_css_binary_descr preview_descr
;
2888 enum ia_css_err err
= IA_CSS_SUCCESS
;
2889 bool continuous
, need_vf_pp
= false;
2890 bool need_isp_copy_binary
= false;
2891 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2892 bool sensor
= false;
2894 /* preview only have 1 output pin now */
2895 struct ia_css_frame_info
*pipe_out_info
= &pipe
->output_info
[0];
2896 struct ia_css_preview_settings
*mycs
= &pipe
->pipe_settings
.preview
;
2898 IA_CSS_ENTER_PRIVATE("");
2899 assert(pipe
!= NULL
);
2900 assert(pipe
->stream
!= NULL
);
2901 assert(pipe
->mode
== IA_CSS_PIPE_ID_PREVIEW
);
2903 online
= pipe
->stream
->config
.online
;
2904 continuous
= pipe
->stream
->config
.continuous
;
2905 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2906 sensor
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
;
2909 if (mycs
->preview_binary
.info
)
2910 return IA_CSS_SUCCESS
;
2912 err
= ia_css_util_check_input(&pipe
->stream
->config
, false, false);
2913 if (err
!= IA_CSS_SUCCESS
)
2915 err
= ia_css_frame_check_info(pipe_out_info
);
2916 if (err
!= IA_CSS_SUCCESS
)
2919 /* Note: the current selection of vf_pp binary and
2920 * parameterization of the preview binary contains a few pieces
2921 * of hardcoded knowledge. This needs to be cleaned up such that
2922 * the binary selection becomes more generic.
2923 * The vf_pp binary is needed if one or more of the following features
2925 * 1. YUV downscaling.
2927 * 3. An output format that is not supported by the preview binary.
2928 * In practice this means something other than yuv_line or nv12.
2929 * The decision if the vf_pp binary is needed for YUV downscaling is
2930 * made after the preview binary selection, since some preview binaries
2931 * can perform the requested YUV downscaling.
2933 need_vf_pp
= pipe
->config
.enable_dz
;
2934 need_vf_pp
|= pipe_out_info
->format
!= IA_CSS_FRAME_FORMAT_YUV_LINE
&&
2935 !(pipe_out_info
->format
== IA_CSS_FRAME_FORMAT_NV12
||
2936 pipe_out_info
->format
== IA_CSS_FRAME_FORMAT_NV12_16
||
2937 pipe_out_info
->format
== IA_CSS_FRAME_FORMAT_NV12_TILEY
);
2939 /* Preview step 1 */
2940 if (pipe
->vf_yuv_ds_input_info
.res
.width
)
2941 prev_vf_info
= pipe
->vf_yuv_ds_input_info
;
2943 prev_vf_info
= *pipe_out_info
;
2944 /* If vf_pp is needed, then preview must output yuv_line.
2945 * The exception is when vf_pp is manually disabled, that is only
2946 * used in combination with a pipeline extension that requires
2947 * yuv_line as input.
2950 ia_css_frame_info_set_format(&prev_vf_info
,
2951 IA_CSS_FRAME_FORMAT_YUV_LINE
);
2953 err
= ia_css_pipe_get_preview_binarydesc(
2960 if (err
!= IA_CSS_SUCCESS
)
2962 err
= ia_css_binary_find(&preview_descr
, &mycs
->preview_binary
);
2963 if (err
!= IA_CSS_SUCCESS
)
2967 /* The delay latency determines the number of invalid frames after
2968 * a stream is started. */
2969 pipe
->num_invalid_frames
= pipe
->dvs_frame_delay
;
2970 pipe
->info
.num_invalid_frames
= pipe
->num_invalid_frames
;
2972 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
2973 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2974 pipe
->num_invalid_frames
, pipe
->dvs_frame_delay
);
2977 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2978 need_vf_pp
|= mycs
->preview_binary
.out_frame_info
[0].res
.width
!= pipe_out_info
->res
.width
;
2979 need_vf_pp
|= mycs
->preview_binary
.out_frame_info
[0].res
.height
!= pipe_out_info
->res
.height
;
2981 /* When vf_pp is needed, then the output format of the selected
2982 * preview binary must be yuv_line. If this is not the case,
2983 * then the preview binary selection is done again.
2986 (mycs
->preview_binary
.out_frame_info
[0].format
!= IA_CSS_FRAME_FORMAT_YUV_LINE
)) {
2988 /* Preview step 2 */
2989 if (pipe
->vf_yuv_ds_input_info
.res
.width
)
2990 prev_vf_info
= pipe
->vf_yuv_ds_input_info
;
2992 prev_vf_info
= *pipe_out_info
;
2994 ia_css_frame_info_set_format(&prev_vf_info
,
2995 IA_CSS_FRAME_FORMAT_YUV_LINE
);
2997 err
= ia_css_pipe_get_preview_binarydesc(
3004 if (err
!= IA_CSS_SUCCESS
)
3006 err
= ia_css_binary_find(&preview_descr
,
3007 &mycs
->preview_binary
);
3008 if (err
!= IA_CSS_SUCCESS
)
3013 struct ia_css_binary_descr vf_pp_descr
;
3015 /* Viewfinder post-processing */
3016 ia_css_pipe_get_vfpp_binarydesc(pipe
, &vf_pp_descr
,
3017 &mycs
->preview_binary
.out_frame_info
[0],
3019 err
= ia_css_binary_find(&vf_pp_descr
,
3020 &mycs
->vf_pp_binary
);
3021 if (err
!= IA_CSS_SUCCESS
)
3025 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3026 /* When the input system is 2401, only the Direct Sensor Mode
3027 * Offline Preview uses the ISP copy binary.
3029 need_isp_copy_binary
= !online
&& sensor
;
3032 need_isp_copy_binary
= !online
&& !continuous
;
3034 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3035 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3036 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3037 * copies sensor data to DDR) does not have much use.
3039 need_isp_copy_binary
= !online
&& !continuous
&& !(pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
);
3044 if (need_isp_copy_binary
) {
3045 err
= load_copy_binary(pipe
,
3047 &mycs
->preview_binary
);
3048 if (err
!= IA_CSS_SUCCESS
)
3052 if (pipe
->shading_table
) {
3053 ia_css_shading_table_free(pipe
->shading_table
);
3054 pipe
->shading_table
= NULL
;
3057 return IA_CSS_SUCCESS
;
3061 ia_css_binary_unload(struct ia_css_binary
*binary
)
3063 ia_css_binary_destroy_isp_parameters(binary
);
3066 static enum ia_css_err
3067 unload_preview_binaries(struct ia_css_pipe
*pipe
)
3069 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
3071 if ((pipe
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_PREVIEW
)) {
3072 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
3073 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3075 ia_css_binary_unload(&pipe
->pipe_settings
.preview
.copy_binary
);
3076 ia_css_binary_unload(&pipe
->pipe_settings
.preview
.preview_binary
);
3077 ia_css_binary_unload(&pipe
->pipe_settings
.preview
.vf_pp_binary
);
3079 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
3080 return IA_CSS_SUCCESS
;
3083 static const struct ia_css_fw_info
*last_output_firmware(
3084 const struct ia_css_fw_info
*fw
)
3086 const struct ia_css_fw_info
*last_fw
= NULL
;
3087 /* fw can be NULL */
3088 IA_CSS_ENTER_LEAVE_PRIVATE("");
3090 for (; fw
; fw
= fw
->next
) {
3091 const struct ia_css_fw_info
*info
= fw
;
3092 if (info
->info
.isp
.sp
.enable
.output
)
3098 static enum ia_css_err
add_firmwares(
3099 struct ia_css_pipeline
*me
,
3100 struct ia_css_binary
*binary
,
3101 const struct ia_css_fw_info
*fw
,
3102 const struct ia_css_fw_info
*last_fw
,
3103 unsigned int binary_mode
,
3104 struct ia_css_frame
*in_frame
,
3105 struct ia_css_frame
*out_frame
,
3106 struct ia_css_frame
*vf_frame
,
3107 struct ia_css_pipeline_stage
**my_stage
,
3108 struct ia_css_pipeline_stage
**vf_stage
)
3110 enum ia_css_err err
= IA_CSS_SUCCESS
;
3111 struct ia_css_pipeline_stage
*extra_stage
= NULL
;
3112 struct ia_css_pipeline_stage_desc stage_desc
;
3114 /* all args can be NULL ??? */
3115 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3116 "add_firmwares() enter:\n");
3118 for (; fw
; fw
= fw
->next
) {
3119 struct ia_css_frame
*out
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
] = {NULL
};
3120 struct ia_css_frame
*in
= NULL
;
3121 struct ia_css_frame
*vf
= NULL
;
3122 if ((fw
== last_fw
) && (fw
->info
.isp
.sp
.enable
.out_frame
!= 0)) {
3125 if (fw
->info
.isp
.sp
.enable
.in_frame
!= 0) {
3128 if (fw
->info
.isp
.sp
.enable
.out_frame
!= 0) {
3131 ia_css_pipe_get_firmwares_stage_desc(&stage_desc
, binary
,
3132 out
, in
, vf
, fw
, binary_mode
);
3133 err
= ia_css_pipeline_create_and_add_stage(me
,
3136 if (err
!= IA_CSS_SUCCESS
)
3138 if (fw
->info
.isp
.sp
.enable
.output
!= 0)
3139 in_frame
= extra_stage
->args
.out_frame
[0];
3140 if (my_stage
&& !*my_stage
&& extra_stage
)
3141 *my_stage
= extra_stage
;
3142 if (vf_stage
&& !*vf_stage
&& extra_stage
&&
3143 fw
->info
.isp
.sp
.enable
.vf_veceven
)
3144 *vf_stage
= extra_stage
;
3149 static enum ia_css_err
add_vf_pp_stage(
3150 struct ia_css_pipe
*pipe
,
3151 struct ia_css_frame
*in_frame
,
3152 struct ia_css_frame
*out_frame
,
3153 struct ia_css_binary
*vf_pp_binary
,
3154 struct ia_css_pipeline_stage
**vf_pp_stage
)
3157 struct ia_css_pipeline
*me
= NULL
;
3158 const struct ia_css_fw_info
*last_fw
= NULL
;
3159 enum ia_css_err err
= IA_CSS_SUCCESS
;
3160 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
3161 struct ia_css_pipeline_stage_desc stage_desc
;
3163 /* out_frame can be NULL ??? */
3166 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3167 if (in_frame
== NULL
)
3168 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3169 if (vf_pp_binary
== NULL
)
3170 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3171 if (vf_pp_stage
== NULL
)
3172 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3174 ia_css_pipe_util_create_output_frames(out_frames
);
3175 me
= &pipe
->pipeline
;
3177 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3178 "add_vf_pp_stage() enter:\n");
3180 *vf_pp_stage
= NULL
;
3182 last_fw
= last_output_firmware(pipe
->vf_stage
);
3183 if (!pipe
->extra_config
.disable_vf_pp
) {
3185 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3186 ia_css_pipe_get_generic_stage_desc(&stage_desc
, vf_pp_binary
,
3187 out_frames
, in_frame
, NULL
);
3189 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
3190 ia_css_pipe_get_generic_stage_desc(&stage_desc
, vf_pp_binary
,
3191 out_frames
, in_frame
, NULL
);
3193 err
= ia_css_pipeline_create_and_add_stage(me
, &stage_desc
, vf_pp_stage
);
3194 if (err
!= IA_CSS_SUCCESS
)
3196 in_frame
= (*vf_pp_stage
)->args
.out_frame
[0];
3198 err
= add_firmwares(me
, vf_pp_binary
, pipe
->vf_stage
, last_fw
,
3199 IA_CSS_BINARY_MODE_VF_PP
,
3200 in_frame
, out_frame
, NULL
,
3205 static enum ia_css_err
add_yuv_scaler_stage(
3206 struct ia_css_pipe
*pipe
,
3207 struct ia_css_pipeline
*me
,
3208 struct ia_css_frame
*in_frame
,
3209 struct ia_css_frame
*out_frame
,
3210 struct ia_css_frame
*internal_out_frame
,
3211 struct ia_css_binary
*yuv_scaler_binary
,
3212 struct ia_css_pipeline_stage
**pre_vf_pp_stage
)
3214 const struct ia_css_fw_info
*last_fw
;
3215 enum ia_css_err err
= IA_CSS_SUCCESS
;
3216 struct ia_css_frame
*vf_frame
= NULL
;
3217 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
3218 struct ia_css_pipeline_stage_desc stage_desc
;
3220 /* out_frame can be NULL ??? */
3221 assert(in_frame
!= NULL
);
3222 assert(pipe
!= NULL
);
3224 assert(yuv_scaler_binary
!= NULL
);
3225 assert(pre_vf_pp_stage
!= NULL
);
3226 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3227 "add_yuv_scaler_stage() enter:\n");
3229 *pre_vf_pp_stage
= NULL
;
3230 ia_css_pipe_util_create_output_frames(out_frames
);
3232 last_fw
= last_output_firmware(pipe
->output_stage
);
3235 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3236 ia_css_pipe_get_generic_stage_desc(&stage_desc
,
3237 yuv_scaler_binary
, out_frames
, in_frame
, vf_frame
);
3239 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
3240 ia_css_pipe_util_set_output_frames(out_frames
, 1, internal_out_frame
);
3241 ia_css_pipe_get_generic_stage_desc(&stage_desc
,
3242 yuv_scaler_binary
, out_frames
, in_frame
, vf_frame
);
3244 err
= ia_css_pipeline_create_and_add_stage(me
,
3247 if (err
!= IA_CSS_SUCCESS
)
3249 in_frame
= (*pre_vf_pp_stage
)->args
.out_frame
[0];
3251 err
= add_firmwares(me
, yuv_scaler_binary
, pipe
->output_stage
, last_fw
,
3252 IA_CSS_BINARY_MODE_CAPTURE_PP
,
3253 in_frame
, out_frame
, vf_frame
,
3254 NULL
, pre_vf_pp_stage
);
3255 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3256 (*pre_vf_pp_stage
)->args
.vf_downscale_log2
= yuv_scaler_binary
->vf_downscale_log2
;
3258 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3259 "add_yuv_scaler_stage() leave:\n");
3263 static enum ia_css_err
add_capture_pp_stage(
3264 struct ia_css_pipe
*pipe
,
3265 struct ia_css_pipeline
*me
,
3266 struct ia_css_frame
*in_frame
,
3267 struct ia_css_frame
*out_frame
,
3268 struct ia_css_binary
*capture_pp_binary
,
3269 struct ia_css_pipeline_stage
**capture_pp_stage
)
3271 const struct ia_css_fw_info
*last_fw
= NULL
;
3272 enum ia_css_err err
= IA_CSS_SUCCESS
;
3273 struct ia_css_frame
*vf_frame
= NULL
;
3274 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
3275 struct ia_css_pipeline_stage_desc stage_desc
;
3277 /* out_frame can be NULL ??? */
3278 assert(in_frame
!= NULL
);
3279 assert(pipe
!= NULL
);
3281 assert(capture_pp_binary
!= NULL
);
3282 assert(capture_pp_stage
!= NULL
);
3283 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3284 "add_capture_pp_stage() enter:\n");
3286 *capture_pp_stage
= NULL
;
3287 ia_css_pipe_util_create_output_frames(out_frames
);
3289 last_fw
= last_output_firmware(pipe
->output_stage
);
3290 err
= ia_css_frame_allocate_from_info(&vf_frame
,
3291 &capture_pp_binary
->vf_frame_info
);
3292 if (err
!= IA_CSS_SUCCESS
)
3295 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3296 ia_css_pipe_get_generic_stage_desc(&stage_desc
,
3297 capture_pp_binary
, out_frames
, NULL
, vf_frame
);
3299 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
3300 ia_css_pipe_get_generic_stage_desc(&stage_desc
,
3301 capture_pp_binary
, out_frames
, NULL
, vf_frame
);
3303 err
= ia_css_pipeline_create_and_add_stage(me
,
3306 if (err
!= IA_CSS_SUCCESS
)
3308 err
= add_firmwares(me
, capture_pp_binary
, pipe
->output_stage
, last_fw
,
3309 IA_CSS_BINARY_MODE_CAPTURE_PP
,
3310 in_frame
, out_frame
, vf_frame
,
3311 NULL
, capture_pp_stage
);
3312 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3313 if (*capture_pp_stage
) {
3314 (*capture_pp_stage
)->args
.vf_downscale_log2
=
3315 capture_pp_binary
->vf_downscale_log2
;
3320 static void sh_css_setup_queues(void)
3322 const struct ia_css_fw_info
*fw
;
3323 unsigned int HIVE_ADDR_host_sp_queues_initialized
;
3325 sh_css_hmm_buffer_record_init();
3327 sh_css_event_init_irq_mask();
3330 HIVE_ADDR_host_sp_queues_initialized
=
3331 fw
->info
.sp
.host_sp_queues_initialized
;
3335 /* set "host_sp_queues_initialized" to "true" */
3336 sp_dmem_store_uint32(SP0_ID
,
3337 (unsigned int)sp_address_of(host_sp_queues_initialized
),
3339 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_setup_queues() leave:\n");
3342 static enum ia_css_err
3343 init_vf_frameinfo_defaults(struct ia_css_pipe
*pipe
,
3344 struct ia_css_frame
*vf_frame
, unsigned int idx
)
3346 enum ia_css_err err
= IA_CSS_SUCCESS
;
3347 unsigned int thread_id
;
3348 enum sh_css_queue_id queue_id
;
3350 assert(vf_frame
!= NULL
);
3352 sh_css_pipe_get_viewfinder_frame_info(pipe
, &vf_frame
->info
, idx
);
3353 vf_frame
->contiguous
= false;
3354 vf_frame
->flash_state
= IA_CSS_FRAME_FLASH_STATE_NONE
;
3355 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
3356 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
+ idx
, thread_id
, &queue_id
);
3357 vf_frame
->dynamic_queue_id
= queue_id
;
3358 vf_frame
->buf_type
= IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
+ idx
;
3360 err
= ia_css_frame_init_planes(vf_frame
);
3364 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3366 get_crop_lines_for_bayer_order (
3367 const struct ia_css_stream_config
*config
)
3369 assert(config
!= NULL
);
3370 if ((IA_CSS_BAYER_ORDER_BGGR
== config
->input_config
.bayer_order
)
3371 || (IA_CSS_BAYER_ORDER_GBRG
== config
->input_config
.bayer_order
))
3378 get_crop_columns_for_bayer_order (
3379 const struct ia_css_stream_config
*config
)
3381 assert(config
!= NULL
);
3382 if ((IA_CSS_BAYER_ORDER_RGGB
== config
->input_config
.bayer_order
)
3383 || (IA_CSS_BAYER_ORDER_GBRG
== config
->input_config
.bayer_order
))
3389 /* This function is to get the sum of all extra pixels in addition to the effective
3390 * input, it includes dvs envelop and filter run-in */
3391 static void get_pipe_extra_pixel(struct ia_css_pipe
*pipe
,
3392 unsigned int *extra_row
, unsigned int *extra_column
)
3394 enum ia_css_pipe_id pipe_id
= pipe
->mode
;
3395 unsigned int left_cropping
= 0, top_cropping
= 0;
3397 struct ia_css_resolution dvs_env
= pipe
->config
.dvs_envelope
;
3399 /* The dvs envelope info may not be correctly sent down via pipe config
3400 * The check is made and the correct value is populated in the binary info
3401 * Use this value when computing crop, else excess lines may get trimmed
3404 case IA_CSS_PIPE_ID_PREVIEW
:
3405 if (pipe
->pipe_settings
.preview
.preview_binary
.info
) {
3406 left_cropping
= pipe
->pipe_settings
.preview
.preview_binary
.info
->sp
.pipeline
.left_cropping
;
3407 top_cropping
= pipe
->pipe_settings
.preview
.preview_binary
.info
->sp
.pipeline
.top_cropping
;
3409 dvs_env
= pipe
->pipe_settings
.preview
.preview_binary
.dvs_envelope
;
3411 case IA_CSS_PIPE_ID_VIDEO
:
3412 if (pipe
->pipe_settings
.video
.video_binary
.info
) {
3413 left_cropping
= pipe
->pipe_settings
.video
.video_binary
.info
->sp
.pipeline
.left_cropping
;
3414 top_cropping
= pipe
->pipe_settings
.video
.video_binary
.info
->sp
.pipeline
.top_cropping
;
3416 dvs_env
= pipe
->pipe_settings
.video
.video_binary
.dvs_envelope
;
3418 case IA_CSS_PIPE_ID_CAPTURE
:
3419 for (i
= 0; i
< pipe
->pipe_settings
.capture
.num_primary_stage
; i
++) {
3420 if (pipe
->pipe_settings
.capture
.primary_binary
[i
].info
) {
3421 left_cropping
+= pipe
->pipe_settings
.capture
.primary_binary
[i
].info
->sp
.pipeline
.left_cropping
;
3422 top_cropping
+= pipe
->pipe_settings
.capture
.primary_binary
[i
].info
->sp
.pipeline
.top_cropping
;
3424 dvs_env
.width
+= pipe
->pipe_settings
.capture
.primary_binary
[i
].dvs_envelope
.width
;
3425 dvs_env
.height
+= pipe
->pipe_settings
.capture
.primary_binary
[i
].dvs_envelope
.height
;
3432 *extra_row
= top_cropping
+ dvs_env
.height
;
3433 *extra_column
= left_cropping
+ dvs_env
.width
;
3437 ia_css_get_crop_offsets (
3438 struct ia_css_pipe
*pipe
,
3439 struct ia_css_frame_info
*in_frame
)
3441 unsigned int row
= 0;
3442 unsigned int column
= 0;
3443 struct ia_css_resolution
*input_res
;
3444 struct ia_css_resolution
*effective_res
;
3445 unsigned int extra_row
= 0, extra_col
= 0;
3446 unsigned int min_reqd_height
, min_reqd_width
;
3448 assert(pipe
!= NULL
);
3449 assert(pipe
->stream
!= NULL
);
3450 assert(in_frame
!= NULL
);
3452 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3453 pipe
, pipe
->config
.input_effective_res
.width
,
3454 pipe
->config
.input_effective_res
.height
);
3456 input_res
= &pipe
->stream
->config
.input_config
.input_res
;
3458 effective_res
= &pipe
->stream
->config
.input_config
.effective_res
;
3460 effective_res
= &pipe
->config
.input_effective_res
;
3463 get_pipe_extra_pixel(pipe
, &extra_row
, &extra_col
);
3465 in_frame
->raw_bayer_order
= pipe
->stream
->config
.input_config
.bayer_order
;
3467 min_reqd_height
= effective_res
->height
+ extra_row
;
3468 min_reqd_width
= effective_res
->width
+ extra_col
;
3470 if (input_res
->height
> min_reqd_height
) {
3471 row
= (input_res
->height
- min_reqd_height
) / 2;
3474 if (input_res
->width
> min_reqd_width
) {
3475 column
= (input_res
->width
- min_reqd_width
) / 2;
3481 * 1. Require the special support for RAW10 packed mode.
3482 * 2. Require the special support for the online use cases.
3485 /* ISP expects GRBG bayer order, we skip one line and/or one row
3486 * to correct in case the input bayer order is different.
3488 column
+= get_crop_columns_for_bayer_order(&pipe
->stream
->config
);
3489 row
+= get_crop_lines_for_bayer_order(&pipe
->stream
->config
);
3491 in_frame
->crop_info
.start_column
= column
;
3492 in_frame
->crop_info
.start_line
= row
;
3494 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column
, row
);
3500 static enum ia_css_err
3501 init_in_frameinfo_memory_defaults(struct ia_css_pipe
*pipe
,
3502 struct ia_css_frame
*frame
, enum ia_css_frame_format format
)
3504 struct ia_css_frame
*in_frame
;
3505 enum ia_css_err err
= IA_CSS_SUCCESS
;
3506 unsigned int thread_id
;
3507 enum sh_css_queue_id queue_id
;
3509 assert(frame
!= NULL
);
3512 in_frame
->info
.format
= format
;
3514 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3515 if (format
== IA_CSS_FRAME_FORMAT_RAW
)
3516 in_frame
->info
.format
= (pipe
->stream
->config
.pack_raw_pixels
) ?
3517 IA_CSS_FRAME_FORMAT_RAW_PACKED
: IA_CSS_FRAME_FORMAT_RAW
;
3521 in_frame
->info
.res
.width
= pipe
->stream
->config
.input_config
.input_res
.width
;
3522 in_frame
->info
.res
.height
= pipe
->stream
->config
.input_config
.input_res
.height
;
3523 in_frame
->info
.raw_bit_depth
=
3524 ia_css_pipe_util_pipe_input_format_bpp(pipe
);
3525 ia_css_frame_info_set_width(&in_frame
->info
, pipe
->stream
->config
.input_config
.input_res
.width
, 0);
3526 in_frame
->contiguous
= false;
3527 in_frame
->flash_state
= IA_CSS_FRAME_FLASH_STATE_NONE
;
3528 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
3529 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME
, thread_id
, &queue_id
);
3530 in_frame
->dynamic_queue_id
= queue_id
;
3531 in_frame
->buf_type
= IA_CSS_BUFFER_TYPE_INPUT_FRAME
;
3532 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3533 ia_css_get_crop_offsets(pipe
, &in_frame
->info
);
3535 err
= ia_css_frame_init_planes(in_frame
);
3537 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
3538 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame
->info
.raw_bayer_order
);
3543 static enum ia_css_err
3544 init_out_frameinfo_defaults(struct ia_css_pipe
*pipe
,
3545 struct ia_css_frame
*out_frame
, unsigned int idx
)
3547 enum ia_css_err err
= IA_CSS_SUCCESS
;
3548 unsigned int thread_id
;
3549 enum sh_css_queue_id queue_id
;
3551 assert(out_frame
!= NULL
);
3553 sh_css_pipe_get_output_frame_info(pipe
, &out_frame
->info
, idx
);
3554 out_frame
->contiguous
= false;
3555 out_frame
->flash_state
= IA_CSS_FRAME_FLASH_STATE_NONE
;
3556 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
3557 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
+ idx
, thread_id
, &queue_id
);
3558 out_frame
->dynamic_queue_id
= queue_id
;
3559 out_frame
->buf_type
= IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
+ idx
;
3560 err
= ia_css_frame_init_planes(out_frame
);
3565 /* Create stages for video pipe */
3566 static enum ia_css_err
create_host_video_pipeline(struct ia_css_pipe
*pipe
)
3568 struct ia_css_pipeline_stage_desc stage_desc
;
3569 struct ia_css_binary
*copy_binary
, *video_binary
,
3570 *yuv_scaler_binary
, *vf_pp_binary
;
3571 struct ia_css_pipeline_stage
*copy_stage
= NULL
;
3572 struct ia_css_pipeline_stage
*video_stage
= NULL
;
3573 struct ia_css_pipeline_stage
*yuv_scaler_stage
= NULL
;
3574 struct ia_css_pipeline_stage
*vf_pp_stage
= NULL
;
3575 struct ia_css_pipeline
*me
;
3576 struct ia_css_frame
*in_frame
= NULL
;
3577 struct ia_css_frame
*out_frame
;
3578 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
3579 struct ia_css_frame
*vf_frame
= NULL
;
3580 enum ia_css_err err
= IA_CSS_SUCCESS
;
3581 bool need_copy
= false;
3582 bool need_vf_pp
= false;
3583 bool need_yuv_pp
= false;
3584 unsigned num_output_pins
;
3585 bool need_in_frameinfo_memory
= false;
3587 unsigned int i
, num_yuv_scaler
;
3588 bool *is_output_stage
= NULL
;
3590 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
3591 if ((pipe
== NULL
) || (pipe
->stream
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_VIDEO
)) {
3592 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
3593 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3595 ia_css_pipe_util_create_output_frames(out_frames
);
3596 out_frame
= &pipe
->out_frame_struct
;
3598 /* pipeline already created as part of create_host_pipeline_structure */
3599 me
= &pipe
->pipeline
;
3600 ia_css_pipeline_clean(me
);
3602 me
->dvs_frame_delay
= pipe
->dvs_frame_delay
;
3604 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3605 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3606 * except for the following: online or continuous
3608 need_in_frameinfo_memory
= !(pipe
->stream
->config
.online
|| pipe
->stream
->config
.continuous
);
3610 /* Construct in_frame info (only in case we have dynamic input */
3611 need_in_frameinfo_memory
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
3614 /* Construct in_frame info (only in case we have dynamic input */
3615 if (need_in_frameinfo_memory
) {
3616 in_frame
= &pipe
->in_frame_struct
;
3617 err
= init_in_frameinfo_memory_defaults(pipe
, in_frame
, IA_CSS_FRAME_FORMAT_RAW
);
3618 if (err
!= IA_CSS_SUCCESS
)
3622 out_frame
->data
= 0;
3623 err
= init_out_frameinfo_defaults(pipe
, out_frame
, 0);
3624 if (err
!= IA_CSS_SUCCESS
)
3627 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
]) {
3628 vf_frame
= &pipe
->vf_frame_struct
;
3630 err
= init_vf_frameinfo_defaults(pipe
, vf_frame
, 0);
3631 if (err
!= IA_CSS_SUCCESS
)
3635 copy_binary
= &pipe
->pipe_settings
.video
.copy_binary
;
3636 video_binary
= &pipe
->pipe_settings
.video
.video_binary
;
3637 vf_pp_binary
= &pipe
->pipe_settings
.video
.vf_pp_binary
;
3638 num_output_pins
= video_binary
->info
->num_output_pins
;
3640 yuv_scaler_binary
= pipe
->pipe_settings
.video
.yuv_scaler_binary
;
3641 num_yuv_scaler
= pipe
->pipe_settings
.video
.num_yuv_scaler
;
3642 is_output_stage
= pipe
->pipe_settings
.video
.is_output_stage
;
3644 need_copy
= (copy_binary
!= NULL
&& copy_binary
->info
!= NULL
);
3645 need_vf_pp
= (vf_pp_binary
!= NULL
&& vf_pp_binary
->info
!= NULL
);
3646 need_yuv_pp
= (yuv_scaler_binary
!= NULL
&& yuv_scaler_binary
->info
!= NULL
);
3649 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3650 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
3651 out_frames
, NULL
, NULL
);
3652 err
= ia_css_pipeline_create_and_add_stage(me
,
3655 if (err
!= IA_CSS_SUCCESS
)
3657 in_frame
= me
->stages
->args
.out_frame
[0];
3658 } else if (pipe
->stream
->config
.continuous
) {
3659 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3660 /* When continous is enabled, configure in_frame with the
3661 * last pipe, which is the copy pipe.
3663 in_frame
= pipe
->stream
->last_pipe
->continuous_frames
[0];
3665 in_frame
= pipe
->continuous_frames
[0];
3669 ia_css_pipe_util_set_output_frames(out_frames
, 0, need_yuv_pp
? NULL
: out_frame
);
3671 /* when the video binary supports a second output pin,
3672 it can directly produce the vf_frame. */
3674 ia_css_pipe_get_generic_stage_desc(&stage_desc
, video_binary
,
3675 out_frames
, in_frame
, NULL
);
3677 ia_css_pipe_get_generic_stage_desc(&stage_desc
, video_binary
,
3678 out_frames
, in_frame
, vf_frame
);
3680 err
= ia_css_pipeline_create_and_add_stage(me
,
3683 if (err
!= IA_CSS_SUCCESS
)
3686 /* If we use copy iso video, the input must be yuv iso raw */
3688 video_stage
->args
.copy_vf
=
3689 video_binary
->info
->sp
.pipeline
.mode
== IA_CSS_BINARY_MODE_COPY
;
3690 video_stage
->args
.copy_output
= video_stage
->args
.copy_vf
;
3693 /* when the video binary supports only 1 output pin, vf_pp is needed to
3694 produce the vf_frame.*/
3695 if (need_vf_pp
&& video_stage
) {
3696 in_frame
= video_stage
->args
.out_vf_frame
;
3697 err
= add_vf_pp_stage(pipe
, in_frame
, vf_frame
, vf_pp_binary
,
3699 if (err
!= IA_CSS_SUCCESS
)
3705 for (frm
= 0; frm
< NUM_VIDEO_TNR_FRAMES
; frm
++) {
3707 for (frm
= 0; frm
< NUM_TNR_FRAMES
; frm
++) {
3709 video_stage
->args
.tnr_frames
[frm
] =
3710 pipe
->pipe_settings
.video
.tnr_frames
[frm
];
3712 for (frm
= 0; frm
< MAX_NUM_VIDEO_DELAY_FRAMES
; frm
++) {
3713 video_stage
->args
.delay_frames
[frm
] =
3714 pipe
->pipe_settings
.video
.delay_frames
[frm
];
3718 /* Append Extension on Video out, if enabled */
3719 if (!need_vf_pp
&& video_stage
&& pipe
->config
.acc_extension
&&
3720 (pipe
->config
.acc_extension
->info
.isp
.type
== IA_CSS_ACC_OUTPUT
))
3722 struct ia_css_frame
*out
= NULL
;
3723 struct ia_css_frame
*in
= NULL
;
3725 if ((pipe
->config
.acc_extension
->info
.isp
.sp
.enable
.output
) &&
3726 (pipe
->config
.acc_extension
->info
.isp
.sp
.enable
.in_frame
) &&
3727 (pipe
->config
.acc_extension
->info
.isp
.sp
.enable
.out_frame
)) {
3729 /* In/Out Frame mapping to support output frame extension.*/
3730 out
= video_stage
->args
.out_frame
[0];
3731 err
= ia_css_frame_allocate_from_info(&in
, &(pipe
->output_info
[0]));
3732 if (err
!= IA_CSS_SUCCESS
)
3734 video_stage
->args
.out_frame
[0] = in
;
3737 err
= add_firmwares( me
, video_binary
, pipe
->output_stage
,
3738 last_output_firmware(pipe
->output_stage
),
3739 IA_CSS_BINARY_MODE_VIDEO
,
3740 in
, out
, NULL
, &video_stage
, NULL
);
3741 if (err
!= IA_CSS_SUCCESS
)
3745 if (need_yuv_pp
&& video_stage
) {
3746 struct ia_css_frame
*tmp_in_frame
= video_stage
->args
.out_frame
[0];
3747 struct ia_css_frame
*tmp_out_frame
= NULL
;
3749 for (i
= 0; i
< num_yuv_scaler
; i
++) {
3750 if (is_output_stage
[i
] == true) {
3751 tmp_out_frame
= out_frame
;
3753 tmp_out_frame
= NULL
;
3755 err
= add_yuv_scaler_stage(pipe
, me
, tmp_in_frame
, tmp_out_frame
,
3757 &yuv_scaler_binary
[i
],
3760 if (err
!= IA_CSS_SUCCESS
) {
3761 IA_CSS_LEAVE_ERR_PRIVATE(err
);
3764 /* we use output port 1 as internal output port */
3765 if (yuv_scaler_stage
)
3766 tmp_in_frame
= yuv_scaler_stage
->args
.out_frame
[1];
3770 pipe
->pipeline
.acquire_isp_each_stage
= false;
3771 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
3774 IA_CSS_LEAVE_ERR_PRIVATE(err
);
3778 static enum ia_css_err
3779 create_host_acc_pipeline(struct ia_css_pipe
*pipe
)
3781 enum ia_css_err err
= IA_CSS_SUCCESS
;
3782 const struct ia_css_fw_info
*fw
;
3785 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
3786 if ((pipe
== NULL
) || (pipe
->stream
== NULL
)) {
3787 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
3788 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3791 pipe
->pipeline
.num_execs
= pipe
->config
.acc_num_execs
;
3792 /* Reset pipe_qos_config to default disable all QOS extension stages */
3793 if (pipe
->config
.acc_extension
)
3794 pipe
->pipeline
.pipe_qos_config
= 0;
3796 fw
= pipe
->vf_stage
;
3797 for (i
= 0; fw
; fw
= fw
->next
){
3798 err
= sh_css_pipeline_add_acc_stage(&pipe
->pipeline
, fw
);
3799 if (err
!= IA_CSS_SUCCESS
)
3803 for (i
=0; i
<pipe
->config
.num_acc_stages
; i
++) {
3804 struct ia_css_fw_info
*fw
= pipe
->config
.acc_stages
[i
];
3805 err
= sh_css_pipeline_add_acc_stage(&pipe
->pipeline
, fw
);
3806 if (err
!= IA_CSS_SUCCESS
)
3810 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
3813 IA_CSS_LEAVE_ERR_PRIVATE(err
);
3817 /* Create stages for preview */
3818 static enum ia_css_err
3819 create_host_preview_pipeline(struct ia_css_pipe
*pipe
)
3821 struct ia_css_pipeline_stage
*copy_stage
= NULL
;
3822 struct ia_css_pipeline_stage
*preview_stage
= NULL
;
3823 struct ia_css_pipeline_stage
*vf_pp_stage
= NULL
;
3824 struct ia_css_pipeline_stage_desc stage_desc
;
3825 struct ia_css_pipeline
*me
= NULL
;
3826 struct ia_css_binary
*copy_binary
, *preview_binary
, *vf_pp_binary
= NULL
;
3827 struct ia_css_frame
*in_frame
= NULL
;
3828 enum ia_css_err err
= IA_CSS_SUCCESS
;
3829 struct ia_css_frame
*out_frame
;
3830 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
3831 bool need_in_frameinfo_memory
= false;
3832 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3833 bool sensor
= false;
3834 bool buffered_sensor
= false;
3835 bool online
= false;
3836 bool continuous
= false;
3839 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
3840 if ((pipe
== NULL
) || (pipe
->stream
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_PREVIEW
)) {
3841 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
3842 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3846 ia_css_pipe_util_create_output_frames(out_frames
);
3847 /* pipeline already created as part of create_host_pipeline_structure */
3848 me
= &pipe
->pipeline
;
3849 ia_css_pipeline_clean(me
);
3851 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3852 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3853 * except for the following:
3854 * - Direct Sensor Mode Online Preview
3855 * - Buffered Sensor Mode Online Preview
3856 * - Direct Sensor Mode Continuous Preview
3857 * - Buffered Sensor Mode Continous Preview
3859 sensor
= (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
);
3860 buffered_sensor
= (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
);
3861 online
= pipe
->stream
->config
.online
;
3862 continuous
= pipe
->stream
->config
.continuous
;
3863 need_in_frameinfo_memory
=
3864 !((sensor
&& (online
|| continuous
)) || (buffered_sensor
&& (online
|| continuous
)));
3866 /* Construct in_frame info (only in case we have dynamic input */
3867 need_in_frameinfo_memory
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
3869 if (need_in_frameinfo_memory
) {
3870 err
= init_in_frameinfo_memory_defaults(pipe
, &me
->in_frame
, IA_CSS_FRAME_FORMAT_RAW
);
3871 if (err
!= IA_CSS_SUCCESS
)
3874 in_frame
= &me
->in_frame
;
3879 err
= init_out_frameinfo_defaults(pipe
, &me
->out_frame
[0], 0);
3880 if (err
!= IA_CSS_SUCCESS
)
3882 out_frame
= &me
->out_frame
[0];
3884 copy_binary
= &pipe
->pipe_settings
.preview
.copy_binary
;
3885 preview_binary
= &pipe
->pipe_settings
.preview
.preview_binary
;
3886 if (pipe
->pipe_settings
.preview
.vf_pp_binary
.info
)
3887 vf_pp_binary
= &pipe
->pipe_settings
.preview
.vf_pp_binary
;
3889 if (pipe
->pipe_settings
.preview
.copy_binary
.info
) {
3890 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3891 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
3892 out_frames
, NULL
, NULL
);
3893 err
= ia_css_pipeline_create_and_add_stage(me
,
3896 if (err
!= IA_CSS_SUCCESS
)
3898 in_frame
= me
->stages
->args
.out_frame
[0];
3902 } else if (pipe
->stream
->config
.continuous
) {
3904 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3905 /* When continuous is enabled, configure in_frame with the
3906 * last pipe, which is the copy pipe.
3908 if (continuous
|| !online
){
3909 in_frame
= pipe
->stream
->last_pipe
->continuous_frames
[0];
3912 in_frame
= pipe
->continuous_frames
[0];
3917 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
3918 ia_css_pipe_get_generic_stage_desc(&stage_desc
, preview_binary
,
3919 out_frames
, in_frame
, NULL
);
3921 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
3922 ia_css_pipe_get_generic_stage_desc(&stage_desc
, preview_binary
,
3923 out_frames
, in_frame
, NULL
);
3925 err
= ia_css_pipeline_create_and_add_stage(me
,
3928 if (err
!= IA_CSS_SUCCESS
)
3930 /* If we use copy iso preview, the input must be yuv iso raw */
3931 preview_stage
->args
.copy_vf
=
3932 preview_binary
->info
->sp
.pipeline
.mode
== IA_CSS_BINARY_MODE_COPY
;
3933 preview_stage
->args
.copy_output
= !preview_stage
->args
.copy_vf
;
3934 if (preview_stage
->args
.copy_vf
&& !preview_stage
->args
.out_vf_frame
) {
3935 /* in case of copy, use the vf frame as output frame */
3936 preview_stage
->args
.out_vf_frame
=
3937 preview_stage
->args
.out_frame
[0];
3940 if (preview_binary
->info
->sp
.pipeline
.mode
== IA_CSS_BINARY_MODE_COPY
)
3941 in_frame
= preview_stage
->args
.out_vf_frame
;
3943 in_frame
= preview_stage
->args
.out_frame
[0];
3944 err
= add_vf_pp_stage(pipe
, in_frame
, out_frame
, vf_pp_binary
,
3946 if (err
!= IA_CSS_SUCCESS
)
3950 pipe
->pipeline
.acquire_isp_each_stage
= false;
3951 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
3954 IA_CSS_LEAVE_ERR_PRIVATE(err
);
3958 static void send_raw_frames(struct ia_css_pipe
*pipe
)
3960 if (pipe
->stream
->config
.continuous
) {
3963 sh_css_update_host2sp_cont_num_raw_frames
3964 (pipe
->stream
->config
.init_num_cont_raw_buf
, true);
3965 sh_css_update_host2sp_cont_num_raw_frames
3966 (pipe
->stream
->config
.target_num_cont_raw_buf
, false);
3968 /* Hand-over all the SP-internal buffers */
3969 for (i
= 0; i
< pipe
->stream
->config
.init_num_cont_raw_buf
; i
++) {
3970 sh_css_update_host2sp_offline_frame(i
,
3971 pipe
->continuous_frames
[i
], pipe
->cont_md_buffers
[i
]);
3978 static enum ia_css_err
3979 preview_start(struct ia_css_pipe
*pipe
)
3981 struct ia_css_pipeline
*me
;
3982 struct ia_css_binary
*copy_binary
, *preview_binary
, *vf_pp_binary
= NULL
;
3983 enum ia_css_err err
= IA_CSS_SUCCESS
;
3984 struct ia_css_pipe
*copy_pipe
, *capture_pipe
;
3985 struct ia_css_pipe
*acc_pipe
;
3986 enum sh_css_pipe_config_override copy_ovrd
;
3987 enum ia_css_input_mode preview_pipe_input_mode
;
3989 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
3990 if ((pipe
== NULL
) || (pipe
->stream
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_PREVIEW
)) {
3991 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
3992 return IA_CSS_ERR_INVALID_ARGUMENTS
;
3995 me
= &pipe
->pipeline
;
3997 preview_pipe_input_mode
= pipe
->stream
->config
.mode
;
3999 copy_pipe
= pipe
->pipe_settings
.preview
.copy_pipe
;
4000 capture_pipe
= pipe
->pipe_settings
.preview
.capture_pipe
;
4001 acc_pipe
= pipe
->pipe_settings
.preview
.acc_pipe
;
4003 copy_binary
= &pipe
->pipe_settings
.preview
.copy_binary
;
4004 preview_binary
= &pipe
->pipe_settings
.preview
.preview_binary
;
4005 if (pipe
->pipe_settings
.preview
.vf_pp_binary
.info
)
4006 vf_pp_binary
= &pipe
->pipe_settings
.preview
.vf_pp_binary
;
4008 sh_css_metrics_start_frame();
4010 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4011 /* multi stream video needs mipi buffers */
4012 err
= send_mipi_frames(pipe
);
4013 if (err
!= IA_CSS_SUCCESS
)
4016 send_raw_frames(pipe
);
4019 unsigned int thread_id
;
4021 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
4022 copy_ovrd
= 1 << thread_id
;
4024 if (pipe
->stream
->cont_capt
) {
4025 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe
), &thread_id
);
4026 copy_ovrd
|= 1 << thread_id
;
4030 /* Construct and load the copy pipe */
4031 if (pipe
->stream
->config
.continuous
) {
4032 sh_css_sp_init_pipeline(©_pipe
->pipeline
,
4033 IA_CSS_PIPE_ID_COPY
,
4034 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe
),
4036 pipe
->stream
->config
.pixels_per_clock
== 2, false,
4037 false, pipe
->required_bds_factor
,
4039 pipe
->stream
->config
.mode
,
4040 &pipe
->stream
->config
.metadata_config
,
4042 &pipe
->stream
->info
.metadata_info
4044 &pipe
->stream
->info
.metadata_info
,
4046 #if !defined(HAS_NO_INPUT_SYSTEM)
4048 , pipe
->stream
->config
.source
.port
.port
4050 pipe
->stream
->config
.source
.port
.port
,
4056 &pipe
->config
.internal_frame_origin_bqs_on_sctbl
,
4057 pipe
->stream
->isp_params_configs
);
4060 /* make the preview pipe start with mem mode input, copy handles
4062 preview_pipe_input_mode
= IA_CSS_INPUT_MODE_MEMORY
;
4065 /* Construct and load the capture pipe */
4066 if (pipe
->stream
->cont_capt
) {
4067 sh_css_sp_init_pipeline(&capture_pipe
->pipeline
,
4068 IA_CSS_PIPE_ID_CAPTURE
,
4069 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe
),
4070 capture_pipe
->config
.default_capture_config
.enable_xnr
!= 0,
4071 capture_pipe
->stream
->config
.pixels_per_clock
== 2,
4072 true, /* continuous */
4073 false, /* offline */
4074 capture_pipe
->required_bds_factor
,
4076 IA_CSS_INPUT_MODE_MEMORY
,
4077 &pipe
->stream
->config
.metadata_config
,
4079 &pipe
->stream
->info
.metadata_info
4081 &pipe
->stream
->info
.metadata_info
,
4083 #if !defined(HAS_NO_INPUT_SYSTEM)
4093 &capture_pipe
->config
.internal_frame_origin_bqs_on_sctbl
,
4094 capture_pipe
->stream
->isp_params_configs
);
4099 sh_css_sp_init_pipeline(&acc_pipe
->pipeline
,
4101 (uint8_t) ia_css_pipe_get_pipe_num(acc_pipe
),
4103 pipe
->stream
->config
.pixels_per_clock
== 2,
4104 false, /* continuous */
4105 false, /* offline */
4106 pipe
->required_bds_factor
,
4108 IA_CSS_INPUT_MODE_MEMORY
,
4115 #if !defined(HAS_NO_INPUT_SYSTEM)
4117 , (mipi_port_ID_t
) 0
4125 &pipe
->config
.internal_frame_origin_bqs_on_sctbl
,
4126 pipe
->stream
->isp_params_configs
);
4130 start_pipe(pipe
, copy_ovrd
, preview_pipe_input_mode
);
4132 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4135 IA_CSS_LEAVE_ERR_PRIVATE(err
);
4140 ia_css_pipe_enqueue_buffer(struct ia_css_pipe
*pipe
,
4141 const struct ia_css_buffer
*buffer
)
4143 enum ia_css_err return_err
= IA_CSS_SUCCESS
;
4144 unsigned int thread_id
;
4145 enum sh_css_queue_id queue_id
;
4146 struct ia_css_pipeline
*pipeline
;
4147 struct ia_css_pipeline_stage
*stage
;
4148 struct ia_css_rmgr_vbuf_handle p_vbuf
;
4149 struct ia_css_rmgr_vbuf_handle
*h_vbuf
;
4150 struct sh_css_hmm_buffer ddr_buffer
;
4151 enum ia_css_buffer_type buf_type
;
4152 enum ia_css_pipe_id pipe_id
;
4155 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe
, buffer
);
4157 if ((pipe
== NULL
) || (buffer
== NULL
)) {
4158 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4159 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4162 buf_type
= buffer
->type
;
4163 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4166 if (buf_type
== IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
) {
4167 bool found_pipe
= false;
4168 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
4169 if ((buffer
->data
.frame
->info
.res
.width
== pipe
->output_info
[i
].res
.width
) &&
4170 (buffer
->data
.frame
->info
.res
.height
== pipe
->output_info
[i
].res
.height
)) {
4177 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4179 if (buf_type
== IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
) {
4180 bool found_pipe
= false;
4181 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
4182 if ((buffer
->data
.frame
->info
.res
.width
== pipe
->vf_output_info
[i
].res
.width
) &&
4183 (buffer
->data
.frame
->info
.res
.height
== pipe
->vf_output_info
[i
].res
.height
)) {
4190 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4193 pipe_id
= pipe
->mode
;
4195 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id
, buf_type
);
4198 assert(pipe_id
< IA_CSS_PIPE_ID_NUM
);
4199 assert(buf_type
< IA_CSS_NUM_DYNAMIC_BUFFER_TYPE
);
4200 if ((buf_type
== IA_CSS_BUFFER_TYPE_INVALID
) ||
4201 (buf_type
>= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE
) ||
4202 (pipe_id
>= IA_CSS_PIPE_ID_NUM
)) {
4203 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR
);
4204 return IA_CSS_ERR_INTERNAL_ERROR
;
4207 ret_err
= ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
4209 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4210 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4213 ret_err
= ia_css_query_internal_queue_id(buf_type
, thread_id
, &queue_id
);
4215 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4216 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4219 if ((queue_id
<= SH_CSS_INVALID_QUEUE_ID
) || (queue_id
>= SH_CSS_MAX_NUM_QUEUES
)) {
4220 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4221 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4224 if (!sh_css_sp_is_running()) {
4225 IA_CSS_LOG("SP is not running!");
4226 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
4227 /* SP is not running. The queues are not valid */
4228 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4232 pipeline
= &pipe
->pipeline
;
4234 assert(pipeline
!= NULL
||
4235 pipe_id
== IA_CSS_PIPE_ID_COPY
||
4236 pipe_id
== IA_CSS_PIPE_ID_ACC
);
4238 assert(sizeof(NULL
) <= sizeof(ddr_buffer
.kernel_ptr
));
4239 ddr_buffer
.kernel_ptr
= HOST_ADDRESS(NULL
);
4240 ddr_buffer
.cookie_ptr
= buffer
->driver_cookie
;
4241 ddr_buffer
.timing_data
= buffer
->timing_data
;
4243 if (buf_type
== IA_CSS_BUFFER_TYPE_3A_STATISTICS
) {
4244 if (buffer
->data
.stats_3a
== NULL
) {
4245 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4246 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4248 ddr_buffer
.kernel_ptr
= HOST_ADDRESS(buffer
->data
.stats_3a
);
4249 ddr_buffer
.payload
.s3a
= *buffer
->data
.stats_3a
;
4250 } else if (buf_type
== IA_CSS_BUFFER_TYPE_DIS_STATISTICS
) {
4251 if (buffer
->data
.stats_dvs
== NULL
) {
4252 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4253 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4255 ddr_buffer
.kernel_ptr
= HOST_ADDRESS(buffer
->data
.stats_dvs
);
4256 ddr_buffer
.payload
.dis
= *buffer
->data
.stats_dvs
;
4257 } else if (buf_type
== IA_CSS_BUFFER_TYPE_METADATA
) {
4258 if (buffer
->data
.metadata
== NULL
) {
4259 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4260 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4262 ddr_buffer
.kernel_ptr
= HOST_ADDRESS(buffer
->data
.metadata
);
4263 ddr_buffer
.payload
.metadata
= *buffer
->data
.metadata
;
4264 } else if ((buf_type
== IA_CSS_BUFFER_TYPE_INPUT_FRAME
)
4265 || (buf_type
== IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
)
4266 || (buf_type
== IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
)
4267 || (buf_type
== IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
)
4268 || (buf_type
== IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME
)) {
4269 if (buffer
->data
.frame
== NULL
) {
4270 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4271 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4273 ddr_buffer
.kernel_ptr
= HOST_ADDRESS(buffer
->data
.frame
);
4274 ddr_buffer
.payload
.frame
.frame_data
= buffer
->data
.frame
->data
;
4275 ddr_buffer
.payload
.frame
.flashed
= 0;
4277 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
4278 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4279 buf_type
, buffer
->data
.frame
->data
);
4282 #if CONFIG_ON_FRAME_ENQUEUE()
4283 return_err
= set_config_on_frame_enqueue(
4284 &buffer
->data
.frame
->info
,
4285 &ddr_buffer
.payload
.frame
);
4286 if (IA_CSS_SUCCESS
!= return_err
) {
4287 IA_CSS_LEAVE_ERR(return_err
);
4293 /* start of test for using rmgr for acq/rel memory */
4296 p_vbuf
.size
= sizeof(struct sh_css_hmm_buffer
);
4298 /* TODO: change next to correct pool for optimization */
4299 ia_css_rmgr_acq_vbuf(hmm_buffer_pool
, &h_vbuf
);
4301 assert(h_vbuf
!= NULL
);
4302 assert(h_vbuf
->vptr
!= 0x0);
4304 if ((h_vbuf
== NULL
) || (h_vbuf
->vptr
== 0x0)) {
4305 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR
);
4306 return IA_CSS_ERR_INTERNAL_ERROR
;
4309 mmgr_store(h_vbuf
->vptr
,
4310 (void *)(&ddr_buffer
),
4311 sizeof(struct sh_css_hmm_buffer
));
4312 if ((buf_type
== IA_CSS_BUFFER_TYPE_3A_STATISTICS
)
4313 || (buf_type
== IA_CSS_BUFFER_TYPE_DIS_STATISTICS
)
4314 || (buf_type
== IA_CSS_BUFFER_TYPE_LACE_STATISTICS
)) {
4315 if (pipeline
== NULL
) {
4316 ia_css_rmgr_rel_vbuf(hmm_buffer_pool
, &h_vbuf
);
4317 IA_CSS_LOG("pipeline is empty!");
4318 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR
);
4319 return IA_CSS_ERR_INTERNAL_ERROR
;
4322 for (stage
= pipeline
->stages
; stage
; stage
= stage
->next
) {
4323 /* The SP will read the params
4324 after it got empty 3a and dis */
4325 if (STATS_ENABLED(stage
)) {
4326 /* there is a stage that needs it */
4327 return_err
= ia_css_bufq_enqueue_buffer(thread_id
,
4329 (uint32_t)h_vbuf
->vptr
);
4332 } else if ((buf_type
== IA_CSS_BUFFER_TYPE_INPUT_FRAME
)
4333 || (buf_type
== IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
)
4334 || (buf_type
== IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
)
4335 || (buf_type
== IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
)
4336 || (buf_type
== IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME
)
4337 || (buf_type
== IA_CSS_BUFFER_TYPE_METADATA
)) {
4339 return_err
= ia_css_bufq_enqueue_buffer(thread_id
,
4341 (uint32_t)h_vbuf
->vptr
);
4342 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4343 if ((return_err
== IA_CSS_SUCCESS
) && (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
== buf_type
)) {
4344 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4345 ddr_buffer
.payload
.frame
.frame_data
,
4346 queue_id
, thread_id
);
4352 if (return_err
== IA_CSS_SUCCESS
) {
4353 if (sh_css_hmm_buffer_record_acquire(
4355 HOST_ADDRESS(ddr_buffer
.kernel_ptr
))) {
4356 IA_CSS_LOG("send vbuf=%p", h_vbuf
);
4358 return_err
= IA_CSS_ERR_INTERNAL_ERROR
;
4359 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4364 * Tell the SP which queues are not empty,
4365 * by sending the software event.
4367 if (return_err
== IA_CSS_SUCCESS
) {
4368 if (!sh_css_sp_is_running()) {
4369 /* SP is not running. The queues are not valid */
4370 IA_CSS_LOG("SP is not running!");
4371 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
4372 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4374 return_err
= ia_css_bufq_enqueue_psys_event(
4375 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED
,
4380 ia_css_rmgr_rel_vbuf(hmm_buffer_pool
, &h_vbuf
);
4381 IA_CSS_ERROR("buffer not enqueued");
4384 IA_CSS_LEAVE("return value = %d", return_err
);
4390 * TODO: Free up the hmm memory space.
4393 ia_css_pipe_dequeue_buffer(struct ia_css_pipe
*pipe
,
4394 struct ia_css_buffer
*buffer
)
4396 enum ia_css_err return_err
;
4397 enum sh_css_queue_id queue_id
;
4398 hrt_vaddress ddr_buffer_addr
= (hrt_vaddress
)0;
4399 struct sh_css_hmm_buffer ddr_buffer
;
4400 enum ia_css_buffer_type buf_type
;
4401 enum ia_css_pipe_id pipe_id
;
4402 unsigned int thread_id
;
4403 hrt_address kernel_ptr
= 0;
4406 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe
, buffer
);
4408 if ((pipe
== NULL
) || (buffer
== NULL
)) {
4409 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4410 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4413 pipe_id
= pipe
->mode
;
4415 buf_type
= buffer
->type
;
4417 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id
, buf_type
);
4419 ddr_buffer
.kernel_ptr
= 0;
4421 ret_err
= ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
4423 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4424 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4427 ret_err
= ia_css_query_internal_queue_id(buf_type
, thread_id
, &queue_id
);
4429 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4430 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4433 if ((queue_id
<= SH_CSS_INVALID_QUEUE_ID
) || (queue_id
>= SH_CSS_MAX_NUM_QUEUES
)) {
4434 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4435 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4438 if (!sh_css_sp_is_running()) {
4439 IA_CSS_LOG("SP is not running!");
4440 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
4441 /* SP is not running. The queues are not valid */
4442 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4445 return_err
= ia_css_bufq_dequeue_buffer(queue_id
,
4446 (uint32_t *)&ddr_buffer_addr
);
4448 if (return_err
== IA_CSS_SUCCESS
) {
4449 struct ia_css_frame
*frame
;
4450 struct sh_css_hmm_buffer_record
*hmm_buffer_record
= NULL
;
4452 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr
);
4454 /* Validate the ddr_buffer_addr and buf_type */
4455 hmm_buffer_record
= sh_css_hmm_buffer_record_validate(
4456 ddr_buffer_addr
, buf_type
);
4457 if (hmm_buffer_record
!= NULL
) {
4458 /* valid hmm_buffer_record found. Save the kernel_ptr
4459 * for validation after performing mmgr_load. The
4460 * vbuf handle and buffer_record can be released.
4462 kernel_ptr
= hmm_buffer_record
->kernel_ptr
;
4463 ia_css_rmgr_rel_vbuf(hmm_buffer_pool
, &hmm_buffer_record
->h_vbuf
);
4464 sh_css_hmm_buffer_record_reset(hmm_buffer_record
);
4466 IA_CSS_ERROR("hmm_buffer_record not found (0x%u) buf_type(%d)",
4467 ddr_buffer_addr
, buf_type
);
4468 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR
);
4469 return IA_CSS_ERR_INTERNAL_ERROR
;
4472 mmgr_load(ddr_buffer_addr
,
4474 sizeof(struct sh_css_hmm_buffer
));
4476 /* if the kernel_ptr is 0 or an invalid, return an error.
4477 * do not access the buffer via the kernal_ptr.
4479 if ((ddr_buffer
.kernel_ptr
== 0) ||
4480 (kernel_ptr
!= HOST_ADDRESS(ddr_buffer
.kernel_ptr
))) {
4481 IA_CSS_ERROR("kernel_ptr invalid");
4482 IA_CSS_ERROR("expected: (0x%llx)", (u64
)kernel_ptr
);
4483 IA_CSS_ERROR("actual: (0x%llx)", (u64
)HOST_ADDRESS(ddr_buffer
.kernel_ptr
));
4484 IA_CSS_ERROR("buf_type: %d\n", buf_type
);
4485 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR
);
4486 return IA_CSS_ERR_INTERNAL_ERROR
;
4489 if (ddr_buffer
.kernel_ptr
!= 0) {
4490 /* buffer->exp_id : all instances to be removed later once the driver change
4491 * is completed. See patch #5758 for reference */
4493 buffer
->driver_cookie
= ddr_buffer
.cookie_ptr
;
4494 buffer
->timing_data
= ddr_buffer
.timing_data
;
4496 if ((buf_type
== IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
) ||
4497 (buf_type
== IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
)) {
4498 buffer
->isys_eof_clock_tick
.ticks
= ddr_buffer
.isys_eof_clock_tick
;
4502 case IA_CSS_BUFFER_TYPE_INPUT_FRAME
:
4503 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
:
4504 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
:
4505 if ((pipe
) && (pipe
->stop_requested
== true))
4508 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4509 /* free mipi frames only for old input system
4510 * for 2401 it is done in ia_css_stream_destroy call
4512 return_err
= free_mipi_frames(pipe
);
4513 if (return_err
!= IA_CSS_SUCCESS
) {
4514 IA_CSS_LOG("free_mipi_frames() failed");
4515 IA_CSS_LEAVE_ERR(return_err
);
4519 pipe
->stop_requested
= false;
4521 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
:
4522 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME
:
4523 frame
= (struct ia_css_frame
*)HOST_ADDRESS(ddr_buffer
.kernel_ptr
);
4524 buffer
->data
.frame
= frame
;
4525 buffer
->exp_id
= ddr_buffer
.payload
.frame
.exp_id
;
4526 frame
->exp_id
= ddr_buffer
.payload
.frame
.exp_id
;
4527 frame
->isp_config_id
= ddr_buffer
.payload
.frame
.isp_parameters_id
;
4528 if (ddr_buffer
.payload
.frame
.flashed
== 1)
4529 frame
->flash_state
=
4530 IA_CSS_FRAME_FLASH_STATE_PARTIAL
;
4531 if (ddr_buffer
.payload
.frame
.flashed
== 2)
4532 frame
->flash_state
=
4533 IA_CSS_FRAME_FLASH_STATE_FULL
;
4534 frame
->valid
= pipe
->num_invalid_frames
== 0;
4536 pipe
->num_invalid_frames
--;
4538 if (frame
->info
.format
== IA_CSS_FRAME_FORMAT_BINARY_8
) {
4539 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4540 frame
->planes
.binary
.size
= frame
->data_bytes
;
4542 frame
->planes
.binary
.size
=
4543 sh_css_sp_get_binary_copy_size();
4546 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4547 if (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
== buf_type
) {
4548 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4549 frame
->data
, frame
->isp_config_id
, thread_id
);
4553 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
4554 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4555 buf_type
, buffer
->data
.frame
->data
);
4558 case IA_CSS_BUFFER_TYPE_3A_STATISTICS
:
4559 buffer
->data
.stats_3a
=
4560 (struct ia_css_isp_3a_statistics
*)HOST_ADDRESS(ddr_buffer
.kernel_ptr
);
4561 buffer
->exp_id
= ddr_buffer
.payload
.s3a
.exp_id
;
4562 buffer
->data
.stats_3a
->exp_id
= ddr_buffer
.payload
.s3a
.exp_id
;
4563 buffer
->data
.stats_3a
->isp_config_id
= ddr_buffer
.payload
.s3a
.isp_config_id
;
4565 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS
:
4566 buffer
->data
.stats_dvs
=
4567 (struct ia_css_isp_dvs_statistics
*)
4568 HOST_ADDRESS(ddr_buffer
.kernel_ptr
);
4569 buffer
->exp_id
= ddr_buffer
.payload
.dis
.exp_id
;
4570 buffer
->data
.stats_dvs
->exp_id
= ddr_buffer
.payload
.dis
.exp_id
;
4572 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS
:
4574 case IA_CSS_BUFFER_TYPE_METADATA
:
4575 buffer
->data
.metadata
=
4576 (struct ia_css_metadata
*)HOST_ADDRESS(ddr_buffer
.kernel_ptr
);
4577 buffer
->exp_id
= ddr_buffer
.payload
.metadata
.exp_id
;
4578 buffer
->data
.metadata
->exp_id
= ddr_buffer
.payload
.metadata
.exp_id
;
4581 return_err
= IA_CSS_ERR_INTERNAL_ERROR
;
4588 * Tell the SP which queues are not full,
4589 * by sending the software event.
4591 if (return_err
== IA_CSS_SUCCESS
){
4592 if (!sh_css_sp_is_running()) {
4593 IA_CSS_LOG("SP is not running!");
4594 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
4595 /* SP is not running. The queues are not valid */
4596 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4598 ia_css_bufq_enqueue_psys_event(
4599 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED
,
4604 IA_CSS_LEAVE("buffer=%p", buffer
);
4610 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4611 * TODO: modify and move it if possible.
4613 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4614 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4615 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4616 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4617 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4619 static enum ia_css_event_type convert_event_sp_to_host_domain
[] = {
4620 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE
, /**< Output frame ready. */
4621 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE
, /**< Second output frame ready. */
4622 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE
, /**< Viewfinder Output frame ready. */
4623 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE
, /**< Second viewfinder Output frame ready. */
4624 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE
, /**< Indication that 3A statistics are available. */
4625 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE
, /**< Indication that DIS statistics are available. */
4626 IA_CSS_EVENT_TYPE_PIPELINE_DONE
, /**< Pipeline Done event, sent after last pipeline stage. */
4627 IA_CSS_EVENT_TYPE_FRAME_TAGGED
, /**< Frame tagged. */
4628 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE
, /**< Input frame ready. */
4629 IA_CSS_EVENT_TYPE_METADATA_DONE
, /**< Metadata ready. */
4630 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE
, /**< Indication that LACE statistics are available. */
4631 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE
, /**< Extension stage executed. */
4632 IA_CSS_EVENT_TYPE_TIMER
, /**< Timing measurement data. */
4633 IA_CSS_EVENT_TYPE_PORT_EOF
, /**< End Of Frame event, sent when in buffered sensor mode. */
4634 IA_CSS_EVENT_TYPE_FW_WARNING
, /**< Performance warning encountered by FW */
4635 IA_CSS_EVENT_TYPE_FW_ASSERT
, /**< Assertion hit by FW */
4636 0, /** error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4640 ia_css_dequeue_event(struct ia_css_event
*event
)
4642 return ia_css_dequeue_psys_event(event
);
4646 ia_css_dequeue_psys_event(struct ia_css_event
*event
)
4648 enum ia_css_pipe_id pipe_id
= 0;
4649 uint8_t payload
[4] = {0,0,0,0};
4650 enum ia_css_err ret_err
;
4653 * a) use generic decoding function , same as the one used by sp.
4654 * b) group decode and dequeue into eventQueue module
4656 * We skip the IA_CSS_ENTER logging call
4657 * to avoid flooding the logs when the host application
4660 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4662 if (!sh_css_sp_is_running()) {
4663 /* SP is not running. The queues are not valid */
4664 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4667 /* dequeue the event (if any) from the psys event queue */
4668 ret_err
= ia_css_bufq_dequeue_psys_event(payload
);
4669 if (ret_err
!= IA_CSS_SUCCESS
)
4672 IA_CSS_LOG("event dequeued from psys event queue");
4674 /* Tell the SP that we dequeued an event from the event queue. */
4675 ia_css_bufq_enqueue_psys_event(
4676 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED
, 0, 0, 0);
4678 /* Events are decoded into 4 bytes of payload, the first byte
4679 * contains the sp event type. This is converted to a host enum.
4680 * TODO: can this enum conversion be eliminated */
4681 event
->type
= convert_event_sp_to_host_domain
[payload
[0]];
4682 /* Some sane default values since not all events use all fields. */
4684 event
->port
= IA_CSS_CSI2_PORT0
;
4686 event
->fw_warning
= IA_CSS_FW_WARNING_NONE
;
4687 event
->fw_handle
= 0;
4688 event
->timer_data
= 0;
4689 event
->timer_code
= 0;
4690 event
->timer_subcode
= 0;
4692 if (event
->type
== IA_CSS_EVENT_TYPE_TIMER
) {
4693 /* timer event ??? get the 2nd event and decode the data into the event struct */
4695 /* 1st event: LSB 16-bit timer data and code */
4696 event
->timer_data
= ((payload
[1] & 0xFF) | ((payload
[3] & 0xFF) << 8));
4697 event
->timer_code
= payload
[2];
4698 payload
[0] = payload
[1] = payload
[2] = payload
[3] = 0;
4699 ret_err
= ia_css_bufq_dequeue_psys_event(payload
);
4700 if (ret_err
!= IA_CSS_SUCCESS
) {
4701 /* no 2nd event ??? an error */
4702 /* Putting IA_CSS_ERROR is resulting in failures in
4703 * Merrifield smoke testing */
4704 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4707 ia_css_bufq_enqueue_psys_event(
4708 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED
, 0, 0, 0);
4709 event
->type
= convert_event_sp_to_host_domain
[payload
[0]];
4711 if (event
->type
== IA_CSS_EVENT_TYPE_TIMER
) {
4712 /* 2nd event data: MSB 16-bit timer and subcode */
4713 tmp_data
= ((payload
[1] & 0xFF) | ((payload
[3] & 0xFF) << 8));
4714 event
->timer_data
|= (tmp_data
<< 16);
4715 event
->timer_subcode
= payload
[2];
4717 /* It's a non timer event. So clear first half of the timer event data.
4718 * If the second part of the TIMER event is not recieved, we discard
4719 * the first half of the timer data and process the non timer event without
4720 * affecting the flow. So the non timer event falls through
4723 event
->timer_data
= 0;
4724 event
->timer_code
= 0;
4725 event
->timer_subcode
= 0;
4726 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4729 if (event
->type
== IA_CSS_EVENT_TYPE_PORT_EOF
) {
4730 event
->port
= (enum ia_css_csi2_port
)payload
[1];
4731 event
->exp_id
= payload
[3];
4732 } else if (event
->type
== IA_CSS_EVENT_TYPE_FW_WARNING
) {
4733 event
->fw_warning
= (enum ia_css_fw_warning
)payload
[1];
4734 /* exp_id is only available in these warning types */
4735 if (event
->fw_warning
== IA_CSS_FW_WARNING_EXP_ID_LOCKED
||
4736 event
->fw_warning
== IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED
)
4737 event
->exp_id
= payload
[3];
4738 } else if (event
->type
== IA_CSS_EVENT_TYPE_FW_ASSERT
) {
4739 event
->fw_assert_module_id
= payload
[1]; /* module */
4740 event
->fw_assert_line_no
= (payload
[2] << 8) + payload
[3];
4741 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4742 } else if (event
->type
!= IA_CSS_EVENT_TYPE_TIMER
) {
4743 /* pipe related events.
4744 * payload[1] contains the pipe_num,
4745 * payload[2] contains the pipe_id. These are different. */
4746 event
->pipe
= find_pipe_by_num(payload
[1]);
4747 pipe_id
= (enum ia_css_pipe_id
)payload
[2];
4748 /* Check to see if pipe still exists */
4750 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4752 if (event
->type
== IA_CSS_EVENT_TYPE_FRAME_TAGGED
) {
4753 /* find the capture pipe that goes with this */
4755 n
= event
->pipe
->stream
->num_pipes
;
4756 for (i
= 0; i
< n
; i
++) {
4757 struct ia_css_pipe
*p
=
4758 event
->pipe
->stream
->pipes
[i
];
4759 if (p
->config
.mode
== IA_CSS_PIPE_MODE_CAPTURE
) {
4764 event
->exp_id
= payload
[3];
4766 if (event
->type
== IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE
) {
4767 /* payload[3] contains the acc fw handle. */
4768 uint32_t stage_num
= (uint32_t)payload
[3];
4769 ret_err
= ia_css_pipeline_get_fw_from_stage(
4770 &(event
->pipe
->pipeline
),
4772 &(event
->fw_handle
));
4773 if (ret_err
!= IA_CSS_SUCCESS
) {
4774 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4782 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event
->type
, pipe_id
);
4784 IA_CSS_LEAVE("event_id=%d", event
->type
);
4786 return IA_CSS_SUCCESS
;
4790 ia_css_dequeue_isys_event(struct ia_css_event
*event
)
4792 uint8_t payload
[4] = {0, 0, 0, 0};
4793 enum ia_css_err err
= IA_CSS_SUCCESS
;
4795 /* We skip the IA_CSS_ENTER logging call
4796 * to avoid flooding the logs when the host application
4799 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4801 if (!sh_css_sp_is_running()) {
4802 /* SP is not running. The queues are not valid */
4803 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4806 err
= ia_css_bufq_dequeue_isys_event(payload
);
4807 if (err
!= IA_CSS_SUCCESS
)
4810 IA_CSS_LOG("event dequeued from isys event queue");
4812 /* Update SP state to indicate that element was dequeued. */
4813 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED
);
4815 /* Fill return struct with appropriate info */
4816 event
->type
= IA_CSS_EVENT_TYPE_PORT_EOF
;
4817 /* EOF events are associated with a CSI port, not with a pipe */
4819 event
->port
= payload
[1];
4820 event
->exp_id
= payload
[3];
4822 IA_CSS_LEAVE_ERR(err
);
4827 acc_start(struct ia_css_pipe
*pipe
)
4829 assert(pipe
!= NULL
);
4830 assert(pipe
->stream
!= NULL
);
4832 start_pipe(pipe
, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD
,
4833 pipe
->stream
->config
.mode
);
4836 static enum ia_css_err
4837 sh_css_pipe_start(struct ia_css_stream
*stream
)
4839 enum ia_css_err err
= IA_CSS_SUCCESS
;
4841 struct ia_css_pipe
*pipe
;
4842 enum ia_css_pipe_id pipe_id
;
4843 unsigned int thread_id
;
4845 IA_CSS_ENTER_PRIVATE("stream = %p", stream
);
4847 if (stream
== NULL
) {
4848 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4849 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4851 pipe
= stream
->last_pipe
;
4853 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
4854 return IA_CSS_ERR_INVALID_ARGUMENTS
;
4857 pipe_id
= pipe
->mode
;
4859 if(stream
->started
== true) {
4860 IA_CSS_WARNING("Cannot start stream that is already started");
4861 IA_CSS_LEAVE_ERR(err
);
4865 pipe
->stop_requested
= false;
4868 case IA_CSS_PIPE_ID_PREVIEW
:
4869 err
= preview_start(pipe
);
4871 case IA_CSS_PIPE_ID_VIDEO
:
4872 err
= video_start(pipe
);
4874 case IA_CSS_PIPE_ID_CAPTURE
:
4875 err
= capture_start(pipe
);
4877 case IA_CSS_PIPE_ID_YUVPP
:
4878 err
= yuvpp_start(pipe
);
4880 case IA_CSS_PIPE_ID_ACC
:
4884 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
4886 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4887 if (!stream
->config
.continuous
) {
4889 for (i
= 1; i
< stream
->num_pipes
&& IA_CSS_SUCCESS
== err
; i
++) {
4890 switch (stream
->pipes
[i
]->mode
) {
4891 case IA_CSS_PIPE_ID_PREVIEW
:
4892 stream
->pipes
[i
]->stop_requested
= false;
4893 err
= preview_start(stream
->pipes
[i
]);
4895 case IA_CSS_PIPE_ID_VIDEO
:
4896 stream
->pipes
[i
]->stop_requested
= false;
4897 err
= video_start(stream
->pipes
[i
]);
4899 case IA_CSS_PIPE_ID_CAPTURE
:
4900 stream
->pipes
[i
]->stop_requested
= false;
4901 err
= capture_start(stream
->pipes
[i
]);
4903 case IA_CSS_PIPE_ID_YUVPP
:
4904 stream
->pipes
[i
]->stop_requested
= false;
4905 err
= yuvpp_start(stream
->pipes
[i
]);
4907 case IA_CSS_PIPE_ID_ACC
:
4908 stream
->pipes
[i
]->stop_requested
= false;
4909 acc_start(stream
->pipes
[i
]);
4912 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
4916 if (err
!= IA_CSS_SUCCESS
) {
4917 IA_CSS_LEAVE_ERR_PRIVATE(err
);
4921 /* Force ISP parameter calculation after a mode change
4922 * Acceleration API examples pass NULL for stream but they
4923 * don't use ISP parameters anyway. So this should be okay.
4924 * The SP binary (jpeg) copy does not use any parameters.
4926 if (!copy_on_sp(pipe
)) {
4927 sh_css_invalidate_params(stream
);
4928 err
= sh_css_param_update_isp_params(pipe
,
4929 stream
->isp_params_configs
, true, NULL
);
4930 if (err
!= IA_CSS_SUCCESS
) {
4931 IA_CSS_LEAVE_ERR_PRIVATE(err
);
4936 ia_css_debug_pipe_graph_dump_epilogue();
4938 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
4940 if (!sh_css_sp_is_running()) {
4941 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
4942 /* SP is not running. The queues are not valid */
4943 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
4945 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM
,
4946 (uint8_t)thread_id
, 0, 0);
4948 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4949 if (!stream
->config
.continuous
) {
4951 for (i
= 1; i
< stream
->num_pipes
; i
++) {
4952 ia_css_pipeline_get_sp_thread_id(
4953 ia_css_pipe_get_pipe_num(stream
->pipes
[i
]),
4955 ia_css_bufq_enqueue_psys_event(
4956 IA_CSS_PSYS_SW_EVENT_START_STREAM
,
4957 (uint8_t)thread_id
, 0, 0);
4961 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4962 if (pipe
->stream
->config
.continuous
) {
4963 struct ia_css_pipe
*copy_pipe
= NULL
;
4965 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
4966 copy_pipe
= pipe
->pipe_settings
.preview
.copy_pipe
;
4967 else if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
4968 copy_pipe
= pipe
->pipe_settings
.video
.copy_pipe
;
4970 if (copy_pipe
== NULL
) {
4971 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
4972 return IA_CSS_ERR_INTERNAL_ERROR
;
4974 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe
), &thread_id
);
4975 /* by the time we reach here q is initialized and handle is available.*/
4976 ia_css_bufq_enqueue_psys_event(
4977 IA_CSS_PSYS_SW_EVENT_START_STREAM
,
4978 (uint8_t)thread_id
, 0, 0);
4980 if (pipe
->stream
->cont_capt
) {
4981 struct ia_css_pipe
*capture_pipe
= NULL
;
4982 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
4983 capture_pipe
= pipe
->pipe_settings
.preview
.capture_pipe
;
4984 else if (pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
4985 capture_pipe
= pipe
->pipe_settings
.video
.capture_pipe
;
4987 if (capture_pipe
== NULL
) {
4988 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
4989 return IA_CSS_ERR_INTERNAL_ERROR
;
4991 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe
), &thread_id
);
4992 /* by the time we reach here q is initialized and handle is available.*/
4993 ia_css_bufq_enqueue_psys_event(
4994 IA_CSS_PSYS_SW_EVENT_START_STREAM
,
4995 (uint8_t)thread_id
, 0, 0);
4998 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
4999 if (pipe_id
== IA_CSS_PIPE_ID_PREVIEW
) {
5000 struct ia_css_pipe
*acc_pipe
= NULL
;
5001 acc_pipe
= pipe
->pipe_settings
.preview
.acc_pipe
;
5004 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe
), &thread_id
);
5005 /* by the time we reach here q is initialized and handle is available.*/
5006 ia_css_bufq_enqueue_psys_event(
5007 IA_CSS_PSYS_SW_EVENT_START_STREAM
,
5008 (uint8_t) thread_id
, 0, 0);
5012 stream
->started
= true;
5014 IA_CSS_LEAVE_ERR_PRIVATE(err
);
5020 sh_css_enable_cont_capt(bool enable
, bool stop_copy_preview
)
5022 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
5023 "sh_css_enable_cont_capt() enter: enable=%d\n", enable
);
5024 //my_css.cont_capt = enable;
5025 my_css
.stop_copy_preview
= stop_copy_preview
;
5029 sh_css_continuous_is_enabled(uint8_t pipe_num
)
5032 * @brief Stop all "ia_css_pipe" instances in the target
5033 * "ia_css_stream" instance.
5035 * Refer to "Local prototypes" for more info.
5037 static enum ia_css_err
5038 sh_css_pipes_stop(struct ia_css_stream
*stream
)
5042 struct ia_css_pipe
*pipe
;
5045 enum ia_css_err err
= IA_CSS_SUCCESS
;
5046 struct ia_css_pipe
*main_pipe
;
5047 enum ia_css_pipe_id main_pipe_id
;
5052 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num
);
5054 assert(stream
!= NULL
);
5055 if (stream
== NULL
) {
5056 IA_CSS_LOG("stream does NOT exist!");
5057 err
= IA_CSS_ERR_INTERNAL_ERROR
;
5063 pipe
= find_pipe_by_num(pipe_num
);
5064 continuous
= pipe
&& pipe
->stream
->config
.continuous
;
5065 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
5066 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5071 main_pipe
= stream
->last_pipe
;
5072 assert(main_pipe
!= NULL
);
5073 if (main_pipe
== NULL
) {
5074 IA_CSS_LOG("main_pipe does NOT exist!");
5075 err
= IA_CSS_ERR_INTERNAL_ERROR
;
5082 ia_css_stream_get_max_buffer_depth(struct ia_css_stream
*stream
, int *buffer_depth
)
5084 if (buffer_depth
== NULL
)
5085 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5086 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5088 *buffer_depth
= NUM_CONTINUOUS_FRAMES
;
5089 return IA_CSS_SUCCESS
;
5092 main_pipe_id
= main_pipe
->mode
;
5093 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id
);
5098 ia_css_stream_set_buffer_depth(struct ia_css_stream
*stream
, int buffer_depth
)
5100 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth
);
5102 if (buffer_depth
> NUM_CONTINUOUS_FRAMES
|| buffer_depth
< 1)
5103 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5104 /* ok, value allowed */
5105 stream
->config
.target_num_cont_raw_buf
= buffer_depth
;
5106 /* TODO: check what to regarding initialization */
5107 return IA_CSS_SUCCESS
;
5111 * Stop all "ia_css_pipe" instances in this target
5112 * "ia_css_stream" instance.
5114 for (i
= 0; i
< stream
->num_pipes
; i
++) {
5115 /* send the "stop" request to the "ia_css_pipe" instance */
5116 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5117 stream
->pipes
[i
]->pipeline
.pipe_id
);
5118 err
= ia_css_pipeline_request_stop(&stream
->pipes
[i
]->pipeline
);
5123 ia_css_stream_get_buffer_depth(struct ia_css_stream
*stream
, int *buffer_depth
)
5125 if (buffer_depth
== NULL
)
5126 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5127 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_get_buffer_depth() enter: void\n");
5130 * Exit this loop if "ia_css_pipeline_request_stop()"
5131 * returns the error code.
5133 * The error code would be generated in the following
5135 * (1) The Scalar Processor has already been stopped.
5136 * (2) The "Host->SP" event queue is full.
5138 * As the convention of using CSS API 2.0/2.1, such CSS
5139 * error code would be propogated from the CSS-internal
5140 * API returned value to the CSS API returned value. Then
5141 * the CSS driver should capture these error code and
5142 * handle it in the driver exception handling mechanism.
5144 if (err
!= IA_CSS_SUCCESS
) {
5150 * In the CSS firmware use scenario "Continuous Preview"
5151 * as well as "Continuous Video", the "ia_css_pipe" instance
5152 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5153 * the CSS firmware so that it is not listed in the target
5154 * "ia_css_stream" instance.
5156 * We need to stop this "Copy Pipe", as well.
5158 if (main_pipe
->stream
->config
.continuous
) {
5159 struct ia_css_pipe
*copy_pipe
= NULL
;
5161 /* get the reference to "Copy Pipe" */
5162 if (main_pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
5163 copy_pipe
= main_pipe
->pipe_settings
.preview
.copy_pipe
;
5164 else if (main_pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
5165 copy_pipe
= main_pipe
->pipe_settings
.video
.copy_pipe
;
5167 /* return the error code if "Copy Pipe" does NOT exist */
5168 assert(copy_pipe
!= NULL
);
5169 if (copy_pipe
== NULL
) {
5170 IA_CSS_LOG("Copy Pipe does NOT exist!");
5171 err
= IA_CSS_ERR_INTERNAL_ERROR
;
5175 /* send the "stop" request to "Copy Pipe" */
5176 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5177 copy_pipe
->pipeline
.pipe_id
);
5178 err
= ia_css_pipeline_request_stop(©_pipe
->pipeline
);
5182 IA_CSS_LEAVE_ERR_PRIVATE(err
);
5187 * @brief Check if all "ia_css_pipe" instances in the target
5188 * "ia_css_stream" instance have stopped.
5190 * Refer to "Local prototypes" for more info.
5193 sh_css_pipes_have_stopped(struct ia_css_stream
*stream
)
5197 struct ia_css_pipe
*main_pipe
;
5198 enum ia_css_pipe_id main_pipe_id
;
5202 assert(stream
!= NULL
);
5203 if (stream
== NULL
) {
5204 IA_CSS_LOG("stream does NOT exist!");
5209 main_pipe
= stream
->last_pipe
;
5210 assert(main_pipe
!= NULL
);
5212 if (main_pipe
== NULL
) {
5213 IA_CSS_LOG("main_pipe does NOT exist!");
5218 main_pipe_id
= main_pipe
->mode
;
5219 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id
);
5222 * Check if every "ia_css_pipe" instance in this target
5223 * "ia_css_stream" instance has stopped.
5225 for (i
= 0; i
< stream
->num_pipes
; i
++) {
5226 rval
= rval
&& ia_css_pipeline_has_stopped(&stream
->pipes
[i
]->pipeline
);
5227 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5228 stream
->pipes
[i
]->pipeline
.pipe_id
,
5233 * In the CSS firmware use scenario "Continuous Preview"
5234 * as well as "Continuous Video", the "ia_css_pipe" instance
5235 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5236 * the CSS firmware so that it is not listed in the target
5237 * "ia_css_stream" instance.
5239 * We need to check if this "Copy Pipe" has stopped, as well.
5241 if (main_pipe
->stream
->config
.continuous
) {
5242 struct ia_css_pipe
*copy_pipe
= NULL
;
5244 /* get the reference to "Copy Pipe" */
5245 if (main_pipe_id
== IA_CSS_PIPE_ID_PREVIEW
)
5246 copy_pipe
= main_pipe
->pipe_settings
.preview
.copy_pipe
;
5247 else if (main_pipe_id
== IA_CSS_PIPE_ID_VIDEO
)
5248 copy_pipe
= main_pipe
->pipe_settings
.video
.copy_pipe
;
5250 /* return if "Copy Pipe" does NOT exist */
5251 assert(copy_pipe
!= NULL
);
5252 if (copy_pipe
== NULL
) {
5253 IA_CSS_LOG("Copy Pipe does NOT exist!");
5259 /* check if "Copy Pipe" has stopped or not */
5260 rval
= rval
&& ia_css_pipeline_has_stopped(©_pipe
->pipeline
);
5261 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5262 copy_pipe
->pipeline
.pipe_id
,
5267 IA_CSS_LEAVE_PRIVATE("rval=%d", rval
);
5272 sh_css_continuous_is_enabled(uint8_t pipe_num
)
5274 struct ia_css_pipe
*pipe
;
5277 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num
);
5279 pipe
= find_pipe_by_num(pipe_num
);
5280 continuous
= pipe
&& pipe
->stream
->config
.continuous
;
5281 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
5282 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5288 ia_css_stream_get_max_buffer_depth(struct ia_css_stream
*stream
, int *buffer_depth
)
5290 if (buffer_depth
== NULL
)
5291 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5292 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5294 *buffer_depth
= NUM_CONTINUOUS_FRAMES
;
5295 return IA_CSS_SUCCESS
;
5299 ia_css_stream_set_buffer_depth(struct ia_css_stream
*stream
, int buffer_depth
)
5301 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth
);
5303 if (buffer_depth
> NUM_CONTINUOUS_FRAMES
|| buffer_depth
< 1)
5304 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5305 /* ok, value allowed */
5306 stream
->config
.target_num_cont_raw_buf
= buffer_depth
;
5307 /* TODO: check what to regarding initialization */
5308 return IA_CSS_SUCCESS
;
5312 ia_css_stream_get_buffer_depth(struct ia_css_stream
*stream
, int *buffer_depth
)
5314 if (buffer_depth
== NULL
)
5315 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5316 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_get_buffer_depth() enter: void\n");
5319 *buffer_depth
= stream
->config
.target_num_cont_raw_buf
;
5320 return IA_CSS_SUCCESS
;
5323 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5325 sh_css_get_mipi_sizes_for_check(const unsigned int port
, const unsigned int idx
)
5327 OP___assert(port
< N_CSI_PORTS
);
5328 OP___assert(idx
< IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT
);
5329 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5330 port
, idx
, my_css
.mipi_sizes_for_check
[port
][idx
]);
5331 return my_css
.mipi_sizes_for_check
[port
][idx
];
5335 static enum ia_css_err
sh_css_pipe_configure_output(
5336 struct ia_css_pipe
*pipe
,
5338 unsigned int height
,
5339 unsigned int padded_width
,
5340 enum ia_css_frame_format format
,
5343 enum ia_css_err err
= IA_CSS_SUCCESS
;
5345 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d",
5346 pipe
, width
, height
, padded_width
, format
, idx
);
5348 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
5349 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5352 err
= ia_css_util_check_res(width
, height
);
5353 if (err
!= IA_CSS_SUCCESS
) {
5354 IA_CSS_LEAVE_ERR_PRIVATE(err
);
5357 if (pipe
->output_info
[idx
].res
.width
!= width
||
5358 pipe
->output_info
[idx
].res
.height
!= height
||
5359 pipe
->output_info
[idx
].format
!= format
)
5361 ia_css_frame_info_init(
5362 &pipe
->output_info
[idx
],
5368 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
5369 return IA_CSS_SUCCESS
;
5372 static enum ia_css_err
5373 sh_css_pipe_get_shading_info(struct ia_css_pipe
*pipe
,
5375 struct ia_css_shading_info
*info
)
5377 struct ia_css_shading_info
*shading_info
,
5378 struct ia_css_pipe_config
*pipe_config
)
5381 enum ia_css_err err
= IA_CSS_SUCCESS
;
5382 struct ia_css_binary
*binary
= NULL
;
5384 assert(pipe
!= NULL
);
5386 assert(info
!= NULL
);
5388 assert(shading_info
!= NULL
);
5389 assert(pipe_config
!= NULL
);
5391 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
5392 "sh_css_pipe_get_shading_info() enter:\n");
5394 binary
= ia_css_pipe_get_shading_correction_binary(pipe
);
5397 err
= ia_css_binary_get_shading_info(binary
,
5398 IA_CSS_SHADING_CORRECTION_TYPE_1
,
5399 pipe
->required_bds_factor
,
5400 (const struct ia_css_stream_config
*)&pipe
->stream
->config
,
5404 shading_info
, pipe_config
);
5406 /* Other function calls can be added here when other shading correction types will be added
5410 /* When the pipe does not have a binary which has the shading
5411 * correction, this function does not need to fill the shading
5412 * information. It is not a error case, and then
5413 * this function should return IA_CSS_SUCCESS.
5416 memset(info
, 0, sizeof(*info
));
5418 memset(shading_info
, 0, sizeof(*shading_info
));
5424 static enum ia_css_err
5425 sh_css_pipe_get_grid_info(struct ia_css_pipe
*pipe
,
5426 struct ia_css_grid_info
*info
)
5428 enum ia_css_err err
= IA_CSS_SUCCESS
;
5429 struct ia_css_binary
*binary
= NULL
;
5431 assert(pipe
!= NULL
);
5432 assert(info
!= NULL
);
5434 IA_CSS_ENTER_PRIVATE("");
5436 binary
= ia_css_pipe_get_s3a_binary(pipe
);
5439 err
= ia_css_binary_3a_grid_info(binary
, info
, pipe
);
5440 if (err
!= IA_CSS_SUCCESS
)
5443 memset(&info
->s3a_grid
, 0, sizeof(info
->s3a_grid
));
5445 binary
= ia_css_pipe_get_sdis_binary(pipe
);
5448 ia_css_binary_dvs_grid_info(binary
, info
, pipe
);
5449 ia_css_binary_dvs_stat_grid_info(binary
, info
, pipe
);
5451 memset(&info
->dvs_grid
.dvs_grid_info
, 0,
5452 sizeof(info
->dvs_grid
.dvs_grid_info
));
5453 memset(&info
->dvs_grid
.dvs_stat_grid_info
, 0,
5454 sizeof(info
->dvs_grid
.dvs_stat_grid_info
));
5457 if (binary
!= NULL
) {
5458 /* copy pipe does not have ISP binary*/
5459 info
->isp_in_width
= binary
->internal_frame_info
.res
.width
;
5460 info
->isp_in_height
= binary
->internal_frame_info
.res
.height
;
5463 #if defined(HAS_VAMEM_VERSION_2)
5464 info
->vamem_type
= IA_CSS_VAMEM_TYPE_2
;
5465 #elif defined(HAS_VAMEM_VERSION_1)
5466 info
->vamem_type
= IA_CSS_VAMEM_TYPE_1
;
5468 #error "Unknown VAMEM version"
5472 IA_CSS_LEAVE_ERR_PRIVATE(err
);
5478 * @brief Check if a format is supported by the pipe.
5481 static enum ia_css_err
5482 ia_css_pipe_check_format(struct ia_css_pipe
*pipe
, enum ia_css_frame_format format
)
5484 const enum ia_css_frame_format
*supported_formats
;
5485 int number_of_formats
;
5489 IA_CSS_ENTER_PRIVATE("");
5491 if (NULL
== pipe
|| NULL
== pipe
->pipe_settings
.video
.video_binary
.info
) {
5492 IA_CSS_ERROR("Pipe or binary info is not set");
5493 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
5494 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5497 supported_formats
= pipe
->pipe_settings
.video
.video_binary
.info
->output_formats
;
5498 number_of_formats
= sizeof(pipe
->pipe_settings
.video
.video_binary
.info
->output_formats
)/sizeof(enum ia_css_frame_format
);
5500 for (i
= 0; i
< number_of_formats
&& !found
; i
++) {
5501 if (supported_formats
[i
] == format
) {
5507 IA_CSS_ERROR("Requested format is not supported by binary");
5508 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
5509 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5511 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
5512 return IA_CSS_SUCCESS
;
5517 static enum ia_css_err
load_video_binaries(struct ia_css_pipe
*pipe
)
5519 struct ia_css_frame_info video_in_info
, tnr_info
,
5520 *video_vf_info
, video_bds_out_info
, *pipe_out_info
, *pipe_vf_out_info
;
5522 enum ia_css_err err
= IA_CSS_SUCCESS
;
5523 bool continuous
= pipe
->stream
->config
.continuous
;
5525 unsigned num_output_pins
;
5526 struct ia_css_frame_info video_bin_out_info
;
5527 bool need_scaler
= false;
5528 bool vf_res_different_than_output
= false;
5529 bool need_vf_pp
= false;
5531 struct ia_css_video_settings
*mycs
= &pipe
->pipe_settings
.video
;
5533 IA_CSS_ENTER_PRIVATE("");
5534 assert(pipe
!= NULL
);
5535 assert(pipe
->mode
== IA_CSS_PIPE_ID_VIDEO
);
5536 /* we only test the video_binary because offline video doesn't need a
5537 * vf_pp binary and online does not (always use) the copy_binary.
5538 * All are always reset at the same time anyway.
5540 if (mycs
->video_binary
.info
)
5541 return IA_CSS_SUCCESS
;
5543 online
= pipe
->stream
->config
.online
;
5544 pipe_out_info
= &pipe
->output_info
[0];
5545 pipe_vf_out_info
= &pipe
->vf_output_info
[0];
5547 assert(pipe_out_info
!= NULL
);
5550 * There is no explicit input format requirement for raw or yuv
5551 * What matters is that there is a binary that supports the stream format.
5552 * This is checked in the binary_find(), so no need to check it here
5554 err
= ia_css_util_check_input(&pipe
->stream
->config
, false, false);
5555 if (err
!= IA_CSS_SUCCESS
)
5557 /* cannot have online video and input_mode memory */
5558 if (online
&& pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
)
5559 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5560 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
]) {
5561 err
= ia_css_util_check_vf_out_info(pipe_out_info
,
5563 if (err
!= IA_CSS_SUCCESS
)
5566 err
= ia_css_frame_check_info(pipe_out_info
);
5567 if (err
!= IA_CSS_SUCCESS
)
5571 if (pipe
->out_yuv_ds_input_info
.res
.width
)
5572 video_bin_out_info
= pipe
->out_yuv_ds_input_info
;
5574 video_bin_out_info
= *pipe_out_info
;
5577 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
]){
5578 video_vf_info
= pipe_vf_out_info
;
5579 vf_res_different_than_output
= (video_vf_info
->res
.width
!= video_bin_out_info
.res
.width
) ||
5580 (video_vf_info
->res
.height
!= video_bin_out_info
.res
.height
);
5583 video_vf_info
= NULL
;
5586 need_scaler
= need_downscaling(video_bin_out_info
.res
, pipe_out_info
->res
);
5588 /* we build up the pipeline starting at the end */
5589 /* YUV post-processing if needed */
5591 struct ia_css_cas_binary_descr cas_scaler_descr
5592 = IA_CSS_DEFAULT_CAS_BINARY_DESCR
;
5594 /* NV12 is the common format that is supported by both */
5595 /* yuv_scaler and the video_xx_isp2_min binaries. */
5596 video_bin_out_info
.format
= IA_CSS_FRAME_FORMAT_NV12
;
5598 err
= ia_css_pipe_create_cas_scaler_desc_single_output(
5599 &video_bin_out_info
,
5603 if (err
!= IA_CSS_SUCCESS
)
5605 mycs
->num_yuv_scaler
= cas_scaler_descr
.num_stage
;
5606 mycs
->yuv_scaler_binary
= kzalloc(cas_scaler_descr
.num_stage
*
5607 sizeof(struct ia_css_binary
), GFP_KERNEL
);
5608 if (!mycs
->yuv_scaler_binary
) {
5609 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
5612 mycs
->is_output_stage
= kzalloc(cas_scaler_descr
.num_stage
5613 * sizeof(bool), GFP_KERNEL
);
5614 if (!mycs
->is_output_stage
) {
5615 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
5618 for (i
= 0; i
< cas_scaler_descr
.num_stage
; i
++) {
5619 struct ia_css_binary_descr yuv_scaler_descr
;
5620 mycs
->is_output_stage
[i
] = cas_scaler_descr
.is_output_stage
[i
];
5621 ia_css_pipe_get_yuvscaler_binarydesc(pipe
,
5622 &yuv_scaler_descr
, &cas_scaler_descr
.in_info
[i
],
5623 &cas_scaler_descr
.out_info
[i
],
5624 &cas_scaler_descr
.internal_out_info
[i
],
5625 &cas_scaler_descr
.vf_info
[i
]);
5626 err
= ia_css_binary_find(&yuv_scaler_descr
,
5627 &mycs
->yuv_scaler_binary
[i
]);
5628 if (err
!= IA_CSS_SUCCESS
) {
5629 kfree(mycs
->is_output_stage
);
5630 mycs
->is_output_stage
= NULL
;
5634 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr
);
5639 struct ia_css_binary_descr video_descr
;
5640 enum ia_css_frame_format vf_info_format
;
5642 err
= ia_css_pipe_get_video_binarydesc(pipe
,
5643 &video_descr
, &video_in_info
, &video_bds_out_info
, &video_bin_out_info
, video_vf_info
,
5644 pipe
->stream
->config
.left_padding
);
5645 if (err
!= IA_CSS_SUCCESS
)
5648 /* In the case where video_vf_info is not NULL, this allows
5649 * us to find a potential video library with desired vf format.
5650 * If success, no vf_pp binary is needed.
5651 * If failed, we will look up video binary with YUV_LINE vf format
5653 err
= ia_css_binary_find(&video_descr
,
5654 &mycs
->video_binary
);
5656 if (err
!= IA_CSS_SUCCESS
) {
5657 if (video_vf_info
) {
5658 /* This will do another video binary lookup later for YUV_LINE format*/
5662 } else if (video_vf_info
) {
5663 /* The first video binary lookup is successful, but we may
5664 * still need vf_pp binary based on additiona check */
5665 num_output_pins
= mycs
->video_binary
.info
->num_output_pins
;
5666 vf_ds_log2
= mycs
->video_binary
.vf_downscale_log2
;
5668 /* If the binary has dual output pins, we need vf_pp if the resolution
5670 need_vf_pp
|= ((num_output_pins
== 2) && vf_res_different_than_output
);
5672 /* If the binary has single output pin, we need vf_pp if additional
5673 * scaling is needed for vf */
5674 need_vf_pp
|= ((num_output_pins
== 1) &&
5675 ((video_vf_info
->res
.width
<< vf_ds_log2
!= pipe_out_info
->res
.width
) ||
5676 (video_vf_info
->res
.height
<< vf_ds_log2
!= pipe_out_info
->res
.height
)));
5680 /* save the current vf_info format for restoration later */
5681 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
5682 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5684 vf_info_format
= video_vf_info
->format
;
5686 if (!pipe
->config
.enable_vfpp_bci
)
5687 ia_css_frame_info_set_format(video_vf_info
,
5688 IA_CSS_FRAME_FORMAT_YUV_LINE
);
5690 ia_css_binary_destroy_isp_parameters(&mycs
->video_binary
);
5692 err
= ia_css_binary_find(&video_descr
,
5693 &mycs
->video_binary
);
5695 /* restore original vf_info format */
5696 ia_css_frame_info_set_format(video_vf_info
,
5698 if (err
!= IA_CSS_SUCCESS
)
5703 /* If a video binary does not use a ref_frame, we set the frame delay
5704 * to 0. This is the case for the 1-stage low-power video binary. */
5705 if (!mycs
->video_binary
.info
->sp
.enable
.ref_frame
)
5706 pipe
->dvs_frame_delay
= 0;
5708 /* The delay latency determines the number of invalid frames after
5709 * a stream is started. */
5710 pipe
->num_invalid_frames
= pipe
->dvs_frame_delay
;
5711 pipe
->info
.num_invalid_frames
= pipe
->num_invalid_frames
;
5713 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5714 * outputs a viewfinder output, then we need double the number of
5717 pipe
->num_invalid_frames
*= 2;
5719 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
5720 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5721 pipe
->num_invalid_frames
, pipe
->dvs_frame_delay
);
5723 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5724 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5726 if (!online
&& !continuous
) {
5727 /* TODO: what exactly needs doing, prepend the copy binary to
5728 * video base this only on !online?
5730 err
= load_copy_binary(pipe
,
5732 &mycs
->video_binary
);
5733 if (err
!= IA_CSS_SUCCESS
)
5740 #if !defined(HAS_OUTPUT_SYSTEM)
5741 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
] && need_vf_pp
) {
5742 struct ia_css_binary_descr vf_pp_descr
;
5744 if (mycs
->video_binary
.vf_frame_info
.format
5745 == IA_CSS_FRAME_FORMAT_YUV_LINE
) {
5746 ia_css_pipe_get_vfpp_binarydesc(pipe
, &vf_pp_descr
,
5747 &mycs
->video_binary
.vf_frame_info
,
5750 /* output from main binary is not yuv line. currently this is
5751 * possible only when bci is enabled on vfpp output */
5752 assert(pipe
->config
.enable_vfpp_bci
== true);
5753 ia_css_pipe_get_yuvscaler_binarydesc(pipe
, &vf_pp_descr
,
5754 &mycs
->video_binary
.vf_frame_info
,
5755 pipe_vf_out_info
, NULL
, NULL
);
5758 err
= ia_css_binary_find(&vf_pp_descr
,
5759 &mycs
->vf_pp_binary
);
5760 if (err
!= IA_CSS_SUCCESS
)
5765 err
= allocate_delay_frames(pipe
);
5767 if (err
!= IA_CSS_SUCCESS
)
5770 if (mycs
->video_binary
.info
->sp
.enable
.block_output
) {
5772 unsigned int tnr_width
;
5773 unsigned int tnr_height
;
5775 tnr_info
= mycs
->video_binary
.out_frame_info
[0];
5778 /* Select resolution for TNR. If
5779 * output_system_in_resolution(GDC_out_resolution) is
5780 * being used, then select that as it will also be in resolution for
5781 * TNR. At present, it only make sense for Skycam */
5782 if (pipe
->config
.output_system_in_res
.width
&& pipe
->config
.output_system_in_res
.height
) {
5783 tnr_width
= pipe
->config
.output_system_in_res
.width
;
5784 tnr_height
= pipe
->config
.output_system_in_res
.height
;
5786 tnr_width
= tnr_info
.res
.width
;
5787 tnr_height
= tnr_info
.res
.height
;
5790 /* Make tnr reference buffers output block width(in pix) align */
5791 tnr_info
.res
.width
=
5793 (mycs
->video_binary
.info
->sp
.block
.block_width
* ISP_NWAY
));
5794 tnr_info
.padded_width
= tnr_info
.res
.width
;
5797 /* Make tnr reference buffers output block height align */
5799 tnr_info
.res
.height
=
5800 CEIL_MUL(tnr_info
.res
.height
,
5801 mycs
->video_binary
.info
->sp
.block
.output_block_height
);
5803 tnr_info
.res
.height
=
5804 CEIL_MUL(tnr_height
,
5805 mycs
->video_binary
.info
->sp
.block
.output_block_height
);
5808 tnr_info
= mycs
->video_binary
.internal_frame_info
;
5810 tnr_info
.format
= IA_CSS_FRAME_FORMAT_YUV_LINE
;
5811 tnr_info
.raw_bit_depth
= SH_CSS_TNR_BIT_DEPTH
;
5814 for (i
= 0; i
< NUM_VIDEO_TNR_FRAMES
; i
++) {
5816 for (i
= 0; i
< NUM_TNR_FRAMES
; i
++) {
5818 if (mycs
->tnr_frames
[i
]) {
5819 ia_css_frame_free(mycs
->tnr_frames
[i
]);
5820 mycs
->tnr_frames
[i
] = NULL
;
5822 err
= ia_css_frame_allocate_from_info(
5823 &mycs
->tnr_frames
[i
],
5825 if (err
!= IA_CSS_SUCCESS
)
5828 IA_CSS_LEAVE_PRIVATE("");
5829 return IA_CSS_SUCCESS
;
5832 static enum ia_css_err
5833 unload_video_binaries(struct ia_css_pipe
*pipe
)
5836 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
5838 if ((pipe
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_VIDEO
)) {
5839 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
5840 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5842 ia_css_binary_unload(&pipe
->pipe_settings
.video
.copy_binary
);
5843 ia_css_binary_unload(&pipe
->pipe_settings
.video
.video_binary
);
5844 ia_css_binary_unload(&pipe
->pipe_settings
.video
.vf_pp_binary
);
5846 ia_css_binary_unload(&pipe
->pipe_settings
.video
.vf_pp_binary
);
5849 for (i
= 0; i
< pipe
->pipe_settings
.video
.num_yuv_scaler
; i
++)
5850 ia_css_binary_unload(&pipe
->pipe_settings
.video
.yuv_scaler_binary
[i
]);
5852 kfree(pipe
->pipe_settings
.video
.is_output_stage
);
5853 pipe
->pipe_settings
.video
.is_output_stage
= NULL
;
5854 kfree(pipe
->pipe_settings
.video
.yuv_scaler_binary
);
5855 pipe
->pipe_settings
.video
.yuv_scaler_binary
= NULL
;
5857 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
5858 return IA_CSS_SUCCESS
;
5861 static enum ia_css_err
video_start(struct ia_css_pipe
*pipe
)
5863 struct ia_css_binary
*copy_binary
;
5864 enum ia_css_err err
= IA_CSS_SUCCESS
;
5865 struct ia_css_pipe
*copy_pipe
, *capture_pipe
;
5866 enum sh_css_pipe_config_override copy_ovrd
;
5867 enum ia_css_input_mode video_pipe_input_mode
;
5870 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
5871 if ((pipe
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_VIDEO
)) {
5872 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
5873 return IA_CSS_ERR_INVALID_ARGUMENTS
;
5876 video_pipe_input_mode
= pipe
->stream
->config
.mode
;
5878 copy_pipe
= pipe
->pipe_settings
.video
.copy_pipe
;
5879 capture_pipe
= pipe
->pipe_settings
.video
.capture_pipe
;
5881 copy_binary
= &pipe
->pipe_settings
.video
.copy_binary
;
5883 sh_css_metrics_start_frame();
5885 /* multi stream video needs mipi buffers */
5887 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5888 err
= send_mipi_frames(pipe
);
5889 if (err
!= IA_CSS_SUCCESS
)
5893 send_raw_frames(pipe
);
5895 unsigned int thread_id
;
5897 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
5898 copy_ovrd
= 1 << thread_id
;
5900 if (pipe
->stream
->cont_capt
) {
5901 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe
), &thread_id
);
5902 copy_ovrd
|= 1 << thread_id
;
5906 /* Construct and load the copy pipe */
5907 if (pipe
->stream
->config
.continuous
) {
5908 sh_css_sp_init_pipeline(©_pipe
->pipeline
,
5909 IA_CSS_PIPE_ID_COPY
,
5910 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe
),
5912 pipe
->stream
->config
.pixels_per_clock
== 2, false,
5913 false, pipe
->required_bds_factor
,
5915 pipe
->stream
->config
.mode
,
5916 &pipe
->stream
->config
.metadata_config
,
5918 &pipe
->stream
->info
.metadata_info
5920 &pipe
->stream
->info
.metadata_info
,
5922 #if !defined(HAS_NO_INPUT_SYSTEM)
5924 , pipe
->stream
->config
.source
.port
.port
5926 pipe
->stream
->config
.source
.port
.port
,
5932 ©_pipe
->config
.internal_frame_origin_bqs_on_sctbl
,
5933 copy_pipe
->stream
->isp_params_configs
);
5936 /* make the video pipe start with mem mode input, copy handles
5938 video_pipe_input_mode
= IA_CSS_INPUT_MODE_MEMORY
;
5941 /* Construct and load the capture pipe */
5942 if (pipe
->stream
->cont_capt
) {
5943 sh_css_sp_init_pipeline(&capture_pipe
->pipeline
,
5944 IA_CSS_PIPE_ID_CAPTURE
,
5945 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe
),
5946 capture_pipe
->config
.default_capture_config
.enable_xnr
!= 0,
5947 capture_pipe
->stream
->config
.pixels_per_clock
== 2,
5948 true, /* continuous */
5949 false, /* offline */
5950 capture_pipe
->required_bds_factor
,
5952 IA_CSS_INPUT_MODE_MEMORY
,
5953 &pipe
->stream
->config
.metadata_config
,
5955 &pipe
->stream
->info
.metadata_info
5957 &pipe
->stream
->info
.metadata_info
,
5959 #if !defined(HAS_NO_INPUT_SYSTEM)
5969 &capture_pipe
->config
.internal_frame_origin_bqs_on_sctbl
,
5970 capture_pipe
->stream
->isp_params_configs
);
5974 start_pipe(pipe
, copy_ovrd
, video_pipe_input_mode
);
5976 IA_CSS_LEAVE_ERR_PRIVATE(err
);
5981 enum ia_css_err
sh_css_pipe_get_viewfinder_frame_info(
5982 struct ia_css_pipe
*pipe
,
5983 struct ia_css_frame_info
*info
,
5986 assert(pipe
!= NULL
);
5987 assert(info
!= NULL
);
5989 /* We could print the pointer as input arg, and the values as output */
5990 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5992 if ( pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
&&
5993 (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_RAW
||
5994 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
))
5995 return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER
;
5996 /* offline video does not generate viewfinder output */
5997 *info
= pipe
->vf_output_info
[idx
];
5999 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
6000 "sh_css_pipe_get_viewfinder_frame_info() leave: \
6001 info.res.width=%d, info.res.height=%d, \
6002 info.padded_width=%d, info.format=%d, \
6003 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
6004 info
->res
.width
,info
->res
.height
,
6005 info
->padded_width
,info
->format
,
6006 info
->raw_bit_depth
,info
->raw_bayer_order
);
6008 return IA_CSS_SUCCESS
;
6011 static enum ia_css_err
6012 sh_css_pipe_configure_viewfinder(struct ia_css_pipe
*pipe
, unsigned int width
,
6013 unsigned int height
, unsigned int min_width
,
6014 enum ia_css_frame_format format
,
6017 enum ia_css_err err
= IA_CSS_SUCCESS
;
6019 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
6020 pipe
, width
, height
, min_width
, format
, idx
);
6023 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
6024 return IA_CSS_ERR_INVALID_ARGUMENTS
;
6028 err
= ia_css_util_check_res(width
, height
);
6029 if (err
!= IA_CSS_SUCCESS
) {
6030 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6033 if (pipe
->vf_output_info
[idx
].res
.width
!= width
||
6034 pipe
->vf_output_info
[idx
].res
.height
!= height
||
6035 pipe
->vf_output_info
[idx
].format
!= format
) {
6036 ia_css_frame_info_init(&pipe
->vf_output_info
[idx
], width
, height
,
6039 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
6040 return IA_CSS_SUCCESS
;
6043 static enum ia_css_err
load_copy_binaries(struct ia_css_pipe
*pipe
)
6045 enum ia_css_err err
= IA_CSS_SUCCESS
;
6047 assert(pipe
!= NULL
);
6048 IA_CSS_ENTER_PRIVATE("");
6050 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6051 if (pipe
->pipe_settings
.capture
.copy_binary
.info
)
6052 return IA_CSS_SUCCESS
;
6054 err
= ia_css_frame_check_info(&pipe
->output_info
[0]);
6055 if (err
!= IA_CSS_SUCCESS
)
6058 err
= verify_copy_out_frame_format(pipe
);
6059 if (err
!= IA_CSS_SUCCESS
)
6062 err
= load_copy_binary(pipe
,
6063 &pipe
->pipe_settings
.capture
.copy_binary
,
6067 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6071 static bool need_capture_pp(
6072 const struct ia_css_pipe
*pipe
)
6074 const struct ia_css_frame_info
*out_info
= &pipe
->output_info
[0];
6075 IA_CSS_ENTER_LEAVE_PRIVATE("");
6076 assert(pipe
!= NULL
);
6077 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
);
6080 /* ldc and capture_pp are not supported in the same pipeline */
6081 if (need_capt_ldc(pipe
) == true)
6084 /* determine whether we need to use the capture_pp binary.
6085 * This is needed for:
6087 * 2. Digital Zoom or
6088 * 3. YUV downscaling
6090 if (pipe
->out_yuv_ds_input_info
.res
.width
&&
6091 ((pipe
->out_yuv_ds_input_info
.res
.width
!= out_info
->res
.width
) ||
6092 (pipe
->out_yuv_ds_input_info
.res
.height
!= out_info
->res
.height
)))
6095 if (pipe
->config
.default_capture_config
.enable_xnr
!= 0)
6098 if ((pipe
->stream
->isp_params_configs
->dz_config
.dx
< HRT_GDC_N
) ||
6099 (pipe
->stream
->isp_params_configs
->dz_config
.dy
< HRT_GDC_N
) ||
6100 pipe
->config
.enable_dz
)
6106 static bool need_capt_ldc(
6107 const struct ia_css_pipe
*pipe
)
6109 IA_CSS_ENTER_LEAVE_PRIVATE("");
6110 assert(pipe
!= NULL
);
6111 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
);
6112 return (pipe
->extra_config
.enable_dvs_6axis
) ? true:false;
6115 static enum ia_css_err
set_num_primary_stages(unsigned int *num
, enum ia_css_pipe_version version
)
6117 enum ia_css_err err
= IA_CSS_SUCCESS
;
6120 return IA_CSS_ERR_INVALID_ARGUMENTS
;
6123 case IA_CSS_PIPE_VERSION_2_6_1
:
6124 *num
= NUM_PRIMARY_HQ_STAGES
;
6126 case IA_CSS_PIPE_VERSION_2_2
:
6127 case IA_CSS_PIPE_VERSION_1
:
6128 *num
= NUM_PRIMARY_STAGES
;
6131 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
6138 static enum ia_css_err
load_primary_binaries(
6139 struct ia_css_pipe
*pipe
)
6141 bool online
= false;
6142 bool memory
= false;
6143 bool continuous
= false;
6144 bool need_pp
= false;
6145 bool need_isp_copy_binary
= false;
6146 bool need_ldc
= false;
6147 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6148 bool sensor
= false;
6150 struct ia_css_frame_info prim_in_info
,
6152 capt_pp_out_info
, vf_info
,
6153 *vf_pp_in_info
, *pipe_out_info
,
6155 *pipe_vf_out_info
, *capt_pp_in_info
,
6160 enum ia_css_err err
= IA_CSS_SUCCESS
;
6161 struct ia_css_capture_settings
*mycs
;
6163 bool need_extra_yuv_scaler
= false;
6165 IA_CSS_ENTER_PRIVATE("");
6166 assert(pipe
!= NULL
);
6167 assert(pipe
->stream
!= NULL
);
6168 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6170 online
= pipe
->stream
->config
.online
;
6171 memory
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
6172 continuous
= pipe
->stream
->config
.continuous
;
6173 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6174 sensor
= (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
);
6177 mycs
= &pipe
->pipe_settings
.capture
;
6178 pipe_out_info
= &pipe
->output_info
[0];
6179 pipe_vf_out_info
= &pipe
->vf_output_info
[0];
6181 if (mycs
->primary_binary
[0].info
)
6182 return IA_CSS_SUCCESS
;
6184 err
= set_num_primary_stages(&mycs
->num_primary_stage
, pipe
->config
.isp_pipe_version
);
6185 if (err
!= IA_CSS_SUCCESS
) {
6186 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6190 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
]) {
6191 err
= ia_css_util_check_vf_out_info(pipe_out_info
, pipe_vf_out_info
);
6192 if (err
!= IA_CSS_SUCCESS
) {
6193 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6198 err
= ia_css_frame_check_info(pipe_out_info
);
6199 if (err
!= IA_CSS_SUCCESS
) {
6200 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6204 need_pp
= need_capture_pp(pipe
);
6206 /* we use the vf output info to get the primary/capture_pp binary
6207 configured for vf_veceven. It will select the closest downscaling
6209 vf_info
= *pipe_vf_out_info
;
6212 * WARNING: The #if def flag has been added below as a
6213 * temporary solution to solve the problem of enabling the
6214 * view finder in a single binary in a capture flow. The
6215 * vf-pp stage has been removed for Skycam in the solution
6216 * provided. The vf-pp stage should be re-introduced when
6217 * required. This should not be considered as a clean solution.
6218 * Proper investigation should be done to come up with the clean
6221 ia_css_frame_info_set_format(&vf_info
, IA_CSS_FRAME_FORMAT_YUV_LINE
);
6223 /* TODO: All this yuv_scaler and capturepp calculation logic
6224 * can be shared later. Capture_pp is also a yuv_scale binary
6225 * with extra XNR funcionality. Therefore, it can be made as the
6226 * first step of the cascade. */
6227 capt_pp_out_info
= pipe
->out_yuv_ds_input_info
;
6228 capt_pp_out_info
.format
= IA_CSS_FRAME_FORMAT_YUV420
;
6229 capt_pp_out_info
.res
.width
/= MAX_PREFERRED_YUV_DS_PER_STEP
;
6230 capt_pp_out_info
.res
.height
/= MAX_PREFERRED_YUV_DS_PER_STEP
;
6231 ia_css_frame_info_set_width(&capt_pp_out_info
, capt_pp_out_info
.res
.width
, 0);
6234 * WARNING: The #if def flag has been added below as a
6235 * temporary solution to solve the problem of enabling the
6236 * view finder in a single binary in a capture flow. The
6237 * vf-pp stage has been removed for Skycam in the solution
6238 * provided. The vf-pp stage should be re-introduced when
6239 * required. This should not be considered as a clean solution.
6240 * Proper investigation should be done to come up with the clean
6243 need_extra_yuv_scaler
= need_downscaling(capt_pp_out_info
.res
,
6244 pipe_out_info
->res
);
6246 if (need_extra_yuv_scaler
) {
6247 struct ia_css_cas_binary_descr cas_scaler_descr
6248 = IA_CSS_DEFAULT_CAS_BINARY_DESCR
;
6249 err
= ia_css_pipe_create_cas_scaler_desc_single_output(
6254 if (err
!= IA_CSS_SUCCESS
) {
6255 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6258 mycs
->num_yuv_scaler
= cas_scaler_descr
.num_stage
;
6259 mycs
->yuv_scaler_binary
= kzalloc(cas_scaler_descr
.num_stage
*
6260 sizeof(struct ia_css_binary
), GFP_KERNEL
);
6261 if (!mycs
->yuv_scaler_binary
) {
6262 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
6263 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6266 mycs
->is_output_stage
= kzalloc(cas_scaler_descr
.num_stage
*
6267 sizeof(bool), GFP_KERNEL
);
6268 if (!mycs
->is_output_stage
) {
6269 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
6270 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6273 for (i
= 0; i
< cas_scaler_descr
.num_stage
; i
++) {
6274 struct ia_css_binary_descr yuv_scaler_descr
;
6275 mycs
->is_output_stage
[i
] = cas_scaler_descr
.is_output_stage
[i
];
6276 ia_css_pipe_get_yuvscaler_binarydesc(pipe
,
6277 &yuv_scaler_descr
, &cas_scaler_descr
.in_info
[i
],
6278 &cas_scaler_descr
.out_info
[i
],
6279 &cas_scaler_descr
.internal_out_info
[i
],
6280 &cas_scaler_descr
.vf_info
[i
]);
6281 err
= ia_css_binary_find(&yuv_scaler_descr
,
6282 &mycs
->yuv_scaler_binary
[i
]);
6283 if (err
!= IA_CSS_SUCCESS
) {
6284 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6288 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr
);
6291 capt_pp_out_info
= pipe
->output_info
[0];
6294 /* TODO Do we disable ldc for skycam */
6295 need_ldc
= need_capt_ldc(pipe
);
6297 /* ldc and capt_pp are not supported in the same pipeline */
6299 struct ia_css_binary_descr capt_ldc_descr
;
6300 ia_css_pipe_get_ldc_binarydesc(pipe
,
6301 &capt_ldc_descr
, &prim_out_info
,
6306 err
= ia_css_binary_find(&capt_ldc_descr
,
6307 &mycs
->capture_ldc_binary
);
6308 if (err
!= IA_CSS_SUCCESS
) {
6309 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6312 } else if (need_pp
) {
6314 /* we build up the pipeline starting at the end */
6315 /* Capture post-processing */
6319 struct ia_css_binary_descr capture_pp_descr
;
6321 capt_pp_in_info
= need_ldc
? &capt_ldc_out_info
: &prim_out_info
;
6324 ia_css_pipe_get_capturepp_binarydesc(pipe
,
6326 &capture_pp_descr
, capt_pp_in_info
,
6328 &capture_pp_descr
, &prim_out_info
,
6330 &capt_pp_out_info
, &vf_info
);
6331 err
= ia_css_binary_find(&capture_pp_descr
,
6332 &mycs
->capture_pp_binary
);
6333 if (err
!= IA_CSS_SUCCESS
) {
6334 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6340 struct ia_css_binary_descr capt_ldc_descr
;
6341 ia_css_pipe_get_ldc_binarydesc(pipe
,
6342 &capt_ldc_descr
, &prim_out_info
,
6343 &capt_ldc_out_info
);
6345 err
= ia_css_binary_find(&capt_ldc_descr
,
6346 &mycs
->capture_ldc_binary
);
6347 if (err
!= IA_CSS_SUCCESS
) {
6348 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6354 prim_out_info
= *pipe_out_info
;
6359 struct ia_css_binary_descr prim_descr
[MAX_NUM_PRIMARY_STAGES
];
6361 for (i
= 0; i
< mycs
->num_primary_stage
; i
++) {
6362 struct ia_css_frame_info
*local_vf_info
= NULL
;
6363 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
] && (i
== mycs
->num_primary_stage
- 1))
6364 local_vf_info
= &vf_info
;
6365 ia_css_pipe_get_primary_binarydesc(pipe
, &prim_descr
[i
], &prim_in_info
, &prim_out_info
, local_vf_info
, i
);
6366 err
= ia_css_binary_find(&prim_descr
[i
], &mycs
->primary_binary
[i
]);
6367 if (err
!= IA_CSS_SUCCESS
) {
6368 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6374 /* Viewfinder post-processing */
6377 &mycs
->capture_pp_binary
.vf_frame_info
;
6380 &mycs
->primary_binary
[mycs
->num_primary_stage
- 1].vf_frame_info
;
6384 * WARNING: The #if def flag has been added below as a
6385 * temporary solution to solve the problem of enabling the
6386 * view finder in a single binary in a capture flow. The
6387 * vf-pp stage has been removed for Skycam in the solution
6388 * provided. The vf-pp stage should be re-introduced when
6389 * required. Thisshould not be considered as a clean solution.
6390 * Proper * investigation should be done to come up with the clean
6393 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
])
6395 struct ia_css_binary_descr vf_pp_descr
;
6397 ia_css_pipe_get_vfpp_binarydesc(pipe
,
6398 &vf_pp_descr
, vf_pp_in_info
, pipe_vf_out_info
);
6399 err
= ia_css_binary_find(&vf_pp_descr
, &mycs
->vf_pp_binary
);
6400 if (err
!= IA_CSS_SUCCESS
) {
6401 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6405 err
= allocate_delay_frames(pipe
);
6407 if (err
!= IA_CSS_SUCCESS
)
6410 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6411 /* When the input system is 2401, only the Direct Sensor Mode
6412 * Offline Capture uses the ISP copy binary.
6414 need_isp_copy_binary
= !online
&& sensor
;
6416 need_isp_copy_binary
= !online
&& !continuous
&& !memory
;
6420 if (need_isp_copy_binary
) {
6421 err
= load_copy_binary(pipe
,
6423 &mycs
->primary_binary
[0]);
6424 if (err
!= IA_CSS_SUCCESS
) {
6425 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6430 return IA_CSS_SUCCESS
;
6433 static enum ia_css_err
6434 allocate_delay_frames(struct ia_css_pipe
*pipe
)
6436 unsigned int num_delay_frames
= 0, i
= 0;
6437 unsigned int dvs_frame_delay
= 0;
6438 struct ia_css_frame_info ref_info
;
6439 enum ia_css_err err
= IA_CSS_SUCCESS
;
6440 enum ia_css_pipe_id mode
= IA_CSS_PIPE_ID_VIDEO
;
6441 struct ia_css_frame
**delay_frames
= NULL
;
6443 IA_CSS_ENTER_PRIVATE("");
6446 IA_CSS_ERROR("Invalid args - pipe %p", pipe
);
6447 return IA_CSS_ERR_INVALID_ARGUMENTS
;
6451 dvs_frame_delay
= pipe
->dvs_frame_delay
;
6453 if (dvs_frame_delay
> 0)
6454 num_delay_frames
= dvs_frame_delay
+ 1;
6457 case IA_CSS_PIPE_ID_CAPTURE
:
6459 struct ia_css_capture_settings
*mycs_capture
= &pipe
->pipe_settings
.capture
;
6464 case IA_CSS_PIPE_ID_VIDEO
:
6466 struct ia_css_video_settings
*mycs_video
= &pipe
->pipe_settings
.video
;
6467 ref_info
= mycs_video
->video_binary
.internal_frame_info
;
6468 /*The ref frame expects
6470 * 2. UV plane with line interleaving, like below
6471 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6473 * This format is not YUV420(which has Y, U and V planes).
6474 * Its closer to NV12, except that the UV plane has UV
6475 * interleaving, like UVUVUVUVUVUVUVUVU...
6477 * TODO: make this ref_frame format as a separate frame format
6479 ref_info
.format
= IA_CSS_FRAME_FORMAT_NV12
;
6480 delay_frames
= mycs_video
->delay_frames
;
6483 case IA_CSS_PIPE_ID_PREVIEW
:
6485 struct ia_css_preview_settings
*mycs_preview
= &pipe
->pipe_settings
.preview
;
6486 ref_info
= mycs_preview
->preview_binary
.internal_frame_info
;
6487 /*The ref frame expects
6489 * 2. UV plane with line interleaving, like below
6490 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6492 * This format is not YUV420(which has Y, U and V planes).
6493 * Its closer to NV12, except that the UV plane has UV
6494 * interleaving, like UVUVUVUVUVUVUVUVU...
6496 * TODO: make this ref_frame format as a separate frame format
6498 ref_info
.format
= IA_CSS_FRAME_FORMAT_NV12
;
6499 delay_frames
= mycs_preview
->delay_frames
;
6503 return IA_CSS_ERR_INVALID_ARGUMENTS
;
6507 ref_info
.raw_bit_depth
= SH_CSS_REF_BIT_DEPTH
;
6509 assert(num_delay_frames
<= MAX_NUM_VIDEO_DELAY_FRAMES
);
6510 for (i
= 0; i
< num_delay_frames
; i
++) {
6511 err
= ia_css_frame_allocate_from_info(&delay_frames
[i
], &ref_info
);
6512 if (err
!= IA_CSS_SUCCESS
)
6515 IA_CSS_LEAVE_PRIVATE("");
6516 return IA_CSS_SUCCESS
;
6519 static enum ia_css_err
load_advanced_binaries(
6520 struct ia_css_pipe
*pipe
)
6522 struct ia_css_frame_info pre_in_info
, gdc_in_info
,
6523 post_in_info
, post_out_info
,
6524 vf_info
, *vf_pp_in_info
, *pipe_out_info
,
6527 bool need_isp_copy
= true;
6528 enum ia_css_err err
= IA_CSS_SUCCESS
;
6530 IA_CSS_ENTER_PRIVATE("");
6532 assert(pipe
!= NULL
);
6533 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6534 if (pipe
->pipe_settings
.capture
.pre_isp_binary
.info
)
6535 return IA_CSS_SUCCESS
;
6536 pipe_out_info
= &pipe
->output_info
[0];
6537 pipe_vf_out_info
= &pipe
->vf_output_info
[0];
6539 vf_info
= *pipe_vf_out_info
;
6540 err
= ia_css_util_check_vf_out_info(pipe_out_info
, &vf_info
);
6541 if (err
!= IA_CSS_SUCCESS
)
6543 need_pp
= need_capture_pp(pipe
);
6545 ia_css_frame_info_set_format(&vf_info
,
6546 IA_CSS_FRAME_FORMAT_YUV_LINE
);
6548 /* we build up the pipeline starting at the end */
6549 /* Capture post-processing */
6551 struct ia_css_binary_descr capture_pp_descr
;
6553 ia_css_pipe_get_capturepp_binarydesc(pipe
,
6554 &capture_pp_descr
, &post_out_info
, pipe_out_info
, &vf_info
);
6555 err
= ia_css_binary_find(&capture_pp_descr
,
6556 &pipe
->pipe_settings
.capture
.capture_pp_binary
);
6557 if (err
!= IA_CSS_SUCCESS
)
6560 post_out_info
= *pipe_out_info
;
6565 struct ia_css_binary_descr post_gdc_descr
;
6567 ia_css_pipe_get_post_gdc_binarydesc(pipe
,
6568 &post_gdc_descr
, &post_in_info
, &post_out_info
, &vf_info
);
6569 err
= ia_css_binary_find(&post_gdc_descr
,
6570 &pipe
->pipe_settings
.capture
.post_isp_binary
);
6571 if (err
!= IA_CSS_SUCCESS
)
6577 struct ia_css_binary_descr gdc_descr
;
6579 ia_css_pipe_get_gdc_binarydesc(pipe
, &gdc_descr
, &gdc_in_info
,
6580 &pipe
->pipe_settings
.capture
.post_isp_binary
.in_frame_info
);
6581 err
= ia_css_binary_find(&gdc_descr
,
6582 &pipe
->pipe_settings
.capture
.anr_gdc_binary
);
6583 if (err
!= IA_CSS_SUCCESS
)
6586 pipe
->pipe_settings
.capture
.anr_gdc_binary
.left_padding
=
6587 pipe
->pipe_settings
.capture
.post_isp_binary
.left_padding
;
6591 struct ia_css_binary_descr pre_gdc_descr
;
6593 ia_css_pipe_get_pre_gdc_binarydesc(pipe
, &pre_gdc_descr
, &pre_in_info
,
6594 &pipe
->pipe_settings
.capture
.anr_gdc_binary
.in_frame_info
);
6595 err
= ia_css_binary_find(&pre_gdc_descr
,
6596 &pipe
->pipe_settings
.capture
.pre_isp_binary
);
6597 if (err
!= IA_CSS_SUCCESS
)
6600 pipe
->pipe_settings
.capture
.pre_isp_binary
.left_padding
=
6601 pipe
->pipe_settings
.capture
.anr_gdc_binary
.left_padding
;
6603 /* Viewfinder post-processing */
6606 &pipe
->pipe_settings
.capture
.capture_pp_binary
.vf_frame_info
;
6609 &pipe
->pipe_settings
.capture
.post_isp_binary
.vf_frame_info
;
6613 struct ia_css_binary_descr vf_pp_descr
;
6615 ia_css_pipe_get_vfpp_binarydesc(pipe
,
6616 &vf_pp_descr
, vf_pp_in_info
, pipe_vf_out_info
);
6617 err
= ia_css_binary_find(&vf_pp_descr
,
6618 &pipe
->pipe_settings
.capture
.vf_pp_binary
);
6619 if (err
!= IA_CSS_SUCCESS
)
6624 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6625 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6626 need_isp_copy
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
;
6629 load_copy_binary(pipe
,
6630 &pipe
->pipe_settings
.capture
.copy_binary
,
6631 &pipe
->pipe_settings
.capture
.pre_isp_binary
);
6636 static enum ia_css_err
load_bayer_isp_binaries(
6637 struct ia_css_pipe
*pipe
)
6639 struct ia_css_frame_info pre_isp_in_info
, *pipe_out_info
;
6640 enum ia_css_err err
= IA_CSS_SUCCESS
;
6641 struct ia_css_binary_descr pre_de_descr
;
6643 IA_CSS_ENTER_PRIVATE("");
6644 assert(pipe
!= NULL
);
6645 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6646 pipe_out_info
= &pipe
->output_info
[0];
6648 if (pipe
->pipe_settings
.capture
.pre_isp_binary
.info
)
6649 return IA_CSS_SUCCESS
;
6651 err
= ia_css_frame_check_info(pipe_out_info
);
6652 if (err
!= IA_CSS_SUCCESS
)
6655 ia_css_pipe_get_pre_de_binarydesc(pipe
, &pre_de_descr
,
6659 err
= ia_css_binary_find(&pre_de_descr
,
6660 &pipe
->pipe_settings
.capture
.pre_isp_binary
);
6665 static enum ia_css_err
load_low_light_binaries(
6666 struct ia_css_pipe
*pipe
)
6668 struct ia_css_frame_info pre_in_info
, anr_in_info
,
6669 post_in_info
, post_out_info
,
6670 vf_info
, *pipe_vf_out_info
, *pipe_out_info
,
6673 bool need_isp_copy
= true;
6674 enum ia_css_err err
= IA_CSS_SUCCESS
;
6676 IA_CSS_ENTER_PRIVATE("");
6677 assert(pipe
!= NULL
);
6678 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6680 if (pipe
->pipe_settings
.capture
.pre_isp_binary
.info
)
6681 return IA_CSS_SUCCESS
;
6682 pipe_vf_out_info
= &pipe
->vf_output_info
[0];
6683 pipe_out_info
= &pipe
->output_info
[0];
6685 vf_info
= *pipe_vf_out_info
;
6686 err
= ia_css_util_check_vf_out_info(pipe_out_info
,
6688 if (err
!= IA_CSS_SUCCESS
)
6690 need_pp
= need_capture_pp(pipe
);
6692 ia_css_frame_info_set_format(&vf_info
,
6693 IA_CSS_FRAME_FORMAT_YUV_LINE
);
6695 /* we build up the pipeline starting at the end */
6696 /* Capture post-processing */
6698 struct ia_css_binary_descr capture_pp_descr
;
6700 ia_css_pipe_get_capturepp_binarydesc(pipe
,
6701 &capture_pp_descr
, &post_out_info
, pipe_out_info
, &vf_info
);
6702 err
= ia_css_binary_find(&capture_pp_descr
,
6703 &pipe
->pipe_settings
.capture
.capture_pp_binary
);
6704 if (err
!= IA_CSS_SUCCESS
)
6707 post_out_info
= *pipe_out_info
;
6712 struct ia_css_binary_descr post_anr_descr
;
6714 ia_css_pipe_get_post_anr_binarydesc(pipe
,
6715 &post_anr_descr
, &post_in_info
, &post_out_info
, &vf_info
);
6716 err
= ia_css_binary_find(&post_anr_descr
,
6717 &pipe
->pipe_settings
.capture
.post_isp_binary
);
6718 if (err
!= IA_CSS_SUCCESS
)
6724 struct ia_css_binary_descr anr_descr
;
6726 ia_css_pipe_get_anr_binarydesc(pipe
, &anr_descr
, &anr_in_info
,
6727 &pipe
->pipe_settings
.capture
.post_isp_binary
.in_frame_info
);
6728 err
= ia_css_binary_find(&anr_descr
,
6729 &pipe
->pipe_settings
.capture
.anr_gdc_binary
);
6730 if (err
!= IA_CSS_SUCCESS
)
6733 pipe
->pipe_settings
.capture
.anr_gdc_binary
.left_padding
=
6734 pipe
->pipe_settings
.capture
.post_isp_binary
.left_padding
;
6738 struct ia_css_binary_descr pre_anr_descr
;
6740 ia_css_pipe_get_pre_anr_binarydesc(pipe
, &pre_anr_descr
, &pre_in_info
,
6741 &pipe
->pipe_settings
.capture
.anr_gdc_binary
.in_frame_info
);
6742 err
= ia_css_binary_find(&pre_anr_descr
,
6743 &pipe
->pipe_settings
.capture
.pre_isp_binary
);
6744 if (err
!= IA_CSS_SUCCESS
)
6747 pipe
->pipe_settings
.capture
.pre_isp_binary
.left_padding
=
6748 pipe
->pipe_settings
.capture
.anr_gdc_binary
.left_padding
;
6750 /* Viewfinder post-processing */
6753 &pipe
->pipe_settings
.capture
.capture_pp_binary
.vf_frame_info
;
6756 &pipe
->pipe_settings
.capture
.post_isp_binary
.vf_frame_info
;
6760 struct ia_css_binary_descr vf_pp_descr
;
6762 ia_css_pipe_get_vfpp_binarydesc(pipe
,
6763 &vf_pp_descr
, vf_pp_in_info
, pipe_vf_out_info
);
6764 err
= ia_css_binary_find(&vf_pp_descr
,
6765 &pipe
->pipe_settings
.capture
.vf_pp_binary
);
6766 if (err
!= IA_CSS_SUCCESS
)
6771 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6772 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6773 need_isp_copy
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
;
6776 err
= load_copy_binary(pipe
,
6777 &pipe
->pipe_settings
.capture
.copy_binary
,
6778 &pipe
->pipe_settings
.capture
.pre_isp_binary
);
6783 static bool copy_on_sp(struct ia_css_pipe
*pipe
)
6787 assert(pipe
!= NULL
);
6788 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "copy_on_sp() enter:\n");
6792 rval
&= (pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
);
6794 rval
&= (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_RAW
);
6796 rval
&= ((pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_BINARY_8
) ||
6797 (pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
));
6802 static enum ia_css_err
load_capture_binaries(
6803 struct ia_css_pipe
*pipe
)
6805 enum ia_css_err err
= IA_CSS_SUCCESS
;
6808 IA_CSS_ENTER_PRIVATE("");
6809 assert(pipe
!= NULL
);
6810 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
6812 if (pipe
->pipe_settings
.capture
.primary_binary
[0].info
) {
6813 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
6814 return IA_CSS_SUCCESS
;
6817 /* in primary, advanced,low light or bayer,
6818 the input format must be raw */
6820 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_ADVANCED
||
6821 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
||
6822 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_LOW_LIGHT
;
6823 err
= ia_css_util_check_input(&pipe
->stream
->config
, must_be_raw
, false);
6824 if (err
!= IA_CSS_SUCCESS
) {
6825 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6828 if (copy_on_sp(pipe
) &&
6829 pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_BINARY_8
) {
6830 ia_css_frame_info_init(
6831 &pipe
->output_info
[0],
6834 IA_CSS_FRAME_FORMAT_BINARY_8
,
6836 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
6837 return IA_CSS_SUCCESS
;
6840 switch (pipe
->config
.default_capture_config
.mode
) {
6841 case IA_CSS_CAPTURE_MODE_RAW
:
6842 err
= load_copy_binaries(pipe
);
6843 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6844 if (err
== IA_CSS_SUCCESS
)
6845 pipe
->pipe_settings
.capture
.copy_binary
.online
= pipe
->stream
->config
.online
;
6848 case IA_CSS_CAPTURE_MODE_BAYER
:
6849 err
= load_bayer_isp_binaries(pipe
);
6851 case IA_CSS_CAPTURE_MODE_PRIMARY
:
6852 err
= load_primary_binaries(pipe
);
6854 case IA_CSS_CAPTURE_MODE_ADVANCED
:
6855 err
= load_advanced_binaries(pipe
);
6857 case IA_CSS_CAPTURE_MODE_LOW_LIGHT
:
6858 err
= load_low_light_binaries(pipe
);
6861 if (err
!= IA_CSS_SUCCESS
) {
6862 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6866 IA_CSS_LEAVE_ERR_PRIVATE(err
);
6870 static enum ia_css_err
6871 unload_capture_binaries(struct ia_css_pipe
*pipe
)
6874 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
6876 if ((pipe
== NULL
) || ((pipe
->mode
!= IA_CSS_PIPE_ID_CAPTURE
) && (pipe
->mode
!= IA_CSS_PIPE_ID_COPY
))) {
6877 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
6878 return IA_CSS_ERR_INVALID_ARGUMENTS
;
6880 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.copy_binary
);
6881 for (i
= 0; i
< MAX_NUM_PRIMARY_STAGES
; i
++)
6882 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.primary_binary
[i
]);
6883 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.pre_isp_binary
);
6884 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.anr_gdc_binary
);
6885 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.post_isp_binary
);
6886 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.capture_pp_binary
);
6887 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.capture_ldc_binary
);
6888 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.vf_pp_binary
);
6890 for (i
= 0; i
< pipe
->pipe_settings
.capture
.num_yuv_scaler
; i
++)
6891 ia_css_binary_unload(&pipe
->pipe_settings
.capture
.yuv_scaler_binary
[i
]);
6893 kfree(pipe
->pipe_settings
.capture
.is_output_stage
);
6894 pipe
->pipe_settings
.capture
.is_output_stage
= NULL
;
6895 kfree(pipe
->pipe_settings
.capture
.yuv_scaler_binary
);
6896 pipe
->pipe_settings
.capture
.yuv_scaler_binary
= NULL
;
6898 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
6899 return IA_CSS_SUCCESS
;
6903 need_downscaling(const struct ia_css_resolution in_res
,
6904 const struct ia_css_resolution out_res
)
6907 if (in_res
.width
> out_res
.width
|| in_res
.height
> out_res
.height
)
6914 need_yuv_scaler_stage(const struct ia_css_pipe
*pipe
)
6917 struct ia_css_resolution in_res
, out_res
;
6919 bool need_format_conversion
= false;
6921 IA_CSS_ENTER_PRIVATE("");
6922 assert(pipe
!= NULL
);
6923 assert(pipe
->mode
== IA_CSS_PIPE_ID_YUVPP
);
6925 /* TODO: make generic function */
6926 need_format_conversion
=
6927 ((pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY
) &&
6928 (pipe
->output_info
[0].format
!= IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
));
6930 in_res
= pipe
->config
.input_effective_res
;
6932 if (pipe
->config
.enable_dz
)
6935 if ((pipe
->output_info
[0].res
.width
!= 0) && need_format_conversion
)
6938 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
6939 out_res
= pipe
->output_info
[i
].res
;
6941 /* A non-zero width means it is a valid output port */
6942 if ((out_res
.width
!= 0) && need_downscaling(in_res
, out_res
))
6949 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6950 /* which has some hard-coded knowledge which prevents reuse of the function. */
6951 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6952 static enum ia_css_err
ia_css_pipe_create_cas_scaler_desc_single_output(
6953 struct ia_css_frame_info
*cas_scaler_in_info
,
6954 struct ia_css_frame_info
*cas_scaler_out_info
,
6955 struct ia_css_frame_info
*cas_scaler_vf_info
,
6956 struct ia_css_cas_binary_descr
*descr
)
6959 unsigned int hor_ds_factor
= 0, ver_ds_factor
= 0;
6960 enum ia_css_err err
= IA_CSS_SUCCESS
;
6961 struct ia_css_frame_info tmp_in_info
= IA_CSS_BINARY_DEFAULT_FRAME_INFO
;
6963 unsigned max_scale_factor_per_stage
= MAX_PREFERRED_YUV_DS_PER_STEP
;
6965 assert(cas_scaler_in_info
!= NULL
);
6966 assert(cas_scaler_out_info
!= NULL
);
6968 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6970 /* We assume that this function is used only for single output port case. */
6971 descr
->num_output_stage
= 1;
6973 hor_ds_factor
= CEIL_DIV(cas_scaler_in_info
->res
.width
, cas_scaler_out_info
->res
.width
);
6974 ver_ds_factor
= CEIL_DIV(cas_scaler_in_info
->res
.height
, cas_scaler_out_info
->res
.height
);
6975 /* use the same horizontal and vertical downscaling factor for simplicity */
6976 assert(hor_ds_factor
== ver_ds_factor
);
6979 while (i
< hor_ds_factor
) {
6981 i
*= max_scale_factor_per_stage
;
6984 descr
->in_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
6985 if (!descr
->in_info
) {
6986 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
6989 descr
->internal_out_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
6990 if (!descr
->internal_out_info
) {
6991 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
6994 descr
->out_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
6995 if (!descr
->out_info
) {
6996 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
6999 descr
->vf_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
7000 if (!descr
->vf_info
) {
7001 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7004 descr
->is_output_stage
= kmalloc(descr
->num_stage
* sizeof(bool), GFP_KERNEL
);
7005 if (!descr
->is_output_stage
) {
7006 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7010 tmp_in_info
= *cas_scaler_in_info
;
7011 for (i
= 0; i
< descr
->num_stage
; i
++) {
7013 descr
->in_info
[i
] = tmp_in_info
;
7014 if ((tmp_in_info
.res
.width
/ max_scale_factor_per_stage
) <= cas_scaler_out_info
->res
.width
) {
7015 descr
->is_output_stage
[i
] = true;
7016 if ((descr
->num_output_stage
> 1) && (i
!= (descr
->num_stage
- 1))) {
7017 descr
->internal_out_info
[i
].res
.width
= cas_scaler_out_info
->res
.width
;
7018 descr
->internal_out_info
[i
].res
.height
= cas_scaler_out_info
->res
.height
;
7019 descr
->internal_out_info
[i
].padded_width
= cas_scaler_out_info
->padded_width
;
7020 descr
->internal_out_info
[i
].format
= IA_CSS_FRAME_FORMAT_YUV420
;
7022 assert(i
== (descr
->num_stage
- 1));
7023 descr
->internal_out_info
[i
].res
.width
= 0;
7024 descr
->internal_out_info
[i
].res
.height
= 0;
7026 descr
->out_info
[i
].res
.width
= cas_scaler_out_info
->res
.width
;
7027 descr
->out_info
[i
].res
.height
= cas_scaler_out_info
->res
.height
;
7028 descr
->out_info
[i
].padded_width
= cas_scaler_out_info
->padded_width
;
7029 descr
->out_info
[i
].format
= cas_scaler_out_info
->format
;
7030 if (cas_scaler_vf_info
!= NULL
) {
7031 descr
->vf_info
[i
].res
.width
= cas_scaler_vf_info
->res
.width
;
7032 descr
->vf_info
[i
].res
.height
= cas_scaler_vf_info
->res
.height
;
7033 descr
->vf_info
[i
].padded_width
= cas_scaler_vf_info
->padded_width
;
7034 ia_css_frame_info_set_format(&descr
->vf_info
[i
], IA_CSS_FRAME_FORMAT_YUV_LINE
);
7036 descr
->vf_info
[i
].res
.width
= 0;
7037 descr
->vf_info
[i
].res
.height
= 0;
7038 descr
->vf_info
[i
].padded_width
= 0;
7041 descr
->is_output_stage
[i
] = false;
7042 descr
->internal_out_info
[i
].res
.width
= tmp_in_info
.res
.width
/ max_scale_factor_per_stage
;
7043 descr
->internal_out_info
[i
].res
.height
= tmp_in_info
.res
.height
/ max_scale_factor_per_stage
;
7044 descr
->internal_out_info
[i
].format
= IA_CSS_FRAME_FORMAT_YUV420
;
7045 ia_css_frame_info_init(&descr
->internal_out_info
[i
],
7046 tmp_in_info
.res
.width
/ max_scale_factor_per_stage
,
7047 tmp_in_info
.res
.height
/ max_scale_factor_per_stage
,
7048 IA_CSS_FRAME_FORMAT_YUV420
, 0);
7049 descr
->out_info
[i
].res
.width
= 0;
7050 descr
->out_info
[i
].res
.height
= 0;
7051 descr
->vf_info
[i
].res
.width
= 0;
7052 descr
->vf_info
[i
].res
.height
= 0;
7054 tmp_in_info
= descr
->internal_out_info
[i
];
7057 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7062 /* FIXME: merge most of this and single output version */
7063 static enum ia_css_err
ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe
*pipe
,
7064 struct ia_css_cas_binary_descr
*descr
)
7066 struct ia_css_frame_info in_info
= IA_CSS_BINARY_DEFAULT_FRAME_INFO
;
7067 struct ia_css_frame_info
*out_info
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
];
7068 struct ia_css_frame_info
*vf_out_info
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
];
7069 struct ia_css_frame_info tmp_in_info
= IA_CSS_BINARY_DEFAULT_FRAME_INFO
;
7071 unsigned int hor_scale_factor
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
],
7072 ver_scale_factor
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
],
7074 unsigned int num_stages
= 0;
7075 enum ia_css_err err
= IA_CSS_SUCCESS
;
7077 unsigned max_scale_factor_per_stage
= MAX_PREFERRED_YUV_DS_PER_STEP
;
7079 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7081 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7083 vf_out_info
[i
] = NULL
;
7084 hor_scale_factor
[i
] = 0;
7085 ver_scale_factor
[i
] = 0;
7088 in_info
.res
= pipe
->config
.input_effective_res
;
7089 in_info
.padded_width
= in_info
.res
.width
;
7090 descr
->num_output_stage
= 0;
7091 /* Find out how much scaling we need for each output */
7092 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7093 if (pipe
->output_info
[i
].res
.width
!= 0) {
7094 out_info
[i
] = &pipe
->output_info
[i
];
7095 if (pipe
->vf_output_info
[i
].res
.width
!= 0)
7096 vf_out_info
[i
] = &pipe
->vf_output_info
[i
];
7097 descr
->num_output_stage
+= 1;
7100 if (out_info
[i
] != NULL
) {
7101 hor_scale_factor
[i
] = CEIL_DIV(in_info
.res
.width
, out_info
[i
]->res
.width
);
7102 ver_scale_factor
[i
] = CEIL_DIV(in_info
.res
.height
, out_info
[i
]->res
.height
);
7103 /* use the same horizontal and vertical scaling factor for simplicity */
7104 assert(hor_scale_factor
[i
] == ver_scale_factor
[i
]);
7108 scale_factor
*= max_scale_factor_per_stage
;
7109 } while (scale_factor
< hor_scale_factor
[i
]);
7111 in_info
.res
= out_info
[i
]->res
;
7115 if (need_yuv_scaler_stage(pipe
) && (num_stages
== 0))
7118 descr
->num_stage
= num_stages
;
7120 descr
->in_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
7121 if (!descr
->in_info
) {
7122 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7125 descr
->internal_out_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
7126 if (!descr
->internal_out_info
) {
7127 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7130 descr
->out_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
7131 if (!descr
->out_info
) {
7132 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7135 descr
->vf_info
= kmalloc(descr
->num_stage
* sizeof(struct ia_css_frame_info
), GFP_KERNEL
);
7136 if (!descr
->vf_info
) {
7137 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7140 descr
->is_output_stage
= kmalloc(descr
->num_stage
* sizeof(bool), GFP_KERNEL
);
7141 if (descr
->is_output_stage
== NULL
) {
7142 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7146 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7149 assert((out_info
[i
-1]->res
.width
>= out_info
[i
]->res
.width
) &&
7150 (out_info
[i
-1]->res
.height
>= out_info
[i
]->res
.height
));
7155 tmp_in_info
.res
= pipe
->config
.input_effective_res
;
7156 tmp_in_info
.format
= IA_CSS_FRAME_FORMAT_YUV420
;
7157 for (i
= 0, j
= 0; i
< descr
->num_stage
; i
++) {
7159 assert(out_info
[j
] != NULL
);
7161 descr
->in_info
[i
] = tmp_in_info
;
7162 if ((tmp_in_info
.res
.width
/ max_scale_factor_per_stage
) <= out_info
[j
]->res
.width
) {
7163 descr
->is_output_stage
[i
] = true;
7164 if ((descr
->num_output_stage
> 1) && (i
!= (descr
->num_stage
- 1))) {
7165 descr
->internal_out_info
[i
].res
.width
= out_info
[j
]->res
.width
;
7166 descr
->internal_out_info
[i
].res
.height
= out_info
[j
]->res
.height
;
7167 descr
->internal_out_info
[i
].padded_width
= out_info
[j
]->padded_width
;
7168 descr
->internal_out_info
[i
].format
= IA_CSS_FRAME_FORMAT_YUV420
;
7170 assert(i
== (descr
->num_stage
- 1));
7171 descr
->internal_out_info
[i
].res
.width
= 0;
7172 descr
->internal_out_info
[i
].res
.height
= 0;
7174 descr
->out_info
[i
].res
.width
= out_info
[j
]->res
.width
;
7175 descr
->out_info
[i
].res
.height
= out_info
[j
]->res
.height
;
7176 descr
->out_info
[i
].padded_width
= out_info
[j
]->padded_width
;
7177 descr
->out_info
[i
].format
= out_info
[j
]->format
;
7178 if (vf_out_info
[j
] != NULL
) {
7179 descr
->vf_info
[i
].res
.width
= vf_out_info
[j
]->res
.width
;
7180 descr
->vf_info
[i
].res
.height
= vf_out_info
[j
]->res
.height
;
7181 descr
->vf_info
[i
].padded_width
= vf_out_info
[j
]->padded_width
;
7182 ia_css_frame_info_set_format(&descr
->vf_info
[i
], IA_CSS_FRAME_FORMAT_YUV_LINE
);
7184 descr
->vf_info
[i
].res
.width
= 0;
7185 descr
->vf_info
[i
].res
.height
= 0;
7186 descr
->vf_info
[i
].padded_width
= 0;
7190 descr
->is_output_stage
[i
] = false;
7191 descr
->internal_out_info
[i
].res
.width
= tmp_in_info
.res
.width
/ max_scale_factor_per_stage
;
7192 descr
->internal_out_info
[i
].res
.height
= tmp_in_info
.res
.height
/ max_scale_factor_per_stage
;
7193 descr
->internal_out_info
[i
].format
= IA_CSS_FRAME_FORMAT_YUV420
;
7194 ia_css_frame_info_init(&descr
->internal_out_info
[i
],
7195 tmp_in_info
.res
.width
/ max_scale_factor_per_stage
,
7196 tmp_in_info
.res
.height
/ max_scale_factor_per_stage
,
7197 IA_CSS_FRAME_FORMAT_YUV420
, 0);
7198 descr
->out_info
[i
].res
.width
= 0;
7199 descr
->out_info
[i
].res
.height
= 0;
7200 descr
->vf_info
[i
].res
.width
= 0;
7201 descr
->vf_info
[i
].res
.height
= 0;
7203 tmp_in_info
= descr
->internal_out_info
[i
];
7206 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7211 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
*descr
)
7213 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7214 kfree(descr
->in_info
);
7215 descr
->in_info
= NULL
;
7216 kfree(descr
->internal_out_info
);
7217 descr
->internal_out_info
= NULL
;
7218 kfree(descr
->out_info
);
7219 descr
->out_info
= NULL
;
7220 kfree(descr
->vf_info
);
7221 descr
->vf_info
= NULL
;
7222 kfree(descr
->is_output_stage
);
7223 descr
->is_output_stage
= NULL
;
7224 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7227 static enum ia_css_err
7228 load_yuvpp_binaries(struct ia_css_pipe
*pipe
)
7230 enum ia_css_err err
= IA_CSS_SUCCESS
;
7231 bool need_scaler
= false;
7232 struct ia_css_frame_info
*vf_pp_in_info
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
];
7233 struct ia_css_yuvpp_settings
*mycs
;
7234 struct ia_css_binary
*next_binary
;
7235 struct ia_css_cas_binary_descr cas_scaler_descr
= IA_CSS_DEFAULT_CAS_BINARY_DESCR
;
7237 bool need_isp_copy_binary
= false;
7239 IA_CSS_ENTER_PRIVATE("");
7240 assert(pipe
!= NULL
);
7241 assert(pipe
->stream
!= NULL
);
7242 assert(pipe
->mode
== IA_CSS_PIPE_ID_YUVPP
);
7244 if (pipe
->pipe_settings
.yuvpp
.copy_binary
.info
)
7247 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7248 err
= ia_css_util_check_input(&pipe
->stream
->config
, false, false);
7249 if (err
!= IA_CSS_SUCCESS
)
7252 mycs
= &pipe
->pipe_settings
.yuvpp
;
7254 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7255 if (pipe
->vf_output_info
[i
].res
.width
!= 0) {
7256 err
= ia_css_util_check_vf_out_info(&pipe
->output_info
[i
],
7257 &pipe
->vf_output_info
[i
]);
7258 if (err
!= IA_CSS_SUCCESS
)
7261 vf_pp_in_info
[i
] = NULL
;
7264 need_scaler
= need_yuv_scaler_stage(pipe
);
7266 /* we build up the pipeline starting at the end */
7267 /* Capture post-processing */
7269 struct ia_css_binary_descr yuv_scaler_descr
;
7271 err
= ia_css_pipe_create_cas_scaler_desc(pipe
,
7273 if (err
!= IA_CSS_SUCCESS
)
7275 mycs
->num_output
= cas_scaler_descr
.num_output_stage
;
7276 mycs
->num_yuv_scaler
= cas_scaler_descr
.num_stage
;
7277 mycs
->yuv_scaler_binary
= kzalloc(cas_scaler_descr
.num_stage
*
7278 sizeof(struct ia_css_binary
), GFP_KERNEL
);
7279 if (!mycs
->yuv_scaler_binary
) {
7280 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7283 mycs
->is_output_stage
= kzalloc(cas_scaler_descr
.num_stage
*
7284 sizeof(bool), GFP_KERNEL
);
7285 if (!mycs
->is_output_stage
) {
7286 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7289 for (i
= 0; i
< cas_scaler_descr
.num_stage
; i
++) {
7290 mycs
->is_output_stage
[i
] = cas_scaler_descr
.is_output_stage
[i
];
7291 ia_css_pipe_get_yuvscaler_binarydesc(pipe
,
7292 &yuv_scaler_descr
, &cas_scaler_descr
.in_info
[i
],
7293 &cas_scaler_descr
.out_info
[i
],
7294 &cas_scaler_descr
.internal_out_info
[i
],
7295 &cas_scaler_descr
.vf_info
[i
]);
7296 err
= ia_css_binary_find(&yuv_scaler_descr
,
7297 &mycs
->yuv_scaler_binary
[i
]);
7298 if (err
!= IA_CSS_SUCCESS
)
7301 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr
);
7303 mycs
->num_output
= 1;
7307 next_binary
= &mycs
->yuv_scaler_binary
[0];
7312 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7315 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7316 * its input is "IA_CSS_STREAM_FORMAT_YUV422_8"?
7318 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7319 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7320 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7322 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7323 * _scale_binary". It would translate the input-frame to the frame formats that
7324 * are supported by the "yuv_scale_binary".
7326 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7327 * pp_defs.h" for the list of input-frame formats that are supported by the
7328 * "yuv_scale_binary".
7330 need_isp_copy_binary
=
7331 (pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_YUV422_8
);
7332 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7333 need_isp_copy_binary
= true;
7334 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7336 if (need_isp_copy_binary
) {
7337 err
= load_copy_binary(pipe
,
7341 if (err
!= IA_CSS_SUCCESS
)
7346 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7348 * In some use cases, the first stage in the "yuvpp" pipe is the
7349 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7350 * the input from either the system DDR or from the IPU internal VMEM.
7351 * So it provides the flag "online" to specify where its input is from,
7354 * (1) "online <= true", the input is from the IPU internal VMEM.
7355 * (2) "online <= false", the input is from the system DDR.
7357 * In other use cases, the first stage in the "yuvpp" pipe is the
7358 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7359 * input ONLY from the system DDR. So it does not provide the flag "online"
7360 * to specify where its input is from.
7362 pipe
->pipe_settings
.capture
.copy_binary
.online
= pipe
->stream
->config
.online
;
7365 /* Viewfinder post-processing */
7367 for (i
= 0, j
= 0; i
< mycs
->num_yuv_scaler
; i
++) {
7368 if (mycs
->is_output_stage
[i
]) {
7371 &mycs
->yuv_scaler_binary
[i
].vf_frame_info
;
7375 mycs
->num_vf_pp
= j
;
7378 &mycs
->copy_binary
.vf_frame_info
;
7379 for (i
= 1; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7380 vf_pp_in_info
[i
] = NULL
;
7382 mycs
->num_vf_pp
= 1;
7384 mycs
->vf_pp_binary
= kzalloc(mycs
->num_vf_pp
* sizeof(struct ia_css_binary
),
7386 if (!mycs
->vf_pp_binary
) {
7387 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
7392 struct ia_css_binary_descr vf_pp_descr
;
7394 for (i
= 0; i
< mycs
->num_vf_pp
; i
++) {
7395 if (pipe
->vf_output_info
[i
].res
.width
!= 0) {
7396 ia_css_pipe_get_vfpp_binarydesc(pipe
,
7397 &vf_pp_descr
, vf_pp_in_info
[i
], &pipe
->vf_output_info
[i
]);
7398 err
= ia_css_binary_find(&vf_pp_descr
, &mycs
->vf_pp_binary
[i
]);
7399 if (err
!= IA_CSS_SUCCESS
)
7405 if (err
!= IA_CSS_SUCCESS
)
7410 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr
);
7412 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "load_yuvpp_binaries() leave, err=%d\n",
7417 static enum ia_css_err
7418 unload_yuvpp_binaries(struct ia_css_pipe
*pipe
)
7421 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
7423 if ((pipe
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_YUVPP
)) {
7424 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
7425 return IA_CSS_ERR_INVALID_ARGUMENTS
;
7427 ia_css_binary_unload(&pipe
->pipe_settings
.yuvpp
.copy_binary
);
7428 for (i
= 0; i
< pipe
->pipe_settings
.yuvpp
.num_yuv_scaler
; i
++) {
7429 ia_css_binary_unload(&pipe
->pipe_settings
.yuvpp
.yuv_scaler_binary
[i
]);
7431 for (i
= 0; i
< pipe
->pipe_settings
.yuvpp
.num_vf_pp
; i
++) {
7432 ia_css_binary_unload(&pipe
->pipe_settings
.yuvpp
.vf_pp_binary
[i
]);
7434 kfree(pipe
->pipe_settings
.yuvpp
.is_output_stage
);
7435 pipe
->pipe_settings
.yuvpp
.is_output_stage
= NULL
;
7436 kfree(pipe
->pipe_settings
.yuvpp
.yuv_scaler_binary
);
7437 pipe
->pipe_settings
.yuvpp
.yuv_scaler_binary
= NULL
;
7438 kfree(pipe
->pipe_settings
.yuvpp
.vf_pp_binary
);
7439 pipe
->pipe_settings
.yuvpp
.vf_pp_binary
= NULL
;
7441 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
7442 return IA_CSS_SUCCESS
;
7445 static enum ia_css_err
yuvpp_start(struct ia_css_pipe
*pipe
)
7447 struct ia_css_binary
*copy_binary
;
7448 enum ia_css_err err
= IA_CSS_SUCCESS
;
7449 enum sh_css_pipe_config_override copy_ovrd
;
7450 enum ia_css_input_mode yuvpp_pipe_input_mode
;
7452 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
7453 if ((pipe
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_YUVPP
)) {
7454 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
7455 return IA_CSS_ERR_INVALID_ARGUMENTS
;
7458 yuvpp_pipe_input_mode
= pipe
->stream
->config
.mode
;
7460 copy_binary
= &pipe
->pipe_settings
.yuvpp
.copy_binary
;
7462 sh_css_metrics_start_frame();
7464 /* multi stream video needs mipi buffers */
7466 #if !defined(HAS_NO_INPUT_SYSTEM) && ( defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) )
7467 err
= send_mipi_frames(pipe
);
7468 if (err
!= IA_CSS_SUCCESS
) {
7469 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7475 unsigned int thread_id
;
7477 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
7478 copy_ovrd
= 1 << thread_id
;
7481 start_pipe(pipe
, copy_ovrd
, yuvpp_pipe_input_mode
);
7483 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7487 static enum ia_css_err
7488 sh_css_pipe_unload_binaries(struct ia_css_pipe
*pipe
)
7490 enum ia_css_err err
= IA_CSS_SUCCESS
;
7491 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
7494 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
7495 return IA_CSS_ERR_INVALID_ARGUMENTS
;
7497 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7498 if (pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
) {
7499 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
7500 return IA_CSS_SUCCESS
;
7503 switch (pipe
->mode
) {
7504 case IA_CSS_PIPE_ID_PREVIEW
:
7505 err
= unload_preview_binaries(pipe
);
7507 case IA_CSS_PIPE_ID_VIDEO
:
7508 err
= unload_video_binaries(pipe
);
7510 case IA_CSS_PIPE_ID_CAPTURE
:
7511 err
= unload_capture_binaries(pipe
);
7513 case IA_CSS_PIPE_ID_YUVPP
:
7514 err
= unload_yuvpp_binaries(pipe
);
7519 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7523 static enum ia_css_err
7524 sh_css_pipe_load_binaries(struct ia_css_pipe
*pipe
)
7526 enum ia_css_err err
= IA_CSS_SUCCESS
;
7528 assert(pipe
!= NULL
);
7529 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "sh_css_pipe_load_binaries() enter:\n");
7531 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7532 if (pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
)
7535 switch (pipe
->mode
) {
7536 case IA_CSS_PIPE_ID_PREVIEW
:
7537 err
= load_preview_binaries(pipe
);
7539 case IA_CSS_PIPE_ID_VIDEO
:
7540 err
= load_video_binaries(pipe
);
7542 case IA_CSS_PIPE_ID_CAPTURE
:
7543 err
= load_capture_binaries(pipe
);
7545 case IA_CSS_PIPE_ID_YUVPP
:
7546 err
= load_yuvpp_binaries(pipe
);
7548 case IA_CSS_PIPE_ID_ACC
:
7551 err
= IA_CSS_ERR_INTERNAL_ERROR
;
7554 if (err
!= IA_CSS_SUCCESS
) {
7555 if (sh_css_pipe_unload_binaries(pipe
) != IA_CSS_SUCCESS
) {
7556 /* currently css does not support multiple error returns in a single function,
7557 * using IA_CSS_ERR_INTERNAL_ERROR in this case */
7558 err
= IA_CSS_ERR_INTERNAL_ERROR
;
7564 static enum ia_css_err
7565 create_host_yuvpp_pipeline(struct ia_css_pipe
*pipe
)
7567 struct ia_css_pipeline
*me
;
7568 enum ia_css_err err
= IA_CSS_SUCCESS
;
7569 struct ia_css_pipeline_stage
*vf_pp_stage
= NULL
,
7571 *yuv_scaler_stage
= NULL
;
7572 struct ia_css_binary
*copy_binary
,
7575 bool need_scaler
= false;
7576 unsigned int num_stage
, num_vf_pp_stage
, num_output_stage
;
7579 struct ia_css_frame
*in_frame
= NULL
;
7580 struct ia_css_frame
*out_frame
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
];
7581 struct ia_css_frame
*bin_out_frame
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
7582 struct ia_css_frame
*vf_frame
[IA_CSS_PIPE_MAX_OUTPUT_STAGE
];
7583 struct ia_css_pipeline_stage_desc stage_desc
;
7584 bool need_in_frameinfo_memory
= false;
7585 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7586 bool sensor
= false;
7587 bool buffered_sensor
= false;
7588 bool online
= false;
7589 bool continuous
= false;
7592 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
7593 if ((pipe
== NULL
) || (pipe
->stream
== NULL
) || (pipe
->mode
!= IA_CSS_PIPE_ID_YUVPP
)) {
7594 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
7595 return IA_CSS_ERR_INVALID_ARGUMENTS
;
7597 me
= &pipe
->pipeline
;
7598 ia_css_pipeline_clean(me
);
7599 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
7600 out_frame
[i
] = NULL
;
7603 ia_css_pipe_util_create_output_frames(bin_out_frame
);
7604 num_stage
= pipe
->pipe_settings
.yuvpp
.num_yuv_scaler
;
7605 num_vf_pp_stage
= pipe
->pipe_settings
.yuvpp
.num_vf_pp
;
7606 num_output_stage
= pipe
->pipe_settings
.yuvpp
.num_output
;
7608 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7609 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7610 * except for the following:
7611 * - Direct Sensor Mode Online Capture
7612 * - Direct Sensor Mode Continuous Capture
7613 * - Buffered Sensor Mode Continous Capture
7615 sensor
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
;
7616 buffered_sensor
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
;
7617 online
= pipe
->stream
->config
.online
;
7618 continuous
= pipe
->stream
->config
.continuous
;
7619 need_in_frameinfo_memory
=
7620 !((sensor
&& (online
|| continuous
)) || (buffered_sensor
&& continuous
));
7622 /* Construct in_frame info (only in case we have dynamic input */
7623 need_in_frameinfo_memory
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
7625 /* the input frame can come from:
7626 * a) memory: connect yuvscaler to me->in_frame
7627 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7628 if (need_in_frameinfo_memory
) {
7629 /* TODO: improve for different input formats. */
7632 * "pipe->stream->config.input_config.format" represents the sensor output
7633 * frame format, e.g. YUV422 8-bit.
7635 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7638 int in_frame_format
;
7639 if (pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY
) {
7640 in_frame_format
= IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
;
7641 } else if (pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_YUV422_8
) {
7643 * When the sensor output frame format is "IA_CSS_STREAM_FORMAT_YUV422_8",
7644 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7647 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7648 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7650 * By now, the "isp_copy_var" binary does NOT provide a separated
7651 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7652 * the YUV422-8 pixels in the frame-line buffer which is designed to
7653 * store the Bayer-Quad RAW pixels.
7655 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7656 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7659 in_frame_format
= IA_CSS_FRAME_FORMAT_RAW
;
7661 in_frame_format
= IA_CSS_FRAME_FORMAT_NV12
;
7664 err
= init_in_frameinfo_memory_defaults(pipe
,
7668 if (err
!= IA_CSS_SUCCESS
) {
7669 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7673 in_frame
= &me
->in_frame
;
7678 for (i
= 0; i
< num_output_stage
; i
++) {
7679 assert(i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
);
7680 if (pipe
->output_info
[i
].res
.width
!= 0) {
7681 err
= init_out_frameinfo_defaults(pipe
, &me
->out_frame
[i
], i
);
7682 if (err
!= IA_CSS_SUCCESS
) {
7683 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7686 out_frame
[i
] = &me
->out_frame
[i
];
7689 /* Construct vf_frame info (only in case we have VF) */
7690 if (pipe
->vf_output_info
[i
].res
.width
!= 0) {
7691 err
= init_vf_frameinfo_defaults(pipe
, &me
->vf_frame
[i
], i
);
7692 if (err
!= IA_CSS_SUCCESS
) {
7693 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7696 vf_frame
[i
] = &me
->vf_frame
[i
];
7700 copy_binary
= &pipe
->pipe_settings
.yuvpp
.copy_binary
;
7701 vf_pp_binary
= pipe
->pipe_settings
.yuvpp
.vf_pp_binary
;
7702 yuv_scaler_binary
= pipe
->pipe_settings
.yuvpp
.yuv_scaler_binary
;
7703 need_scaler
= need_yuv_scaler_stage(pipe
);
7705 if (pipe
->pipe_settings
.yuvpp
.copy_binary
.info
) {
7707 struct ia_css_frame
*in_frame_local
= NULL
;
7709 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7710 /* After isp copy is enabled in_frame needs to be passed. */
7712 in_frame_local
= in_frame
;
7716 ia_css_pipe_util_set_output_frames(bin_out_frame
, 0, NULL
);
7717 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
7718 bin_out_frame
, in_frame_local
, NULL
);
7720 ia_css_pipe_util_set_output_frames(bin_out_frame
, 0, out_frame
[0]);
7721 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
7722 bin_out_frame
, in_frame_local
, NULL
);
7725 err
= ia_css_pipeline_create_and_add_stage(me
,
7729 if (err
!= IA_CSS_SUCCESS
) {
7730 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7735 /* if we use yuv scaler binary, vf output should be from there */
7736 copy_stage
->args
.copy_vf
= !need_scaler
;
7737 /* for yuvpp pipe, it should always be enabled */
7738 copy_stage
->args
.copy_output
= true;
7739 /* connect output of copy binary to input of yuv scaler */
7740 in_frame
= copy_stage
->args
.out_frame
[0];
7745 struct ia_css_frame
*tmp_out_frame
= NULL
;
7746 struct ia_css_frame
*tmp_vf_frame
= NULL
;
7747 struct ia_css_frame
*tmp_in_frame
= in_frame
;
7749 for (i
= 0, j
= 0; i
< num_stage
; i
++) {
7750 assert(j
< num_output_stage
);
7751 if (pipe
->pipe_settings
.yuvpp
.is_output_stage
[i
] == true) {
7752 tmp_out_frame
= out_frame
[j
];
7753 tmp_vf_frame
= vf_frame
[j
];
7755 tmp_out_frame
= NULL
;
7756 tmp_vf_frame
= NULL
;
7759 err
= add_yuv_scaler_stage(pipe
, me
, tmp_in_frame
, tmp_out_frame
,
7761 &yuv_scaler_binary
[i
],
7764 if (err
!= IA_CSS_SUCCESS
) {
7765 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7768 /* we use output port 1 as internal output port */
7769 tmp_in_frame
= yuv_scaler_stage
->args
.out_frame
[1];
7770 if (pipe
->pipe_settings
.yuvpp
.is_output_stage
[i
] == true) {
7771 if (tmp_vf_frame
&& (tmp_vf_frame
->info
.res
.width
!= 0)) {
7772 in_frame
= yuv_scaler_stage
->args
.out_vf_frame
;
7773 err
= add_vf_pp_stage(pipe
, in_frame
, tmp_vf_frame
, &vf_pp_binary
[j
],
7776 if (err
!= IA_CSS_SUCCESS
) {
7777 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7784 } else if (copy_stage
!= NULL
) {
7785 if (vf_frame
[0] != NULL
&& vf_frame
[0]->info
.res
.width
!= 0) {
7786 in_frame
= copy_stage
->args
.out_vf_frame
;
7787 err
= add_vf_pp_stage(pipe
, in_frame
, vf_frame
[0], &vf_pp_binary
[0],
7790 if (err
!= IA_CSS_SUCCESS
) {
7791 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7796 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
7798 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
7800 return IA_CSS_SUCCESS
;
7803 static enum ia_css_err
7804 create_host_copy_pipeline(struct ia_css_pipe
*pipe
,
7805 unsigned max_input_width
,
7806 struct ia_css_frame
*out_frame
)
7808 struct ia_css_pipeline
*me
;
7809 enum ia_css_err err
= IA_CSS_SUCCESS
;
7810 struct ia_css_pipeline_stage_desc stage_desc
;
7812 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
7813 "create_host_copy_pipeline() enter:\n");
7815 /* pipeline already created as part of create_host_pipeline_structure */
7816 me
= &pipe
->pipeline
;
7817 ia_css_pipeline_clean(me
);
7819 /* Construct out_frame info */
7820 out_frame
->contiguous
= false;
7821 out_frame
->flash_state
= IA_CSS_FRAME_FLASH_STATE_NONE
;
7823 if (copy_on_sp(pipe
) &&
7824 pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_BINARY_8
) {
7825 ia_css_frame_info_init(
7829 IA_CSS_FRAME_FORMAT_BINARY_8
,
7831 } else if (out_frame
->info
.format
== IA_CSS_FRAME_FORMAT_RAW
) {
7832 out_frame
->info
.raw_bit_depth
=
7833 ia_css_pipe_util_pipe_input_format_bpp(pipe
);
7837 me
->pipe_id
= IA_CSS_PIPE_ID_COPY
;
7838 pipe
->mode
= IA_CSS_PIPE_ID_COPY
;
7840 ia_css_pipe_get_sp_func_stage_desc(&stage_desc
, out_frame
,
7841 IA_CSS_PIPELINE_RAW_COPY
, max_input_width
);
7842 err
= ia_css_pipeline_create_and_add_stage(me
,
7846 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
7848 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
7849 "create_host_copy_pipeline() leave:\n");
7854 static enum ia_css_err
7855 create_host_isyscopy_capture_pipeline(struct ia_css_pipe
*pipe
)
7857 struct ia_css_pipeline
*me
= &pipe
->pipeline
;
7858 enum ia_css_err err
= IA_CSS_SUCCESS
;
7859 struct ia_css_pipeline_stage_desc stage_desc
;
7860 struct ia_css_frame
*out_frame
= &me
->out_frame
[0];
7861 struct ia_css_pipeline_stage
*out_stage
= NULL
;
7862 unsigned int thread_id
;
7863 enum sh_css_queue_id queue_id
;
7864 unsigned int max_input_width
= MAX_VECTORS_PER_INPUT_LINE_CONT
* ISP_VEC_NELEMS
;
7866 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
7867 "create_host_isyscopy_capture_pipeline() enter:\n");
7868 ia_css_pipeline_clean(me
);
7870 /* Construct out_frame info */
7871 err
= sh_css_pipe_get_output_frame_info(pipe
, &out_frame
->info
, 0);
7872 if (err
!= IA_CSS_SUCCESS
)
7874 out_frame
->contiguous
= false;
7875 out_frame
->flash_state
= IA_CSS_FRAME_FLASH_STATE_NONE
;
7876 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
7877 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, thread_id
, &queue_id
);
7878 out_frame
->dynamic_queue_id
= queue_id
;
7879 out_frame
->buf_type
= IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
;
7882 me
->pipe_id
= IA_CSS_PIPE_ID_CAPTURE
;
7883 pipe
->mode
= IA_CSS_PIPE_ID_CAPTURE
;
7884 ia_css_pipe_get_sp_func_stage_desc(&stage_desc
, out_frame
,
7885 IA_CSS_PIPELINE_ISYS_COPY
, max_input_width
);
7886 err
= ia_css_pipeline_create_and_add_stage(me
,
7887 &stage_desc
, &out_stage
);
7888 if(err
!= IA_CSS_SUCCESS
)
7891 ia_css_pipeline_finalize_stages(me
, pipe
->stream
->config
.continuous
);
7893 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
7894 "create_host_isyscopy_capture_pipeline() leave:\n");
7899 static enum ia_css_err
7900 create_host_regular_capture_pipeline(struct ia_css_pipe
*pipe
)
7902 struct ia_css_pipeline
*me
;
7903 enum ia_css_err err
= IA_CSS_SUCCESS
;
7904 enum ia_css_capture_mode mode
;
7905 struct ia_css_pipeline_stage
*current_stage
= NULL
;
7906 struct ia_css_pipeline_stage
*yuv_scaler_stage
= NULL
;
7907 struct ia_css_binary
*copy_binary
,
7908 *primary_binary
[MAX_NUM_PRIMARY_STAGES
],
7915 *capture_ldc_binary
;
7916 bool need_pp
= false;
7919 struct ia_css_frame
*in_frame
;
7920 struct ia_css_frame
*out_frame
;
7921 struct ia_css_frame
*out_frames
[IA_CSS_BINARY_MAX_OUTPUT_PORTS
];
7922 struct ia_css_frame
*vf_frame
;
7923 struct ia_css_pipeline_stage_desc stage_desc
;
7924 bool need_in_frameinfo_memory
= false;
7925 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7926 bool sensor
= false;
7927 bool buffered_sensor
= false;
7928 bool online
= false;
7929 bool continuous
= false;
7931 unsigned int i
, num_yuv_scaler
, num_primary_stage
;
7932 bool need_yuv_pp
= false;
7933 bool *is_output_stage
= NULL
;
7934 bool need_ldc
= false;
7936 IA_CSS_ENTER_PRIVATE("");
7937 assert(pipe
!= NULL
);
7938 assert(pipe
->stream
!= NULL
);
7939 assert(pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
|| pipe
->mode
== IA_CSS_PIPE_ID_COPY
);
7941 me
= &pipe
->pipeline
;
7942 mode
= pipe
->config
.default_capture_config
.mode
;
7943 raw
= (mode
== IA_CSS_CAPTURE_MODE_RAW
);
7944 ia_css_pipeline_clean(me
);
7945 ia_css_pipe_util_create_output_frames(out_frames
);
7947 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7948 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7949 * except for the following:
7950 * - Direct Sensor Mode Online Capture
7951 * - Direct Sensor Mode Online Capture
7952 * - Direct Sensor Mode Continuous Capture
7953 * - Buffered Sensor Mode Continous Capture
7955 sensor
= (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
);
7956 buffered_sensor
= (pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
);
7957 online
= pipe
->stream
->config
.online
;
7958 continuous
= pipe
->stream
->config
.continuous
;
7959 need_in_frameinfo_memory
=
7960 !((sensor
&& (online
|| continuous
)) || (buffered_sensor
&& (online
|| continuous
)));
7962 /* Construct in_frame info (only in case we have dynamic input */
7963 need_in_frameinfo_memory
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
7965 if (need_in_frameinfo_memory
) {
7966 err
= init_in_frameinfo_memory_defaults(pipe
, &me
->in_frame
, IA_CSS_FRAME_FORMAT_RAW
);
7967 if (err
!= IA_CSS_SUCCESS
) {
7968 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7972 in_frame
= &me
->in_frame
;
7977 err
= init_out_frameinfo_defaults(pipe
, &me
->out_frame
[0], 0);
7978 if (err
!= IA_CSS_SUCCESS
) {
7979 IA_CSS_LEAVE_ERR_PRIVATE(err
);
7982 out_frame
= &me
->out_frame
[0];
7984 /* Construct vf_frame info (only in case we have VF) */
7985 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
]) {
7986 if (mode
== IA_CSS_CAPTURE_MODE_RAW
|| mode
== IA_CSS_CAPTURE_MODE_BAYER
) {
7987 /* These modes don't support viewfinder output */
7990 init_vf_frameinfo_defaults(pipe
, &me
->vf_frame
[0], 0);
7991 vf_frame
= &me
->vf_frame
[0];
7997 copy_binary
= &pipe
->pipe_settings
.capture
.copy_binary
;
7998 num_primary_stage
= pipe
->pipe_settings
.capture
.num_primary_stage
;
7999 if ((num_primary_stage
== 0) && (mode
== IA_CSS_CAPTURE_MODE_PRIMARY
)) {
8000 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
8001 return IA_CSS_ERR_INTERNAL_ERROR
;
8003 for (i
= 0; i
< num_primary_stage
; i
++) {
8004 primary_binary
[i
] = &pipe
->pipe_settings
.capture
.primary_binary
[i
];
8006 vf_pp_binary
= &pipe
->pipe_settings
.capture
.vf_pp_binary
;
8007 pre_isp_binary
= &pipe
->pipe_settings
.capture
.pre_isp_binary
;
8008 anr_gdc_binary
= &pipe
->pipe_settings
.capture
.anr_gdc_binary
;
8009 post_isp_binary
= &pipe
->pipe_settings
.capture
.post_isp_binary
;
8010 capture_pp_binary
= &pipe
->pipe_settings
.capture
.capture_pp_binary
;
8011 yuv_scaler_binary
= pipe
->pipe_settings
.capture
.yuv_scaler_binary
;
8012 num_yuv_scaler
= pipe
->pipe_settings
.capture
.num_yuv_scaler
;
8013 is_output_stage
= pipe
->pipe_settings
.capture
.is_output_stage
;
8014 capture_ldc_binary
= &pipe
->pipe_settings
.capture
.capture_ldc_binary
;
8016 need_pp
= (need_capture_pp(pipe
) || pipe
->output_stage
) &&
8017 mode
!= IA_CSS_CAPTURE_MODE_RAW
&&
8018 mode
!= IA_CSS_CAPTURE_MODE_BAYER
;
8019 need_yuv_pp
= (yuv_scaler_binary
!= NULL
&& yuv_scaler_binary
->info
!= NULL
);
8020 need_ldc
= (capture_ldc_binary
!= NULL
&& capture_ldc_binary
->info
!= NULL
);
8022 if (pipe
->pipe_settings
.capture
.copy_binary
.info
) {
8024 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
8025 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
8027 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
8028 out_frames
, in_frame
, NULL
);
8030 in_frame
= pipe
->stream
->last_pipe
->continuous_frames
[0];
8031 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
8032 out_frames
, in_frame
, NULL
);
8035 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
8036 out_frames
, NULL
, NULL
);
8039 ia_css_pipe_util_set_output_frames(out_frames
, 0, in_frame
);
8040 ia_css_pipe_get_generic_stage_desc(&stage_desc
, copy_binary
,
8041 out_frames
, NULL
, NULL
);
8044 err
= ia_css_pipeline_create_and_add_stage(me
,
8047 if (err
!= IA_CSS_SUCCESS
) {
8048 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8051 } else if (pipe
->stream
->config
.continuous
) {
8052 in_frame
= pipe
->stream
->last_pipe
->continuous_frames
[0];
8055 if (mode
== IA_CSS_CAPTURE_MODE_PRIMARY
) {
8057 struct ia_css_frame
*local_in_frame
= NULL
;
8058 struct ia_css_frame
*local_out_frame
= NULL
;
8060 for (i
= 0; i
< num_primary_stage
; i
++) {
8062 local_in_frame
= in_frame
;
8064 local_in_frame
= NULL
;
8066 if (!need_pp
&& (i
== num_primary_stage
- 1))
8068 if (!need_pp
&& (i
== num_primary_stage
- 1) && !need_ldc
)
8070 local_out_frame
= out_frame
;
8072 local_out_frame
= NULL
;
8073 ia_css_pipe_util_set_output_frames(out_frames
, 0, local_out_frame
);
8075 * WARNING: The #if def flag has been added below as a
8076 * temporary solution to solve the problem of enabling the
8077 * view finder in a single binary in a capture flow. The
8078 * vf-pp stage has been removed from Skycam in the solution
8079 * provided. The vf-pp stage should be re-introduced when
8080 * required. This * should not be considered as a clean solution.
8081 * Proper investigation should be done to come up with the clean
8084 ia_css_pipe_get_generic_stage_desc(&stage_desc
, primary_binary
[i
],
8085 out_frames
, local_in_frame
, NULL
);
8086 err
= ia_css_pipeline_create_and_add_stage(me
,
8089 if (err
!= IA_CSS_SUCCESS
) {
8090 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8095 /* If we use copy iso primary,
8096 the input must be yuv iso raw */
8097 current_stage
->args
.copy_vf
=
8098 primary_binary
[0]->info
->sp
.pipeline
.mode
==
8099 IA_CSS_BINARY_MODE_COPY
;
8100 current_stage
->args
.copy_output
= current_stage
->args
.copy_vf
;
8101 } else if (mode
== IA_CSS_CAPTURE_MODE_ADVANCED
||
8102 mode
== IA_CSS_CAPTURE_MODE_LOW_LIGHT
) {
8103 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
8104 ia_css_pipe_get_generic_stage_desc(&stage_desc
, pre_isp_binary
,
8105 out_frames
, in_frame
, NULL
);
8106 err
= ia_css_pipeline_create_and_add_stage(me
,
8108 if (err
!= IA_CSS_SUCCESS
) {
8109 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8112 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
8113 ia_css_pipe_get_generic_stage_desc(&stage_desc
, anr_gdc_binary
,
8114 out_frames
, NULL
, NULL
);
8115 err
= ia_css_pipeline_create_and_add_stage(me
,
8117 if (err
!= IA_CSS_SUCCESS
) {
8118 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8123 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
8124 ia_css_pipe_get_generic_stage_desc(&stage_desc
, post_isp_binary
,
8125 out_frames
, NULL
, NULL
);
8127 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
8128 ia_css_pipe_get_generic_stage_desc(&stage_desc
, post_isp_binary
,
8129 out_frames
, NULL
, NULL
);
8132 err
= ia_css_pipeline_create_and_add_stage(me
,
8133 &stage_desc
, ¤t_stage
);
8134 if (err
!= IA_CSS_SUCCESS
) {
8135 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8138 } else if (mode
== IA_CSS_CAPTURE_MODE_BAYER
) {
8139 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
8140 ia_css_pipe_get_generic_stage_desc(&stage_desc
, pre_isp_binary
,
8141 out_frames
, in_frame
, NULL
);
8142 err
= ia_css_pipeline_create_and_add_stage(me
,
8145 if (err
!= IA_CSS_SUCCESS
) {
8146 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8152 if (need_pp
&& current_stage
) {
8153 struct ia_css_frame
*local_in_frame
= NULL
;
8154 local_in_frame
= current_stage
->args
.out_frame
[0];
8157 ia_css_pipe_util_set_output_frames(out_frames
, 0, NULL
);
8158 ia_css_pipe_get_generic_stage_desc(&stage_desc
, capture_ldc_binary
,
8159 out_frames
, local_in_frame
, NULL
);
8160 err
= ia_css_pipeline_create_and_add_stage(me
,
8163 local_in_frame
= current_stage
->args
.out_frame
[0];
8165 err
= add_capture_pp_stage(pipe
, me
, local_in_frame
, need_yuv_pp
? NULL
: out_frame
,
8167 /* ldc and capture_pp not supported in same pipeline */
8168 if (need_ldc
&& current_stage
) {
8169 in_frame
= current_stage
->args
.out_frame
[0];
8170 ia_css_pipe_util_set_output_frames(out_frames
, 0, out_frame
);
8171 ia_css_pipe_get_generic_stage_desc(&stage_desc
, capture_ldc_binary
,
8172 out_frames
, in_frame
, NULL
);
8173 err
= ia_css_pipeline_create_and_add_stage(me
,
8176 } else if (need_pp
&& current_stage
) {
8177 in_frame
= current_stage
->args
.out_frame
[0];
8178 err
= add_capture_pp_stage(pipe
, me
, in_frame
, need_yuv_pp
? NULL
: out_frame
,
8182 if (err
!= IA_CSS_SUCCESS
) {
8183 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8188 if (need_yuv_pp
&& current_stage
) {
8189 struct ia_css_frame
*tmp_in_frame
= current_stage
->args
.out_frame
[0];
8190 struct ia_css_frame
*tmp_out_frame
= NULL
;
8192 for (i
= 0; i
< num_yuv_scaler
; i
++) {
8193 if (is_output_stage
[i
] == true)
8194 tmp_out_frame
= out_frame
;
8196 tmp_out_frame
= NULL
;
8198 err
= add_yuv_scaler_stage(pipe
, me
, tmp_in_frame
, tmp_out_frame
,
8200 &yuv_scaler_binary
[i
],
8202 if (err
!= IA_CSS_SUCCESS
) {
8203 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8206 /* we use output port 1 as internal output port */
8207 tmp_in_frame
= yuv_scaler_stage
->args
.out_frame
[1];
8212 * WARNING: The #if def flag has been added below as a
8213 * temporary solution to solve the problem of enabling the
8214 * view finder in a single binary in a capture flow. The vf-pp
8215 * stage has been removed from Skycam in the solution provided.
8216 * The vf-pp stage should be re-introduced when required. This
8217 * should not be considered as a clean solution. Proper
8218 * investigation should be done to come up with the clean solution.
8220 if (mode
!= IA_CSS_CAPTURE_MODE_RAW
&& mode
!= IA_CSS_CAPTURE_MODE_BAYER
&& current_stage
&& vf_frame
) {
8221 in_frame
= current_stage
->args
.out_vf_frame
;
8222 err
= add_vf_pp_stage(pipe
, in_frame
, vf_frame
, vf_pp_binary
,
8224 if (err
!= IA_CSS_SUCCESS
) {
8225 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8229 ia_css_pipeline_finalize_stages(&pipe
->pipeline
, pipe
->stream
->config
.continuous
);
8231 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
8232 "create_host_regular_capture_pipeline() leave:\n");
8234 return IA_CSS_SUCCESS
;
8237 static enum ia_css_err
8238 create_host_capture_pipeline(struct ia_css_pipe
*pipe
)
8240 enum ia_css_err err
= IA_CSS_SUCCESS
;
8242 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
8244 if (pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
)
8245 err
= create_host_isyscopy_capture_pipeline(pipe
);
8247 err
= create_host_regular_capture_pipeline(pipe
);
8248 if (err
!= IA_CSS_SUCCESS
) {
8249 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8253 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8258 static enum ia_css_err
capture_start(
8259 struct ia_css_pipe
*pipe
)
8261 struct ia_css_pipeline
*me
;
8263 enum ia_css_err err
= IA_CSS_SUCCESS
;
8264 enum sh_css_pipe_config_override copy_ovrd
;
8266 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe
);
8268 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
8269 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8272 me
= &pipe
->pipeline
;
8274 if ((pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_RAW
||
8275 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
) &&
8276 (pipe
->config
.mode
!= IA_CSS_PIPE_MODE_COPY
)) {
8277 if (copy_on_sp(pipe
)) {
8278 err
= start_copy_on_sp(pipe
, &me
->out_frame
[0]);
8279 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8284 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8285 /* old isys: need to send_mipi_frames() in all pipe modes */
8286 err
= send_mipi_frames(pipe
);
8287 if (err
!= IA_CSS_SUCCESS
) {
8288 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8291 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8292 if (pipe
->config
.mode
!= IA_CSS_PIPE_MODE_COPY
) {
8293 err
= send_mipi_frames(pipe
);
8294 if (err
!= IA_CSS_SUCCESS
) {
8295 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8303 unsigned int thread_id
;
8305 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
8306 copy_ovrd
= 1 << thread_id
;
8309 start_pipe(pipe
, copy_ovrd
, pipe
->stream
->config
.mode
);
8311 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8313 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8314 * which is currently done in start_binary(); but COPY pipe contains no binary,
8315 * and does not call start_binary(); so we need to configure the rx here.
8317 if (pipe
->config
.mode
== IA_CSS_PIPE_MODE_COPY
&& pipe
->stream
->reconfigure_css_rx
) {
8318 ia_css_isys_rx_configure(&pipe
->stream
->csi_rx_config
, pipe
->stream
->config
.mode
);
8319 pipe
->stream
->reconfigure_css_rx
= false;
8323 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8328 static enum ia_css_err
8329 sh_css_pipe_get_output_frame_info(struct ia_css_pipe
*pipe
,
8330 struct ia_css_frame_info
*info
,
8333 enum ia_css_err err
= IA_CSS_SUCCESS
;
8335 assert(pipe
!= NULL
);
8336 assert(info
!= NULL
);
8338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
8339 "sh_css_pipe_get_output_frame_info() enter:\n");
8341 *info
= pipe
->output_info
[idx
];
8342 if (copy_on_sp(pipe
) &&
8343 pipe
->stream
->config
.input_config
.format
== IA_CSS_STREAM_FORMAT_BINARY_8
) {
8344 ia_css_frame_info_init(
8348 IA_CSS_FRAME_FORMAT_BINARY_8
,
8350 } else if (info
->format
== IA_CSS_FRAME_FORMAT_RAW
||
8351 info
->format
== IA_CSS_FRAME_FORMAT_RAW_PACKED
) {
8352 info
->raw_bit_depth
=
8353 ia_css_pipe_util_pipe_input_format_bpp(pipe
);
8357 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
8358 "sh_css_pipe_get_output_frame_info() leave:\n");
8362 #if !defined(HAS_NO_INPUT_SYSTEM)
8364 ia_css_stream_send_input_frame(const struct ia_css_stream
*stream
,
8365 const unsigned short *data
,
8367 unsigned int height
)
8369 assert(stream
!= NULL
);
8371 ia_css_inputfifo_send_input_frame(
8372 data
, width
, height
,
8373 stream
->config
.channel_id
,
8374 stream
->config
.input_config
.format
,
8375 stream
->config
.pixels_per_clock
== 2);
8379 ia_css_stream_start_input_frame(const struct ia_css_stream
*stream
)
8381 assert(stream
!= NULL
);
8383 ia_css_inputfifo_start_frame(
8384 stream
->config
.channel_id
,
8385 stream
->config
.input_config
.format
,
8386 stream
->config
.pixels_per_clock
== 2);
8390 ia_css_stream_send_input_line(const struct ia_css_stream
*stream
,
8391 const unsigned short *data
,
8393 const unsigned short *data2
,
8394 unsigned int width2
)
8396 assert(stream
!= NULL
);
8398 ia_css_inputfifo_send_line(stream
->config
.channel_id
,
8399 data
, width
, data2
, width2
);
8403 ia_css_stream_send_input_embedded_line(const struct ia_css_stream
*stream
,
8404 enum ia_css_stream_format format
,
8405 const unsigned short *data
,
8408 assert(stream
!= NULL
);
8409 if (data
== NULL
|| width
== 0)
8411 ia_css_inputfifo_send_embedded_line(stream
->config
.channel_id
,
8412 format
, data
, width
);
8416 ia_css_stream_end_input_frame(const struct ia_css_stream
*stream
)
8418 assert(stream
!= NULL
);
8420 ia_css_inputfifo_end_frame(stream
->config
.channel_id
);
8425 append_firmware(struct ia_css_fw_info
**l
, struct ia_css_fw_info
*firmware
)
8427 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l
, firmware
);
8429 IA_CSS_ERROR("NULL fw_info");
8430 IA_CSS_LEAVE_PRIVATE("");
8436 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8437 IA_CSS_LEAVE_PRIVATE("");
8441 remove_firmware(struct ia_css_fw_info
**l
, struct ia_css_fw_info
*firmware
)
8447 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "remove_firmware() enter:\n");
8449 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
, "remove_firmware() leave:\n");
8450 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8453 static enum ia_css_err
upload_isp_code(struct ia_css_fw_info
*firmware
)
8455 hrt_vaddress binary
;
8457 if (firmware
== NULL
) {
8458 IA_CSS_ERROR("NULL input parameter");
8459 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8461 binary
= firmware
->info
.isp
.xmem_addr
;
8464 unsigned size
= firmware
->blob
.size
;
8465 const unsigned char *blob
;
8466 const unsigned char *binary_name
;
8468 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8470 blob
= binary_name
+
8471 strlen((const char *)binary_name
) +
8473 binary
= sh_css_load_blob(blob
, size
);
8474 firmware
->info
.isp
.xmem_addr
= binary
;
8478 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
8479 return IA_CSS_SUCCESS
;
8482 static enum ia_css_err
8483 acc_load_extension(struct ia_css_fw_info
*firmware
)
8485 enum ia_css_err err
;
8486 struct ia_css_fw_info
*hd
= firmware
;
8488 err
= upload_isp_code(hd
);
8489 if (err
!= IA_CSS_SUCCESS
)
8494 if (firmware
== NULL
)
8495 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8496 firmware
->loaded
= true;
8497 return IA_CSS_SUCCESS
;
8501 acc_unload_extension(struct ia_css_fw_info
*firmware
)
8503 struct ia_css_fw_info
*hd
= firmware
;
8504 struct ia_css_fw_info
*hdn
= NULL
;
8506 if (firmware
== NULL
) /* should not happen */
8508 /* unload and remove multiple firmwares */
8510 hdn
= (hd
->next
) ? &(*hd
->next
) : NULL
;
8511 if (hd
->info
.isp
.xmem_addr
) {
8512 hmm_free(hd
->info
.isp
.xmem_addr
);
8513 hd
->info
.isp
.xmem_addr
= mmgr_NULL
;
8515 hd
->isp_code
= NULL
;
8520 firmware
->loaded
= false;
8522 /* Load firmware for extension */
8523 static enum ia_css_err
8524 ia_css_pipe_load_extension(struct ia_css_pipe
*pipe
,
8525 struct ia_css_fw_info
*firmware
)
8527 enum ia_css_err err
= IA_CSS_SUCCESS
;
8529 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware
, pipe
);
8531 if ((firmware
== NULL
) || (pipe
== NULL
)) {
8532 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
8533 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8536 if (firmware
->info
.isp
.type
== IA_CSS_ACC_OUTPUT
) {
8537 if (&pipe
->output_stage
!= NULL
)
8538 append_firmware(&pipe
->output_stage
, firmware
);
8540 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
8541 return IA_CSS_ERR_INTERNAL_ERROR
;
8544 else if (firmware
->info
.isp
.type
== IA_CSS_ACC_VIEWFINDER
) {
8545 if (&pipe
->vf_stage
!= NULL
)
8546 append_firmware(&pipe
->vf_stage
, firmware
);
8548 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR
);
8549 return IA_CSS_ERR_INTERNAL_ERROR
;
8552 err
= acc_load_extension(firmware
);
8554 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8558 /* Unload firmware for extension */
8560 ia_css_pipe_unload_extension(struct ia_css_pipe
*pipe
,
8561 struct ia_css_fw_info
*firmware
)
8563 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware
, pipe
);
8565 if ((firmware
== NULL
) || (pipe
== NULL
)) {
8566 IA_CSS_ERROR("NULL input parameters");
8567 IA_CSS_LEAVE_PRIVATE("");
8571 if (firmware
->info
.isp
.type
== IA_CSS_ACC_OUTPUT
)
8572 remove_firmware(&pipe
->output_stage
, firmware
);
8573 else if (firmware
->info
.isp
.type
== IA_CSS_ACC_VIEWFINDER
)
8574 remove_firmware(&pipe
->vf_stage
, firmware
);
8575 acc_unload_extension(firmware
);
8577 IA_CSS_LEAVE_PRIVATE("");
8581 ia_css_pipeline_uses_params(struct ia_css_pipeline
*me
)
8583 struct ia_css_pipeline_stage
*stage
;
8587 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8588 "ia_css_pipeline_uses_params() enter: me=%p\n", me
);
8590 for (stage
= me
->stages
; stage
; stage
= stage
->next
)
8591 if (stage
->binary_info
&& stage
->binary_info
->enable
.params
) {
8592 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8593 "ia_css_pipeline_uses_params() leave: "
8594 "return_bool=true\n");
8597 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8598 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8602 static enum ia_css_err
8603 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline
*pipeline
,
8606 struct ia_css_fw_info
*fw
= (struct ia_css_fw_info
*)acc_fw
;
8607 /* In QoS case, load_extension already called, so skipping */
8608 enum ia_css_err err
= IA_CSS_SUCCESS
;
8609 if (fw
->loaded
== false)
8610 err
= acc_load_extension(fw
);
8612 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8613 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p,"
8614 " acc_fw=%p\n", pipeline
, acc_fw
);
8616 if (err
== IA_CSS_SUCCESS
) {
8617 struct ia_css_pipeline_stage_desc stage_desc
;
8618 ia_css_pipe_get_acc_stage_desc(&stage_desc
, NULL
, fw
);
8619 err
= ia_css_pipeline_create_and_add_stage(pipeline
,
8624 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8625 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n",err
);
8630 * @brief Tag a specific frame in continuous capture.
8631 * Refer to "sh_css_internal.h" for details.
8633 enum ia_css_err
ia_css_stream_capture_frame(struct ia_css_stream
*stream
,
8634 unsigned int exp_id
)
8636 struct sh_css_tag_descr tag_descr
;
8637 uint32_t encoded_tag_descr
;
8638 enum ia_css_err err
;
8640 assert(stream
!= NULL
);
8641 IA_CSS_ENTER("exp_id=%d", exp_id
);
8643 /* Only continuous streams have a tagger */
8644 if (exp_id
== 0 || !stream
->config
.continuous
) {
8645 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
8646 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8649 if (!sh_css_sp_is_running()) {
8650 /* SP is not running. The queues are not valid */
8651 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
);
8652 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
8655 /* Create the tag descriptor from the parameters */
8656 sh_css_create_tag_descr(0, 0, 0, exp_id
, &tag_descr
);
8657 /* Encode the tag descriptor into a 32-bit value */
8658 encoded_tag_descr
= sh_css_encode_tag_descr(&tag_descr
);
8659 /* Enqueue the encoded tag to the host2sp queue.
8660 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8661 * on both host and the SP side.
8662 * It is mainly because it is enough to have only one tag_cmd queue */
8663 err
= ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr
);
8665 IA_CSS_LEAVE_ERR(err
);
8670 * @brief Configure the continuous capture.
8671 * Refer to "sh_css_internal.h" for details.
8673 enum ia_css_err
ia_css_stream_capture(
8674 struct ia_css_stream
*stream
,
8679 struct sh_css_tag_descr tag_descr
;
8680 unsigned int encoded_tag_descr
;
8681 enum ia_css_err return_err
;
8684 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8686 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8687 "ia_css_stream_capture() enter: num_captures=%d,"
8688 " skip=%d, offset=%d\n", num_captures
, skip
,offset
);
8690 /* Check if the tag descriptor is valid */
8691 if (num_captures
< SH_CSS_MINIMUM_TAG_ID
) {
8692 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8693 "ia_css_stream_capture() leave: return_err=%d\n",
8694 IA_CSS_ERR_INVALID_ARGUMENTS
);
8695 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8698 /* Create the tag descriptor from the parameters */
8699 sh_css_create_tag_descr(num_captures
, skip
, offset
, 0, &tag_descr
);
8702 /* Encode the tag descriptor into a 32-bit value */
8703 encoded_tag_descr
= sh_css_encode_tag_descr(&tag_descr
);
8705 if (!sh_css_sp_is_running()) {
8706 /* SP is not running. The queues are not valid */
8707 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8708 "ia_css_stream_capture() leaving:"
8709 "queues unavailable\n");
8710 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
8713 /* Enqueue the encoded tag to the host2sp queue.
8714 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8715 * on both host and the SP side.
8716 * It is mainly because it is enough to have only one tag_cmd queue */
8717 return_err
= ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr
);
8719 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8720 "ia_css_stream_capture() leave: return_err=%d\n",
8726 void ia_css_stream_request_flash(struct ia_css_stream
*stream
)
8730 assert(stream
!= NULL
);
8731 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_request_flash() enter: void\n");
8734 sh_css_write_host2sp_command(host2sp_cmd_start_flash
);
8736 if (sh_css_sp_is_running()) {
8737 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash
)) {
8738 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8739 ia_css_debug_dump_sp_sw_debug_info();
8740 ia_css_debug_dump_debug_info(NULL
);
8743 IA_CSS_LOG("SP is not running!");
8746 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
8747 "ia_css_stream_request_flash() leave: return_void\n");
8751 sh_css_init_host_sp_control_vars(void)
8753 const struct ia_css_fw_info
*fw
;
8754 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started
;
8756 unsigned int HIVE_ADDR_host_sp_queues_initialized
;
8757 unsigned int HIVE_ADDR_sp_sleep_mode
;
8758 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb
;
8760 unsigned int HIVE_ADDR_sp_stop_copy_preview
;
8762 unsigned int HIVE_ADDR_host_sp_com
;
8763 unsigned int o
= offsetof(struct host_sp_communication
, host2sp_command
)
8766 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8770 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
8771 "sh_css_init_host_sp_control_vars() enter: void\n");
8774 HIVE_ADDR_ia_css_ispctrl_sp_isp_started
= fw
->info
.sp
.isp_started
;
8776 HIVE_ADDR_host_sp_queues_initialized
=
8777 fw
->info
.sp
.host_sp_queues_initialized
;
8778 HIVE_ADDR_sp_sleep_mode
= fw
->info
.sp
.sleep_mode
;
8779 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb
= fw
->info
.sp
.invalidate_tlb
;
8781 HIVE_ADDR_sp_stop_copy_preview
= fw
->info
.sp
.stop_copy_preview
;
8783 HIVE_ADDR_host_sp_com
= fw
->info
.sp
.host_sp_com
;
8785 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started
; /* Suppres warnings in CRUN */
8787 (void)HIVE_ADDR_sp_sleep_mode
;
8788 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb
;
8790 (void)HIVE_ADDR_sp_stop_copy_preview
;
8792 (void)HIVE_ADDR_host_sp_com
;
8794 sp_dmem_store_uint32(SP0_ID
,
8795 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started
),
8798 sp_dmem_store_uint32(SP0_ID
,
8799 (unsigned int)sp_address_of(host_sp_queues_initialized
),
8801 sp_dmem_store_uint32(SP0_ID
,
8802 (unsigned int)sp_address_of(sp_sleep_mode
),
8804 sp_dmem_store_uint32(SP0_ID
,
8805 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb
),
8808 sp_dmem_store_uint32(SP0_ID
,
8809 (unsigned int)sp_address_of(sp_stop_copy_preview
),
8810 my_css
.stop_copy_preview
?(uint32_t)(1):(uint32_t)(0));
8812 store_sp_array_uint(host_sp_com
, o
, host2sp_cmd_ready
);
8814 #if !defined(HAS_NO_INPUT_SYSTEM)
8815 for (i
= 0; i
< N_CSI_PORTS
; i
++) {
8816 sh_css_update_host2sp_num_mipi_frames
8817 (my_css
.num_mipi_frames
[i
]);
8821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE
,
8822 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8826 * create the internal structures and fill in the configuration data
8828 void ia_css_pipe_config_defaults(struct ia_css_pipe_config
*pipe_config
)
8830 struct ia_css_pipe_config def_config
= DEFAULT_PIPE_CONFIG
;
8832 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_pipe_config_defaults()\n");
8833 *pipe_config
= def_config
;
8837 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
*extra_config
)
8839 if (extra_config
== NULL
) {
8840 IA_CSS_ERROR("NULL input parameter");
8844 extra_config
->enable_raw_binning
= false;
8845 extra_config
->enable_yuv_ds
= false;
8846 extra_config
->enable_high_speed
= false;
8847 extra_config
->enable_dvs_6axis
= false;
8848 extra_config
->enable_reduced_pipe
= false;
8849 extra_config
->disable_vf_pp
= false;
8850 extra_config
->enable_fractional_ds
= false;
8853 void ia_css_stream_config_defaults(struct ia_css_stream_config
*stream_config
)
8855 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_config_defaults()\n");
8856 assert(stream_config
!= NULL
);
8857 memset(stream_config
, 0, sizeof(*stream_config
));
8858 stream_config
->online
= true;
8859 stream_config
->left_padding
= -1;
8860 stream_config
->pixels_per_clock
= 1;
8861 /* temporary default value for backwards compatibility.
8862 * This field used to be hardcoded within CSS but this has now
8863 * been moved to the stream_config struct. */
8864 stream_config
->source
.port
.rxcount
= 0x04040404;
8867 static enum ia_css_err
8868 ia_css_acc_pipe_create(struct ia_css_pipe
*pipe
)
8870 enum ia_css_err err
= IA_CSS_SUCCESS
;
8873 IA_CSS_ERROR("NULL input parameter");
8874 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8877 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8878 if (pipe
->config
.acc_num_execs
== 0)
8879 pipe
->config
.acc_num_execs
= 1;
8881 if (pipe
->config
.acc_extension
) {
8882 err
= ia_css_pipe_load_extension(pipe
, pipe
->config
.acc_extension
);
8889 ia_css_pipe_create(const struct ia_css_pipe_config
*config
,
8890 struct ia_css_pipe
**pipe
)
8895 enum ia_css_err err
= IA_CSS_SUCCESS
;
8896 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config
, pipe
);
8898 if (config
== NULL
) {
8899 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
8901 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8907 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
8909 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8911 return ia_css_pipe_create_extra(config
, NULL
, pipe
);
8915 err
= ia_css_pipe_create_extra(config
, NULL
, pipe
);
8917 if(err
== IA_CSS_SUCCESS
) {
8918 IA_CSS_LOG("pipe created successfuly = %p", *pipe
);
8921 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8928 ia_css_pipe_create_extra(const struct ia_css_pipe_config
*config
,
8929 const struct ia_css_pipe_extra_config
*extra_config
,
8930 struct ia_css_pipe
**pipe
)
8932 enum ia_css_err err
= IA_CSS_ERR_INTERNAL_ERROR
;
8933 struct ia_css_pipe
*internal_pipe
= NULL
;
8936 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config
, extra_config
, pipe
);
8938 /* do not allow to create more than the maximum limit */
8939 if (my_css
.pipe_counter
>= IA_CSS_PIPELINE_NUM_MAX
) {
8940 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED
);
8941 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8944 if ((pipe
== NULL
) || (config
== NULL
)) {
8945 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
8946 return IA_CSS_ERR_INVALID_ARGUMENTS
;
8949 ia_css_debug_dump_pipe_config(config
);
8950 ia_css_debug_dump_pipe_extra_config(extra_config
);
8952 err
= create_pipe(config
->mode
, &internal_pipe
, false);
8953 if (err
!= IA_CSS_SUCCESS
) {
8954 IA_CSS_LEAVE_ERR_PRIVATE(err
);
8958 /* now we have a pipe structure to fill */
8959 internal_pipe
->config
= *config
;
8961 internal_pipe
->extra_config
= *extra_config
;
8963 ia_css_pipe_extra_config_defaults(&internal_pipe
->extra_config
);
8965 if (config
->mode
== IA_CSS_PIPE_MODE_ACC
) {
8966 /* Temporary hack to migrate acceleration to CSS 2.0.
8967 * In the future the code for all pipe types should be
8969 *pipe
= internal_pipe
;
8970 if (!internal_pipe
->config
.acc_extension
&&
8971 internal_pipe
->config
.num_acc_stages
== 0){ /* if no acc binary and no standalone stage */
8973 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
8974 return IA_CSS_SUCCESS
;
8976 return ia_css_acc_pipe_create(internal_pipe
);
8979 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8980 if (internal_pipe
->config
.dvs_frame_delay
== IA_CSS_FRAME_DELAY_2
)
8981 internal_pipe
->dvs_frame_delay
= 2;
8983 internal_pipe
->dvs_frame_delay
= 1;
8986 /* we still keep enable_raw_binning for backward compatibility, for any new
8987 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8988 specified, bayer_ds_out_res will take precedence.if none is specified, we
8989 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8990 sensor output) or use default decimation factor 1. */
8991 if (internal_pipe
->extra_config
.enable_raw_binning
&&
8992 internal_pipe
->config
.bayer_ds_out_res
.width
) {
8993 /* fill some code here, if no code is needed, please remove it during integration */
8996 /* YUV downscaling */
8997 if ((internal_pipe
->config
.vf_pp_in_res
.width
||
8998 internal_pipe
->config
.capt_pp_in_res
.width
)) {
8999 enum ia_css_frame_format format
;
9000 if (internal_pipe
->config
.vf_pp_in_res
.width
) {
9001 format
= IA_CSS_FRAME_FORMAT_YUV_LINE
;
9002 ia_css_frame_info_init(
9003 &internal_pipe
->vf_yuv_ds_input_info
,
9004 internal_pipe
->config
.vf_pp_in_res
.width
,
9005 internal_pipe
->config
.vf_pp_in_res
.height
,
9008 if (internal_pipe
->config
.capt_pp_in_res
.width
) {
9009 format
= IA_CSS_FRAME_FORMAT_YUV420
;
9010 ia_css_frame_info_init(
9011 &internal_pipe
->out_yuv_ds_input_info
,
9012 internal_pipe
->config
.capt_pp_in_res
.width
,
9013 internal_pipe
->config
.capt_pp_in_res
.height
,
9017 if (internal_pipe
->config
.vf_pp_in_res
.width
&&
9018 internal_pipe
->config
.mode
== IA_CSS_PIPE_MODE_PREVIEW
) {
9019 ia_css_frame_info_init(
9020 &internal_pipe
->vf_yuv_ds_input_info
,
9021 internal_pipe
->config
.vf_pp_in_res
.width
,
9022 internal_pipe
->config
.vf_pp_in_res
.height
,
9023 IA_CSS_FRAME_FORMAT_YUV_LINE
, 0);
9025 /* handle bayer downscaling output info */
9026 if (internal_pipe
->config
.bayer_ds_out_res
.width
) {
9027 ia_css_frame_info_init(
9028 &internal_pipe
->bds_output_info
,
9029 internal_pipe
->config
.bayer_ds_out_res
.width
,
9030 internal_pipe
->config
.bayer_ds_out_res
.height
,
9031 IA_CSS_FRAME_FORMAT_RAW
, 0);
9034 /* handle output info, assume always needed */
9035 for (i
= 0; i
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; i
++) {
9036 if (internal_pipe
->config
.output_info
[i
].res
.width
) {
9037 err
= sh_css_pipe_configure_output(
9039 internal_pipe
->config
.output_info
[i
].res
.width
,
9040 internal_pipe
->config
.output_info
[i
].res
.height
,
9041 internal_pipe
->config
.output_info
[i
].padded_width
,
9042 internal_pipe
->config
.output_info
[i
].format
,
9044 if (err
!= IA_CSS_SUCCESS
) {
9045 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9046 sh_css_free(internal_pipe
);
9047 internal_pipe
= NULL
;
9052 /* handle vf output info, when configured */
9053 internal_pipe
->enable_viewfinder
[i
] = (internal_pipe
->config
.vf_output_info
[i
].res
.width
!= 0);
9054 if (internal_pipe
->config
.vf_output_info
[i
].res
.width
) {
9055 err
= sh_css_pipe_configure_viewfinder(
9057 internal_pipe
->config
.vf_output_info
[i
].res
.width
,
9058 internal_pipe
->config
.vf_output_info
[i
].res
.height
,
9059 internal_pipe
->config
.vf_output_info
[i
].padded_width
,
9060 internal_pipe
->config
.vf_output_info
[i
].format
,
9062 if (err
!= IA_CSS_SUCCESS
) {
9063 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9064 sh_css_free(internal_pipe
);
9065 internal_pipe
= NULL
;
9070 if (internal_pipe
->config
.acc_extension
) {
9071 err
= ia_css_pipe_load_extension(internal_pipe
,
9072 internal_pipe
->config
.acc_extension
);
9073 if (err
!= IA_CSS_SUCCESS
) {
9074 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9075 sh_css_free(internal_pipe
);
9079 /* set all info to zeroes first */
9080 memset(&internal_pipe
->info
, 0, sizeof(internal_pipe
->info
));
9082 /* all went well, return the pipe */
9083 *pipe
= internal_pipe
;
9084 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
9085 return IA_CSS_SUCCESS
;
9090 ia_css_pipe_get_info(const struct ia_css_pipe
*pipe
,
9091 struct ia_css_pipe_info
*pipe_info
)
9093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
9094 "ia_css_pipe_get_info()\n");
9095 assert(pipe_info
!= NULL
);
9096 if (pipe_info
== NULL
) {
9097 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR
,
9098 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9099 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9101 if (pipe
== NULL
|| pipe
->stream
== NULL
) {
9102 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR
,
9103 "ia_css_pipe_get_info: ia_css_stream_create needs to"
9104 " be called before ia_css_[stream/pipe]_get_info\n");
9105 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9107 /* we succeeded return the info */
9108 *pipe_info
= pipe
->info
;
9109 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_pipe_get_info() leave\n");
9110 return IA_CSS_SUCCESS
;
9113 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info
*pipe_info
)
9117 if (pipe_info
!= NULL
) {
9118 for (i
= 0; i
< IA_CSS_DVS_STAT_NUM_OF_LEVELS
; i
++) {
9119 if (pipe_info
->grid_info
.dvs_grid
.dvs_stat_grid_info
.grd_cfg
[i
].grd_start
.enable
)
9129 ia_css_pipe_override_frame_format(struct ia_css_pipe
*pipe
,
9131 enum ia_css_frame_format new_format
)
9133 enum ia_css_err err
= IA_CSS_SUCCESS
;
9135 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe
, pin_index
, new_format
);
9138 IA_CSS_ERROR("pipe is not set");
9139 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9140 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9143 if (0 != pin_index
&& 1 != pin_index
) {
9144 IA_CSS_ERROR("pin index is not valid");
9145 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9146 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9149 if (IA_CSS_FRAME_FORMAT_NV12_TILEY
!= new_format
) {
9150 IA_CSS_ERROR("new format is not valid");
9151 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9152 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9155 err
= ia_css_pipe_check_format(pipe
, new_format
);
9156 if (IA_CSS_SUCCESS
== err
) {
9157 if (pin_index
== 0) {
9158 pipe
->output_info
[0].format
= new_format
;
9160 pipe
->vf_output_info
[0].format
= new_format
;
9164 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9169 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9170 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9171 static enum ia_css_err
9172 ia_css_stream_configure_rx(struct ia_css_stream
*stream
)
9174 struct ia_css_input_port
*config
;
9175 assert(stream
!= NULL
);
9177 config
= &stream
->config
.source
.port
;
9178 /* AM: this code is not reliable, especially for 2400 */
9179 if (config
->num_lanes
== 1)
9180 stream
->csi_rx_config
.mode
= MONO_1L_1L_0L
;
9181 else if (config
->num_lanes
== 2)
9182 stream
->csi_rx_config
.mode
= MONO_2L_1L_0L
;
9183 else if (config
->num_lanes
== 3)
9184 stream
->csi_rx_config
.mode
= MONO_3L_1L_0L
;
9185 else if (config
->num_lanes
== 4)
9186 stream
->csi_rx_config
.mode
= MONO_4L_1L_0L
;
9187 else if (config
->num_lanes
!= 0)
9188 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9190 if (config
->port
> IA_CSS_CSI2_PORT2
)
9191 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9192 stream
->csi_rx_config
.port
=
9193 ia_css_isys_port_to_mipi_port(config
->port
);
9194 stream
->csi_rx_config
.timeout
= config
->timeout
;
9195 stream
->csi_rx_config
.initcount
= 0;
9196 stream
->csi_rx_config
.synccount
= 0x28282828;
9197 stream
->csi_rx_config
.rxcount
= config
->rxcount
;
9198 if (config
->compression
.type
== IA_CSS_CSI2_COMPRESSION_TYPE_NONE
)
9199 stream
->csi_rx_config
.comp
= MIPI_PREDICTOR_NONE
;
9201 /* not implemented yet, requires extension of the rx_cfg_t
9203 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9205 stream
->csi_rx_config
.is_two_ppc
= (stream
->config
.pixels_per_clock
== 2);
9206 stream
->reconfigure_css_rx
= true;
9207 return IA_CSS_SUCCESS
;
9211 static struct ia_css_pipe
*
9212 find_pipe(struct ia_css_pipe
*pipes
[],
9213 unsigned int num_pipes
,
9214 enum ia_css_pipe_mode mode
,
9218 assert(pipes
!= NULL
);
9219 for (i
= 0; i
< num_pipes
; i
++) {
9220 assert(pipes
[i
] != NULL
);
9221 if (pipes
[i
]->config
.mode
!= mode
)
9223 if (copy_pipe
&& pipes
[i
]->mode
!= IA_CSS_PIPE_ID_COPY
)
9230 static enum ia_css_err
9231 ia_css_acc_stream_create(struct ia_css_stream
*stream
)
9234 enum ia_css_err err
= IA_CSS_SUCCESS
;
9236 assert(stream
!= NULL
);
9237 IA_CSS_ENTER_PRIVATE("stream = %p", stream
);
9239 if (stream
== NULL
) {
9240 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
9241 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9244 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9245 struct ia_css_pipe
*pipe
= stream
->pipes
[i
];
9246 assert(pipe
!= NULL
);
9248 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS
);
9249 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9252 pipe
->stream
= stream
;
9255 /* Map SP threads before doing anything. */
9256 err
= map_sp_threads(stream
, true);
9257 if (err
!= IA_CSS_SUCCESS
) {
9258 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9262 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9263 struct ia_css_pipe
*pipe
= stream
->pipes
[i
];
9264 assert(pipe
!= NULL
);
9265 ia_css_pipe_map_queue(pipe
, true);
9268 err
= create_host_pipeline_structure(stream
);
9269 if (err
!= IA_CSS_SUCCESS
) {
9270 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9274 stream
->started
= false;
9277 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS
);
9279 return IA_CSS_SUCCESS
;
9282 static enum ia_css_err
9283 metadata_info_init(const struct ia_css_metadata_config
*mdc
,
9284 struct ia_css_metadata_info
*md
)
9286 /* Either both width and height should be set or neither */
9287 if ((mdc
->resolution
.height
> 0) ^ (mdc
->resolution
.width
> 0))
9288 return IA_CSS_ERR_INVALID_ARGUMENTS
;
9290 md
->resolution
= mdc
->resolution
;
9291 /* We round up the stride to a multiple of the width
9292 * of the port going to DDR, this is a HW requirements (DMA). */
9293 md
->stride
= CEIL_MUL(mdc
->resolution
.width
, HIVE_ISP_DDR_WORD_BYTES
);
9294 md
->size
= mdc
->resolution
.height
* md
->stride
;
9295 return IA_CSS_SUCCESS
;
9299 static enum ia_css_err
check_pipe_resolutions(const struct ia_css_pipe
*pipe
)
9301 enum ia_css_err err
= IA_CSS_SUCCESS
;
9303 IA_CSS_ENTER_PRIVATE("");
9305 if (!pipe
|| !pipe
->stream
) {
9306 IA_CSS_ERROR("null arguments");
9307 err
= IA_CSS_ERR_INTERNAL_ERROR
;
9311 if (ia_css_util_check_res(pipe
->config
.input_effective_res
.width
,
9312 pipe
->config
.input_effective_res
.height
) != IA_CSS_SUCCESS
) {
9313 IA_CSS_ERROR("effective resolution not supported");
9314 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9317 if (!ia_css_util_resolution_is_zero(pipe
->stream
->config
.input_config
.input_res
)) {
9318 if (!ia_css_util_res_leq(pipe
->config
.input_effective_res
,
9319 pipe
->stream
->config
.input_config
.input_res
)) {
9320 IA_CSS_ERROR("effective resolution is larger than input resolution");
9321 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9325 if (!ia_css_util_resolution_is_even(pipe
->config
.output_info
[0].res
)) {
9326 IA_CSS_ERROR("output resolution must be even");
9327 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9330 if (!ia_css_util_resolution_is_even(pipe
->config
.vf_output_info
[0].res
)) {
9331 IA_CSS_ERROR("VF resolution must be even");
9332 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9336 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9343 ia_css_stream_create(const struct ia_css_stream_config
*stream_config
,
9345 struct ia_css_pipe
*pipes
[],
9346 struct ia_css_stream
**stream
)
9348 struct ia_css_pipe
*curr_pipe
;
9349 struct ia_css_stream
*curr_stream
= NULL
;
9351 bool sensor_binning_changed
;
9353 enum ia_css_err err
= IA_CSS_ERR_INTERNAL_ERROR
;
9354 struct ia_css_metadata_info md_info
;
9356 struct ia_css_resolution effective_res
;
9358 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9359 bool aspect_ratio_crop_enabled
= false;
9363 IA_CSS_ENTER("num_pipes=%d", num_pipes
);
9364 ia_css_debug_dump_stream_config(stream_config
, num_pipes
);
9367 if (num_pipes
== 0 ||
9370 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9371 IA_CSS_LEAVE_ERR(err
);
9375 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9376 /* We don't support metadata for JPEG stream, since they both use str2mem */
9377 if (stream_config
->input_config
.format
== IA_CSS_STREAM_FORMAT_BINARY_8
&&
9378 stream_config
->metadata_config
.resolution
.height
> 0) {
9379 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9380 IA_CSS_LEAVE_ERR(err
);
9385 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9386 if (stream_config
->online
&& stream_config
->pack_raw_pixels
) {
9387 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9388 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9389 IA_CSS_LEAVE_ERR(err
);
9394 #if !defined(HAS_NO_INPUT_SYSTEM)
9395 ia_css_debug_pipe_graph_dump_stream_config(stream_config
);
9397 /* check if mipi size specified */
9398 if (stream_config
->mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
)
9399 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9400 if (!stream_config
->online
)
9403 unsigned int port
= (unsigned int) stream_config
->source
.port
.port
;
9404 if (port
>= N_MIPI_PORT_ID
) {
9405 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9406 IA_CSS_LEAVE_ERR(err
);
9410 if (my_css
.size_mem_words
!= 0){
9411 my_css
.mipi_frame_size
[port
] = my_css
.size_mem_words
;
9412 } else if (stream_config
->mipi_buffer_config
.size_mem_words
!= 0) {
9413 my_css
.mipi_frame_size
[port
] = stream_config
->mipi_buffer_config
.size_mem_words
;
9415 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
9416 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9417 assert(stream_config
->mipi_buffer_config
.size_mem_words
!= 0);
9418 err
= IA_CSS_ERR_INTERNAL_ERROR
;
9419 IA_CSS_LEAVE_ERR(err
);
9423 if (my_css
.size_mem_words
!= 0) {
9424 my_css
.num_mipi_frames
[port
] = 2; /* Temp change: Default for backwards compatibility. */
9425 } else if (stream_config
->mipi_buffer_config
.nof_mipi_buffers
!= 0) {
9426 my_css
.num_mipi_frames
[port
] = stream_config
->mipi_buffer_config
.nof_mipi_buffers
;
9428 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
,
9429 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9430 assert(stream_config
->mipi_buffer_config
.nof_mipi_buffers
!= 0);
9431 err
= IA_CSS_ERR_INTERNAL_ERROR
;
9432 IA_CSS_LEAVE_ERR(err
);
9439 /* Currently we only supported metadata up to a certain size. */
9440 err
= metadata_info_init(&stream_config
->metadata_config
, &md_info
);
9441 if (err
!= IA_CSS_SUCCESS
) {
9442 IA_CSS_LEAVE_ERR(err
);
9446 /* allocate the stream instance */
9447 curr_stream
= kmalloc(sizeof(struct ia_css_stream
), GFP_KERNEL
);
9449 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
9450 IA_CSS_LEAVE_ERR(err
);
9453 /* default all to 0 */
9454 memset(curr_stream
, 0, sizeof(struct ia_css_stream
));
9455 curr_stream
->info
.metadata_info
= md_info
;
9457 /* allocate pipes */
9458 curr_stream
->num_pipes
= num_pipes
;
9459 curr_stream
->pipes
= kzalloc(num_pipes
* sizeof(struct ia_css_pipe
*), GFP_KERNEL
);
9460 if (!curr_stream
->pipes
) {
9461 curr_stream
->num_pipes
= 0;
9464 err
= IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY
;
9465 IA_CSS_LEAVE_ERR(err
);
9469 spcopyonly
= (num_pipes
== 1) && (pipes
[0]->config
.mode
== IA_CSS_PIPE_MODE_COPY
);
9470 for (i
= 0; i
< num_pipes
; i
++)
9471 curr_stream
->pipes
[i
] = pipes
[i
];
9472 curr_stream
->last_pipe
= curr_stream
->pipes
[0];
9473 /* take over stream config */
9474 curr_stream
->config
= *stream_config
;
9476 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9477 if (stream_config
->mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
&&
9478 stream_config
->online
)
9479 curr_stream
->config
.online
= false;
9482 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9483 if (curr_stream
->config
.online
) {
9484 curr_stream
->config
.source
.port
.num_lanes
= stream_config
->source
.port
.num_lanes
;
9485 curr_stream
->config
.mode
= IA_CSS_INPUT_MODE_BUFFERED_SENSOR
;
9488 /* in case driver doesn't configure init number of raw buffers, configure it here */
9489 if (curr_stream
->config
.target_num_cont_raw_buf
== 0)
9490 curr_stream
->config
.target_num_cont_raw_buf
= NUM_CONTINUOUS_FRAMES
;
9491 if (curr_stream
->config
.init_num_cont_raw_buf
== 0)
9492 curr_stream
->config
.init_num_cont_raw_buf
= curr_stream
->config
.target_num_cont_raw_buf
;
9494 /* Enable locking & unlocking of buffers in RAW buffer pool */
9495 if (curr_stream
->config
.ia_css_enable_raw_buffer_locking
)
9496 sh_css_sp_configure_enable_raw_pool_locking(
9497 curr_stream
->config
.lock_all
);
9499 /* copy mode specific stuff */
9500 switch (curr_stream
->config
.mode
) {
9501 case IA_CSS_INPUT_MODE_SENSOR
:
9502 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR
:
9503 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9504 ia_css_stream_configure_rx(curr_stream
);
9507 case IA_CSS_INPUT_MODE_TPG
:
9508 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9509 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9510 curr_stream
->config
.source
.tpg
.x_mask
,
9511 curr_stream
->config
.source
.tpg
.y_mask
,
9512 curr_stream
->config
.source
.tpg
.x_delta
,
9513 curr_stream
->config
.source
.tpg
.y_delta
,
9514 curr_stream
->config
.source
.tpg
.xy_mask
);
9516 sh_css_sp_configure_tpg(
9517 curr_stream
->config
.source
.tpg
.x_mask
,
9518 curr_stream
->config
.source
.tpg
.y_mask
,
9519 curr_stream
->config
.source
.tpg
.x_delta
,
9520 curr_stream
->config
.source
.tpg
.y_delta
,
9521 curr_stream
->config
.source
.tpg
.xy_mask
);
9524 case IA_CSS_INPUT_MODE_PRBS
:
9525 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9526 IA_CSS_LOG("mode prbs");
9527 sh_css_sp_configure_prbs(curr_stream
->config
.source
.prbs
.seed
);
9530 case IA_CSS_INPUT_MODE_MEMORY
:
9531 IA_CSS_LOG("mode memory");
9532 curr_stream
->reconfigure_css_rx
= false;
9535 IA_CSS_LOG("mode sensor/default");
9539 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9540 err
= aspect_ratio_crop_init(curr_stream
,
9542 &aspect_ratio_crop_enabled
);
9543 if (err
!= IA_CSS_SUCCESS
) {
9544 IA_CSS_LEAVE_ERR(err
);
9550 for (i
= 0; i
< num_pipes
; i
++) {
9552 struct ia_css_resolution effective_res
;
9554 curr_pipe
= pipes
[i
];
9555 /* set current stream */
9556 curr_pipe
->stream
= curr_stream
;
9557 /* take over effective info */
9559 effective_res
= curr_pipe
->config
.input_effective_res
;
9560 if (effective_res
.height
== 0 || effective_res
.width
== 0) {
9561 effective_res
= curr_pipe
->stream
->config
.input_config
.effective_res
;
9564 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9565 /* The aspect ratio cropping is currently only
9566 * supported on the new input system. */
9567 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled
, curr_pipe
)) {
9569 struct ia_css_resolution crop_res
;
9571 err
= aspect_ratio_crop(curr_pipe
, &crop_res
);
9572 if (err
== IA_CSS_SUCCESS
) {
9573 effective_res
= crop_res
;
9575 /* in case of error fallback to default
9576 * effective resolution from driver. */
9577 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err
);
9582 curr_pipe
->config
.input_effective_res
= effective_res
;
9584 IA_CSS_LOG("effective_res=%dx%d",
9585 effective_res
.width
,
9586 effective_res
.height
);
9590 for (i
= 0; i
< num_pipes
; i
++) {
9591 if (pipes
[i
]->config
.mode
!= IA_CSS_PIPE_MODE_ACC
&&
9592 pipes
[i
]->config
.mode
!= IA_CSS_PIPE_MODE_COPY
) {
9593 err
= check_pipe_resolutions(pipes
[i
]);
9594 if (err
!= IA_CSS_SUCCESS
) {
9601 err
= ia_css_stream_isp_parameters_init(curr_stream
);
9602 if (err
!= IA_CSS_SUCCESS
)
9604 IA_CSS_LOG("isp_params_configs: %p", curr_stream
->isp_params_configs
);
9606 if (num_pipes
== 1 && pipes
[0]->config
.mode
== IA_CSS_PIPE_MODE_ACC
) {
9607 *stream
= curr_stream
;
9608 err
= ia_css_acc_stream_create(curr_stream
);
9611 /* sensor binning */
9613 sensor_binning_changed
=
9614 sh_css_params_set_binning_factor(curr_stream
, curr_stream
->config
.sensor_binning_factor
);
9616 sensor_binning_changed
= false;
9619 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9620 curr_stream
->config
.sensor_binning_factor
, sensor_binning_changed
);
9621 /* loop over pipes */
9622 IA_CSS_LOG("num_pipes=%d", num_pipes
);
9623 curr_stream
->cont_capt
= false;
9624 /* Temporary hack: we give the preview pipe a reference to the capture
9625 * pipe in continuous capture mode. */
9626 if (curr_stream
->config
.continuous
) {
9627 /* Search for the preview pipe and create the copy pipe */
9628 struct ia_css_pipe
*preview_pipe
;
9629 struct ia_css_pipe
*video_pipe
;
9630 struct ia_css_pipe
*acc_pipe
;
9631 struct ia_css_pipe
*capture_pipe
= NULL
;
9632 struct ia_css_pipe
*copy_pipe
= NULL
;
9634 if (num_pipes
>= 2) {
9635 curr_stream
->cont_capt
= true;
9636 curr_stream
->disable_cont_vf
= curr_stream
->config
.disable_cont_viewfinder
;
9638 curr_stream
->stop_copy_preview
= my_css
.stop_copy_preview
;
9642 /* Create copy pipe here, since it may not be exposed to the driver */
9643 preview_pipe
= find_pipe(pipes
, num_pipes
,
9644 IA_CSS_PIPE_MODE_PREVIEW
, false);
9645 video_pipe
= find_pipe(pipes
, num_pipes
,
9646 IA_CSS_PIPE_MODE_VIDEO
, false);
9647 acc_pipe
= find_pipe(pipes
, num_pipes
,
9648 IA_CSS_PIPE_MODE_ACC
, false);
9649 if (acc_pipe
&& num_pipes
== 2 && curr_stream
->cont_capt
== true)
9650 curr_stream
->cont_capt
= false; /* preview + QoS case will not need cont_capt switch */
9651 if (curr_stream
->cont_capt
== true) {
9652 capture_pipe
= find_pipe(pipes
, num_pipes
,
9653 IA_CSS_PIPE_MODE_CAPTURE
, false);
9654 if (capture_pipe
== NULL
) {
9655 err
= IA_CSS_ERR_INTERNAL_ERROR
;
9659 /* We do not support preview and video pipe at the same time */
9660 if (preview_pipe
&& video_pipe
) {
9661 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9665 if (preview_pipe
&& !preview_pipe
->pipe_settings
.preview
.copy_pipe
) {
9666 err
= create_pipe(IA_CSS_PIPE_MODE_CAPTURE
, ©_pipe
, true);
9667 if (err
!= IA_CSS_SUCCESS
)
9669 ia_css_pipe_config_defaults(©_pipe
->config
);
9670 preview_pipe
->pipe_settings
.preview
.copy_pipe
= copy_pipe
;
9671 copy_pipe
->stream
= curr_stream
;
9673 if (preview_pipe
&& (curr_stream
->cont_capt
== true)) {
9674 preview_pipe
->pipe_settings
.preview
.capture_pipe
= capture_pipe
;
9676 if (video_pipe
&& !video_pipe
->pipe_settings
.video
.copy_pipe
) {
9677 err
= create_pipe(IA_CSS_PIPE_MODE_CAPTURE
, ©_pipe
, true);
9678 if (err
!= IA_CSS_SUCCESS
)
9680 ia_css_pipe_config_defaults(©_pipe
->config
);
9681 video_pipe
->pipe_settings
.video
.copy_pipe
= copy_pipe
;
9682 copy_pipe
->stream
= curr_stream
;
9684 if (video_pipe
&& (curr_stream
->cont_capt
== true)) {
9685 video_pipe
->pipe_settings
.video
.capture_pipe
= capture_pipe
;
9687 if (preview_pipe
&& acc_pipe
) {
9688 preview_pipe
->pipe_settings
.preview
.acc_pipe
= acc_pipe
;
9691 for (i
= 0; i
< num_pipes
; i
++) {
9692 curr_pipe
= pipes
[i
];
9693 /* set current stream */
9694 curr_pipe
->stream
= curr_stream
;
9696 /* take over effective info */
9698 effective_res
= curr_pipe
->config
.input_effective_res
;
9699 err
= ia_css_util_check_res(
9700 effective_res
.width
,
9701 effective_res
.height
);
9702 if (err
!= IA_CSS_SUCCESS
)
9705 /* sensor binning per pipe */
9706 if (sensor_binning_changed
)
9707 sh_css_pipe_free_shading_table(curr_pipe
);
9710 /* now pipes have been configured, info should be available */
9711 for (i
= 0; i
< num_pipes
; i
++) {
9712 struct ia_css_pipe_info
*pipe_info
= NULL
;
9713 curr_pipe
= pipes
[i
];
9715 err
= sh_css_pipe_load_binaries(curr_pipe
);
9716 if (err
!= IA_CSS_SUCCESS
)
9719 /* handle each pipe */
9720 pipe_info
= &curr_pipe
->info
;
9721 for (j
= 0; j
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; j
++) {
9722 err
= sh_css_pipe_get_output_frame_info(curr_pipe
,
9723 &pipe_info
->output_info
[j
], j
);
9724 if (err
!= IA_CSS_SUCCESS
)
9728 pipe_info
->output_system_in_res_info
= curr_pipe
->config
.output_system_in_res
;
9731 err
= sh_css_pipe_get_shading_info(curr_pipe
,
9733 &pipe_info
->shading_info
);
9735 &pipe_info
->shading_info
, &curr_pipe
->config
);
9737 if (err
!= IA_CSS_SUCCESS
)
9739 err
= sh_css_pipe_get_grid_info(curr_pipe
,
9740 &pipe_info
->grid_info
);
9741 if (err
!= IA_CSS_SUCCESS
)
9743 for (j
= 0; j
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; j
++) {
9744 sh_css_pipe_get_viewfinder_frame_info(curr_pipe
,
9745 &pipe_info
->vf_output_info
[j
], j
);
9746 if (err
!= IA_CSS_SUCCESS
)
9751 my_css
.active_pipes
[ia_css_pipe_get_pipe_num(curr_pipe
)] = curr_pipe
;
9754 curr_stream
->started
= false;
9756 /* Map SP threads before doing anything. */
9757 err
= map_sp_threads(curr_stream
, true);
9758 if (err
!= IA_CSS_SUCCESS
) {
9759 IA_CSS_LOG("map_sp_threads: return_err=%d", err
);
9763 for (i
= 0; i
< num_pipes
; i
++) {
9764 curr_pipe
= pipes
[i
];
9765 ia_css_pipe_map_queue(curr_pipe
, true);
9768 /* Create host side pipeline objects without stages */
9769 err
= create_host_pipeline_structure(curr_stream
);
9770 if (err
!= IA_CSS_SUCCESS
) {
9771 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err
);
9775 /* assign curr_stream */
9776 *stream
= curr_stream
;
9780 if (err
== IA_CSS_SUCCESS
)
9782 /* working mode: enter into the seed list */
9783 if (my_css_save
.mode
== sh_css_mode_working
) {
9784 for (i
= 0; i
< MAX_ACTIVE_STREAMS
; i
++)
9785 if (!my_css_save
.stream_seeds
[i
].stream
) {
9786 IA_CSS_LOG("entered stream into loc=%d", i
);
9787 my_css_save
.stream_seeds
[i
].orig_stream
= stream
;
9788 my_css_save
.stream_seeds
[i
].stream
= curr_stream
;
9789 my_css_save
.stream_seeds
[i
].num_pipes
= num_pipes
;
9790 my_css_save
.stream_seeds
[i
].stream_config
= *stream_config
;
9791 for (j
= 0; j
< num_pipes
; j
++) {
9792 my_css_save
.stream_seeds
[i
].pipe_config
[j
] = pipes
[j
]->config
;
9793 my_css_save
.stream_seeds
[i
].pipes
[j
] = pipes
[j
];
9794 my_css_save
.stream_seeds
[i
].orig_pipes
[j
] = &pipes
[j
];
9800 if (err
== IA_CSS_SUCCESS
) {
9801 err
= ia_css_save_stream(curr_stream
);
9804 ia_css_stream_destroy(curr_stream
);
9807 IA_CSS_LEAVE("return_err=%d mode=%d", err
, my_css_save
.mode
);
9809 IA_CSS_LEAVE("return_err=%d", err
);
9815 ia_css_stream_destroy(struct ia_css_stream
*stream
)
9818 enum ia_css_err err
= IA_CSS_SUCCESS
;
9820 enum ia_css_err err1
= IA_CSS_SUCCESS
;
9821 enum ia_css_err err2
= IA_CSS_SUCCESS
;
9824 IA_CSS_ENTER_PRIVATE("stream = %p", stream
);
9825 if (stream
== NULL
) {
9826 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
9827 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9831 ia_css_stream_isp_parameters_uninit(stream
);
9833 if ((stream
->last_pipe
!= NULL
) &&
9834 ia_css_pipeline_is_mapped(stream
->last_pipe
->pipe_num
)) {
9835 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9836 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9837 struct ia_css_pipe
*entry
= stream
->pipes
[i
];
9838 unsigned int sp_thread_id
;
9839 struct sh_css_sp_pipeline_terminal
*sp_pipeline_input_terminal
;
9841 assert(entry
!= NULL
);
9842 if (entry
!= NULL
) {
9843 /* get the SP thread id */
9844 if (ia_css_pipeline_get_sp_thread_id(
9845 ia_css_pipe_get_pipe_num(entry
), &sp_thread_id
) != true)
9846 return IA_CSS_ERR_INTERNAL_ERROR
;
9847 /* get the target input terminal */
9848 sp_pipeline_input_terminal
=
9849 &(sh_css_sp_group
.pipe_io
[sp_thread_id
].input
);
9851 for (i
= 0; i
< IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH
; i
++) {
9852 ia_css_isys_stream_h isys_stream
=
9853 &(sp_pipeline_input_terminal
->context
.virtual_input_system_stream
[i
]);
9854 if (stream
->config
.isys_config
[i
].valid
&& isys_stream
->valid
)
9855 ia_css_isys_stream_destroy(isys_stream
);
9860 if (stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
) {
9862 if (stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
||
9863 stream
->config
.mode
== IA_CSS_INPUT_MODE_TPG
||
9864 stream
->config
.mode
== IA_CSS_INPUT_MODE_PRBS
) {
9866 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9867 struct ia_css_pipe
*entry
= stream
->pipes
[i
];
9868 /* free any mipi frames that are remaining:
9869 * some test stream create-destroy cycles do not generate output frames
9870 * and the mipi buffer is not freed in the deque function
9873 free_mipi_frames(entry
);
9876 stream_unregister_with_csi_rx(stream
);
9879 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9880 struct ia_css_pipe
*curr_pipe
= stream
->pipes
[i
];
9881 assert(curr_pipe
!= NULL
);
9882 ia_css_pipe_map_queue(curr_pipe
, false);
9885 err
= map_sp_threads(stream
, false);
9886 if (err
!= IA_CSS_SUCCESS
) {
9887 IA_CSS_LEAVE_ERR_PRIVATE(err
);
9892 /* remove references from pipes to stream */
9893 for (i
= 0; i
< stream
->num_pipes
; i
++) {
9894 struct ia_css_pipe
*entry
= stream
->pipes
[i
];
9895 assert(entry
!= NULL
);
9896 if (entry
!= NULL
) {
9897 /* clear reference to stream */
9898 entry
->stream
= NULL
;
9899 /* check internal copy pipe */
9900 if (entry
->mode
== IA_CSS_PIPE_ID_PREVIEW
&&
9901 entry
->pipe_settings
.preview
.copy_pipe
) {
9902 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9903 entry
->pipe_settings
.preview
.copy_pipe
->stream
= NULL
;
9905 if (entry
->mode
== IA_CSS_PIPE_ID_VIDEO
&&
9906 entry
->pipe_settings
.video
.copy_pipe
) {
9907 IA_CSS_LOG("clearing stream on internal video copy pipe");
9908 entry
->pipe_settings
.video
.copy_pipe
->stream
= NULL
;
9910 err
= sh_css_pipe_unload_binaries(entry
);
9913 /* free associated memory of stream struct */
9914 kfree(stream
->pipes
);
9915 stream
->pipes
= NULL
;
9916 stream
->num_pipes
= 0;
9918 /* working mode: take out of the seed list */
9919 if (my_css_save
.mode
== sh_css_mode_working
)
9920 for(i
=0;i
<MAX_ACTIVE_STREAMS
;i
++)
9921 if (my_css_save
.stream_seeds
[i
].stream
== stream
)
9923 IA_CSS_LOG("took out stream %d", i
);
9924 my_css_save
.stream_seeds
[i
].stream
= NULL
;
9928 err2
= ia_css_save_restore_remove_stream(stream
);
9930 err1
= (err
!= IA_CSS_SUCCESS
) ? err
: err2
;
9934 IA_CSS_LEAVE_ERR(err
);
9936 IA_CSS_LEAVE_ERR(err1
);
9947 ia_css_stream_get_info(const struct ia_css_stream
*stream
,
9948 struct ia_css_stream_info
*stream_info
)
9950 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_get_info: enter/exit\n");
9951 assert(stream
!= NULL
);
9952 assert(stream_info
!= NULL
);
9954 *stream_info
= stream
->info
;
9955 return IA_CSS_SUCCESS
;
9959 * Rebuild a stream, including allocating structs, setting configuration and
9960 * building the required pipes.
9961 * The data is taken from the css_save struct updated upon stream creation.
9962 * The stream handle is used to identify the correct entry in the css_save struct
9965 ia_css_stream_load(struct ia_css_stream
*stream
)
9969 enum ia_css_err err
;
9970 assert(stream
!= NULL
);
9971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_load() enter, \n");
9972 for (i
= 0; i
< MAX_ACTIVE_STREAMS
; i
++) {
9973 if (my_css_save
.stream_seeds
[i
].stream
== stream
) {
9975 for ( j
= 0; j
< my_css_save
.stream_seeds
[i
].num_pipes
; j
++) {
9976 if ((err
= ia_css_pipe_create(&(my_css_save
.stream_seeds
[i
].pipe_config
[j
]), &my_css_save
.stream_seeds
[i
].pipes
[j
])) != IA_CSS_SUCCESS
) {
9980 ia_css_pipe_destroy(my_css_save
.stream_seeds
[i
].pipes
[k
]);
9985 err
= ia_css_stream_create(&(my_css_save
.stream_seeds
[i
].stream_config
),
9986 my_css_save
.stream_seeds
[i
].num_pipes
,
9987 my_css_save
.stream_seeds
[i
].pipes
,
9988 &(my_css_save
.stream_seeds
[i
].stream
));
9989 if (err
!= IA_CSS_SUCCESS
) {
9990 ia_css_stream_destroy(stream
);
9991 for (j
= 0; j
< my_css_save
.stream_seeds
[i
].num_pipes
; j
++)
9992 ia_css_pipe_destroy(my_css_save
.stream_seeds
[i
].pipes
[j
]);
9998 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_load() exit, \n");
9999 return IA_CSS_SUCCESS
;
10001 /* TODO remove function - DEPRECATED */
10003 return IA_CSS_ERR_NOT_SUPPORTED
;
10008 ia_css_stream_start(struct ia_css_stream
*stream
)
10010 enum ia_css_err err
= IA_CSS_SUCCESS
;
10011 IA_CSS_ENTER("stream = %p", stream
);
10012 if ((stream
== NULL
) || (stream
->last_pipe
== NULL
)) {
10013 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS
);
10014 return IA_CSS_ERR_INVALID_ARGUMENTS
;
10016 IA_CSS_LOG("starting %d", stream
->last_pipe
->mode
);
10018 sh_css_sp_set_disable_continuous_viewfinder(stream
->disable_cont_vf
);
10020 /* Create host side pipeline. */
10021 err
= create_host_pipeline(stream
);
10022 if (err
!= IA_CSS_SUCCESS
) {
10023 IA_CSS_LEAVE_ERR(err
);
10027 #if !defined(HAS_NO_INPUT_SYSTEM)
10028 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10029 if((stream
->config
.mode
== IA_CSS_INPUT_MODE_SENSOR
) ||
10030 (stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
))
10031 stream_register_with_csi_rx(stream
);
10035 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10036 /* Initialize mipi size checks */
10037 if (stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
)
10040 unsigned int port
= (unsigned int) (stream
->config
.source
.port
.port
) ;
10042 for (idx
= 0; idx
< IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT
; idx
++) {
10043 sh_css_sp_group
.config
.mipi_sizes_for_check
[port
][idx
] = sh_css_get_mipi_sizes_for_check(port
, idx
);
10048 #if !defined(HAS_NO_INPUT_SYSTEM)
10049 if (stream
->config
.mode
!= IA_CSS_INPUT_MODE_MEMORY
) {
10050 err
= sh_css_config_input_network(stream
);
10051 if (err
!= IA_CSS_SUCCESS
)
10054 #endif /* !HAS_NO_INPUT_SYSTEM */
10056 err
= sh_css_pipe_start(stream
);
10057 IA_CSS_LEAVE_ERR(err
);
10062 ia_css_stream_stop(struct ia_css_stream
*stream
)
10064 enum ia_css_err err
= IA_CSS_SUCCESS
;
10066 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_stop() enter/exit\n");
10067 assert(stream
!= NULL
);
10068 assert(stream
->last_pipe
!= NULL
);
10069 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_stop: stopping %d\n",
10070 stream
->last_pipe
->mode
);
10072 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10073 /* De-initialize mipi size checks */
10074 if (stream
->config
.mode
== IA_CSS_INPUT_MODE_BUFFERED_SENSOR
)
10077 unsigned int port
= (unsigned int) (stream
->config
.source
.port
.port
) ;
10079 for (idx
= 0; idx
< IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT
; idx
++) {
10080 sh_css_sp_group
.config
.mipi_sizes_for_check
[port
][idx
] = 0;
10085 err
= ia_css_pipeline_request_stop(&stream
->last_pipe
->pipeline
);
10088 err
= sh_css_pipes_stop(stream
);
10090 if (err
!= IA_CSS_SUCCESS
)
10093 /* Ideally, unmapping should happen after pipeline_stop, but current
10094 * semantics do not allow that. */
10095 /* err = map_sp_threads(stream, false); */
10101 ia_css_stream_has_stopped(struct ia_css_stream
*stream
)
10104 assert(stream
!= NULL
);
10107 stopped
= ia_css_pipeline_has_stopped(&stream
->last_pipe
->pipeline
);
10109 stopped
= sh_css_pipes_have_stopped(stream
);
10117 * Destroy the stream and all the pipes related to it.
10118 * The stream handle is used to identify the correct entry in the css_save struct
10121 ia_css_stream_unload(struct ia_css_stream
*stream
)
10124 assert(stream
!= NULL
);
10125 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_unload() enter, \n");
10127 assert (stream
!= NULL
);
10128 for(i
=0;i
<MAX_ACTIVE_STREAMS
;i
++)
10129 if (my_css_save
.stream_seeds
[i
].stream
== stream
)
10132 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_unload(): unloading %d (%p)\n", i
, my_css_save
.stream_seeds
[i
].stream
);
10133 ia_css_stream_destroy(stream
);
10134 for(j
=0;j
<my_css_save
.stream_seeds
[i
].num_pipes
;j
++)
10135 ia_css_pipe_destroy(my_css_save
.stream_seeds
[i
].pipes
[j
]);
10136 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_unload(): after unloading %d (%p)\n", i
, my_css_save
.stream_seeds
[i
].stream
);
10139 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_stream_unload() exit, \n");
10140 return IA_CSS_SUCCESS
;
10145 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe
*pipe
, enum ia_css_pipe_id
*pipe_id
)
10147 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE
, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10149 *pipe_id
= pipe
->mode
;
10151 *pipe_id
= IA_CSS_PIPE_ID_COPY
;
10153 return IA_CSS_SUCCESS
;
10156 enum ia_css_stream_format
10157 ia_css_stream_get_format(const struct ia_css_stream
*stream
)
10159 return stream
->config
.input_config
.format
;
10163 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream
*stream
)
10165 return (stream
->config
.pixels_per_clock
== 2);
10168 struct ia_css_binary
*
10169 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
*stream
)
10171 struct ia_css_pipe
*pipe
;
10173 assert(stream
!= NULL
);
10175 pipe
= stream
->pipes
[0];
10177 if (stream
->num_pipes
== 2) {
10178 assert(stream
->pipes
[1] != NULL
);
10179 if (stream
->pipes
[1]->config
.mode
== IA_CSS_PIPE_MODE_VIDEO
||
10180 stream
->pipes
[1]->config
.mode
== IA_CSS_PIPE_MODE_PREVIEW
)
10181 pipe
= stream
->pipes
[1];
10184 return ia_css_pipe_get_shading_correction_binary(pipe
);
10187 struct ia_css_binary
*
10188 ia_css_stream_get_dvs_binary(const struct ia_css_stream
*stream
)
10191 struct ia_css_pipe
*video_pipe
= NULL
;
10193 /* First we find the video pipe */
10194 for (i
=0; i
<stream
->num_pipes
; i
++) {
10195 struct ia_css_pipe
*pipe
= stream
->pipes
[i
];
10196 if (pipe
->config
.mode
== IA_CSS_PIPE_MODE_VIDEO
) {
10202 return &video_pipe
->pipe_settings
.video
.video_binary
;
10206 struct ia_css_binary
*
10207 ia_css_stream_get_3a_binary(const struct ia_css_stream
*stream
)
10209 struct ia_css_pipe
*pipe
;
10210 struct ia_css_binary
*s3a_binary
= NULL
;
10212 assert(stream
!= NULL
);
10214 pipe
= stream
->pipes
[0];
10216 if (stream
->num_pipes
== 2) {
10217 assert(stream
->pipes
[1] != NULL
);
10218 if (stream
->pipes
[1]->config
.mode
== IA_CSS_PIPE_MODE_VIDEO
||
10219 stream
->pipes
[1]->config
.mode
== IA_CSS_PIPE_MODE_PREVIEW
)
10220 pipe
= stream
->pipes
[1];
10223 s3a_binary
= ia_css_pipe_get_s3a_binary(pipe
);
10230 ia_css_stream_set_output_padded_width(struct ia_css_stream
*stream
, unsigned int output_padded_width
)
10232 enum ia_css_err err
= IA_CSS_SUCCESS
;
10234 struct ia_css_pipe
*pipe
;
10236 assert(stream
!= NULL
);
10238 pipe
= stream
->last_pipe
;
10240 assert(pipe
!= NULL
);
10242 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10243 pipe
->config
.output_info
[IA_CSS_PIPE_OUTPUT_STAGE_0
].padded_width
= output_padded_width
;
10244 pipe
->output_info
[IA_CSS_PIPE_OUTPUT_STAGE_0
].padded_width
= output_padded_width
;
10249 static struct ia_css_binary
*
10250 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe
*pipe
)
10252 struct ia_css_binary
*binary
= NULL
;
10254 assert(pipe
!= NULL
);
10256 switch (pipe
->config
.mode
) {
10257 case IA_CSS_PIPE_MODE_PREVIEW
:
10258 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.preview
.preview_binary
;
10260 case IA_CSS_PIPE_MODE_VIDEO
:
10261 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.video
.video_binary
;
10263 case IA_CSS_PIPE_MODE_CAPTURE
:
10264 if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_PRIMARY
) {
10267 for (i
= 0; i
< pipe
->pipe_settings
.capture
.num_primary_stage
; i
++) {
10268 if (pipe
->pipe_settings
.capture
.primary_binary
[i
].info
->sp
.enable
.sc
) {
10269 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.primary_binary
[i
];
10274 else if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
)
10275 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.pre_isp_binary
;
10276 else if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_ADVANCED
||
10277 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_LOW_LIGHT
) {
10278 if (pipe
->config
.isp_pipe_version
== IA_CSS_PIPE_VERSION_1
)
10279 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.pre_isp_binary
;
10280 else if (pipe
->config
.isp_pipe_version
== IA_CSS_PIPE_VERSION_2_2
)
10281 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.post_isp_binary
;
10288 if (binary
&& binary
->info
->sp
.enable
.sc
)
10294 static struct ia_css_binary
*
10295 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe
*pipe
)
10297 struct ia_css_binary
*binary
= NULL
;
10299 assert(pipe
!= NULL
);
10301 switch (pipe
->config
.mode
) {
10302 case IA_CSS_PIPE_MODE_PREVIEW
:
10303 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.preview
.preview_binary
;
10305 case IA_CSS_PIPE_MODE_VIDEO
:
10306 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.video
.video_binary
;
10308 case IA_CSS_PIPE_MODE_CAPTURE
:
10309 if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_PRIMARY
) {
10311 for (i
= 0; i
< pipe
->pipe_settings
.capture
.num_primary_stage
; i
++) {
10312 if (pipe
->pipe_settings
.capture
.primary_binary
[i
].info
->sp
.enable
.s3a
) {
10313 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.primary_binary
[i
];
10318 else if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
)
10319 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.pre_isp_binary
;
10320 else if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_ADVANCED
||
10321 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_LOW_LIGHT
) {
10322 if (pipe
->config
.isp_pipe_version
== IA_CSS_PIPE_VERSION_1
)
10323 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.pre_isp_binary
;
10324 else if (pipe
->config
.isp_pipe_version
== IA_CSS_PIPE_VERSION_2_2
)
10325 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.capture
.post_isp_binary
;
10334 if (binary
&& !binary
->info
->sp
.enable
.s3a
)
10340 static struct ia_css_binary
*
10341 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe
*pipe
)
10343 struct ia_css_binary
*binary
= NULL
;
10345 assert(pipe
!= NULL
);
10347 switch (pipe
->config
.mode
) {
10348 case IA_CSS_PIPE_MODE_VIDEO
:
10349 binary
= (struct ia_css_binary
*)&pipe
->pipe_settings
.video
.video_binary
;
10355 if (binary
&& !binary
->info
->sp
.enable
.dis
)
10361 struct ia_css_pipeline
*
10362 ia_css_pipe_get_pipeline(const struct ia_css_pipe
*pipe
)
10364 assert(pipe
!= NULL
);
10366 return (struct ia_css_pipeline
*)&pipe
->pipeline
;
10370 ia_css_pipe_get_pipe_num(const struct ia_css_pipe
*pipe
)
10372 assert(pipe
!= NULL
);
10374 /* KW was not sure this function was not returning a value
10375 that was out of range; so added an assert, and, for the
10376 case when asserts are not enabled, clip to the largest
10377 value; pipe_num is unsigned so the value cannot be too small
10379 assert(pipe
->pipe_num
< IA_CSS_PIPELINE_NUM_MAX
);
10381 if (pipe
->pipe_num
>= IA_CSS_PIPELINE_NUM_MAX
)
10382 return (IA_CSS_PIPELINE_NUM_MAX
- 1);
10384 return pipe
->pipe_num
;
10389 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe
*pipe
)
10391 assert(pipe
!= NULL
);
10393 return (unsigned int)pipe
->config
.isp_pipe_version
;
10396 #define SP_START_TIMEOUT_US 30000000
10399 ia_css_start_sp(void)
10401 unsigned long timeout
;
10402 enum ia_css_err err
= IA_CSS_SUCCESS
;
10405 sh_css_sp_start_isp();
10407 /* waiting for the SP is completely started */
10408 timeout
= SP_START_TIMEOUT_US
;
10409 while((ia_css_spctrl_get_state(SP0_ID
) != IA_CSS_SP_SW_INITIALIZED
) && timeout
) {
10413 if (timeout
== 0) {
10414 IA_CSS_ERROR("timeout during SP initialization");
10415 return IA_CSS_ERR_INTERNAL_ERROR
;
10418 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10419 /* TODO: Fix this. */
10421 sh_css_init_host_sp_control_vars();
10423 /* buffers should be initialized only when sp is started */
10424 /* AM: At the moment it will be done only when there is no stream active. */
10426 sh_css_setup_queues();
10427 ia_css_bufq_dump_queue_info();
10430 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10431 ia_css_set_system_mode(IA_CSS_SYS_MODE_WORKING
);
10434 IA_CSS_LEAVE_ERR(err
);
10439 * Time to wait SP for termincate. Only condition when this can happen
10440 * is a fatal hw failure, but we must be able to detect this and emit
10441 * a proper error trace.
10443 #define SP_SHUTDOWN_TIMEOUT_US 200000
10446 ia_css_stop_sp(void)
10448 unsigned long timeout
;
10449 enum ia_css_err err
= IA_CSS_SUCCESS
;
10451 IA_CSS_ENTER("void");
10453 if (!sh_css_sp_is_running()) {
10454 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10455 IA_CSS_LEAVE("SP already stopped : return_err=%d", err
);
10457 /* Return an error - stop SP should not have been called by driver */
10461 /* For now, stop whole SP */
10463 sh_css_write_host2sp_command(host2sp_cmd_terminate
);
10465 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate
)) {
10466 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10467 ia_css_debug_dump_sp_sw_debug_info();
10468 ia_css_debug_dump_debug_info(NULL
);
10471 sh_css_sp_set_sp_running(false);
10473 timeout
= SP_SHUTDOWN_TIMEOUT_US
;
10474 while (!ia_css_spctrl_is_idle(SP0_ID
) && timeout
) {
10478 if ((ia_css_spctrl_get_state(SP0_ID
) != IA_CSS_SP_SW_TERMINATED
))
10479 IA_CSS_WARNING("SP has not terminated (SW)");
10481 if (timeout
== 0) {
10482 IA_CSS_WARNING("SP is not idle");
10483 ia_css_debug_dump_sp_sw_debug_info();
10485 timeout
= SP_SHUTDOWN_TIMEOUT_US
;
10486 while (!isp_ctrl_getbit(ISP0_ID
, ISP_SC_REG
, ISP_IDLE_BIT
) && timeout
) {
10490 if (timeout
== 0) {
10491 IA_CSS_WARNING("ISP is not idle");
10492 ia_css_debug_dump_sp_sw_debug_info();
10495 sh_css_hmm_buffer_record_uninit();
10498 /* clear pending param sets from refcount */
10499 sh_css_param_clear_param_sets();
10501 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10502 /* clear pending param sets from refcount */
10503 sh_css_param_clear_param_sets();
10504 ia_css_set_system_mode(IA_CSS_SYS_MODE_INIT
); /* System is initialized but not 'running' */
10508 IA_CSS_LEAVE_ERR(err
);
10513 ia_css_update_continuous_frames(struct ia_css_stream
*stream
)
10515 struct ia_css_pipe
*pipe
;
10518 ia_css_debug_dtrace(
10519 IA_CSS_DEBUG_TRACE
,
10520 "sh_css_update_continuous_frames() enter:\n");
10522 if (stream
== NULL
) {
10523 ia_css_debug_dtrace(
10524 IA_CSS_DEBUG_TRACE
,
10525 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10526 return IA_CSS_ERR_INVALID_ARGUMENTS
;
10529 pipe
= stream
->continuous_pipe
;
10531 for (i
= stream
->config
.init_num_cont_raw_buf
;
10532 i
< stream
->config
.target_num_cont_raw_buf
; i
++) {
10533 sh_css_update_host2sp_offline_frame(i
,
10534 pipe
->continuous_frames
[i
], pipe
->cont_md_buffers
[i
]);
10536 sh_css_update_host2sp_cont_num_raw_frames
10537 (stream
->config
.target_num_cont_raw_buf
, true);
10538 ia_css_debug_dtrace(
10539 IA_CSS_DEBUG_TRACE
,
10540 "sh_css_update_continuous_frames() leave: return_void\n");
10542 return IA_CSS_SUCCESS
;
10545 void ia_css_pipe_map_queue(struct ia_css_pipe
*pipe
, bool map
)
10547 unsigned int thread_id
;
10548 enum ia_css_pipe_id pipe_id
;
10549 unsigned int pipe_num
;
10550 bool need_input_queue
;
10553 assert(pipe
!= NULL
);
10555 pipe_id
= pipe
->mode
;
10556 pipe_num
= pipe
->pipe_num
;
10558 ia_css_pipeline_get_sp_thread_id(pipe_num
, &thread_id
);
10560 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10561 need_input_queue
= true;
10563 need_input_queue
= pipe
->stream
->config
.mode
== IA_CSS_INPUT_MODE_MEMORY
;
10566 /* map required buffer queues to resources */
10567 /* TODO: to be improved */
10568 if (pipe
->mode
== IA_CSS_PIPE_ID_PREVIEW
) {
10569 if (need_input_queue
)
10570 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10571 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, map
);
10572 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PARAMETER_SET
, map
);
10573 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET
, map
);
10574 #if defined SH_CSS_ENABLE_METADATA
10575 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10577 if (pipe
->pipe_settings
.preview
.preview_binary
.info
&&
10578 pipe
->pipe_settings
.preview
.preview_binary
.info
->sp
.enable
.s3a
)
10579 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_3A_STATISTICS
, map
);
10580 } else if (pipe
->mode
== IA_CSS_PIPE_ID_CAPTURE
) {
10583 if (need_input_queue
)
10584 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10585 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, map
);
10586 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
, map
);
10587 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PARAMETER_SET
, map
);
10588 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET
, map
);
10589 #if defined SH_CSS_ENABLE_METADATA
10590 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10592 if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_PRIMARY
) {
10593 for (i
= 0; i
< pipe
->pipe_settings
.capture
.num_primary_stage
; i
++) {
10594 if (pipe
->pipe_settings
.capture
.primary_binary
[i
].info
&&
10595 pipe
->pipe_settings
.capture
.primary_binary
[i
].info
->sp
.enable
.s3a
) {
10596 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_3A_STATISTICS
, map
);
10600 } else if (pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_ADVANCED
||
10601 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_LOW_LIGHT
||
10602 pipe
->config
.default_capture_config
.mode
== IA_CSS_CAPTURE_MODE_BAYER
) {
10603 if (pipe
->pipe_settings
.capture
.pre_isp_binary
.info
&&
10604 pipe
->pipe_settings
.capture
.pre_isp_binary
.info
->sp
.enable
.s3a
)
10605 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_3A_STATISTICS
, map
);
10607 } else if (pipe
->mode
== IA_CSS_PIPE_ID_VIDEO
) {
10608 if (need_input_queue
)
10609 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10610 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, map
);
10611 if (pipe
->enable_viewfinder
[IA_CSS_PIPE_OUTPUT_STAGE_0
])
10612 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
, map
);
10613 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PARAMETER_SET
, map
);
10614 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET
, map
);
10615 #if defined SH_CSS_ENABLE_METADATA
10616 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10618 if (pipe
->pipe_settings
.video
.video_binary
.info
&&
10619 pipe
->pipe_settings
.video
.video_binary
.info
->sp
.enable
.s3a
)
10620 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_3A_STATISTICS
, map
);
10621 if (pipe
->pipe_settings
.video
.video_binary
.info
&&
10622 (pipe
->pipe_settings
.video
.video_binary
.info
->sp
.enable
.dis
10624 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_DIS_STATISTICS
, map
);
10625 } else if (pipe
->mode
== IA_CSS_PIPE_ID_COPY
) {
10626 if (need_input_queue
)
10627 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10628 if (!pipe
->stream
->config
.continuous
)
10629 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, map
);
10630 #if defined SH_CSS_ENABLE_METADATA
10631 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10633 } else if (pipe
->mode
== IA_CSS_PIPE_ID_ACC
) {
10634 if (need_input_queue
)
10635 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10636 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
, map
);
10637 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PARAMETER_SET
, map
);
10638 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET
, map
);
10639 #if defined SH_CSS_ENABLE_METADATA
10640 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10642 } else if (pipe
->mode
== IA_CSS_PIPE_ID_YUVPP
) {
10644 for (idx
= 0; idx
< IA_CSS_PIPE_MAX_OUTPUT_STAGE
; idx
++) {
10645 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME
+ idx
, map
);
10646 if (pipe
->enable_viewfinder
[idx
])
10647 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME
+ idx
, map
);
10649 if (need_input_queue
)
10650 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_INPUT_FRAME
, map
);
10651 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_PARAMETER_SET
, map
);
10652 #if defined SH_CSS_ENABLE_METADATA
10653 ia_css_queue_map(thread_id
, IA_CSS_BUFFER_TYPE_METADATA
, map
);
10659 #if CONFIG_ON_FRAME_ENQUEUE()
10660 static enum ia_css_err
set_config_on_frame_enqueue(struct ia_css_frame_info
*info
, struct frame_data_wrapper
*frame
)
10662 frame
->config_on_frame_enqueue
.padded_width
= 0;
10664 /* currently we support configuration on frame enqueue only on YUV formats */
10665 /* on other formats the padded_width is zeroed for no configuration override */
10666 switch (info
->format
) {
10667 case IA_CSS_FRAME_FORMAT_YUV420
:
10668 case IA_CSS_FRAME_FORMAT_NV12
:
10669 if (info
->padded_width
> info
->res
.width
)
10671 frame
->config_on_frame_enqueue
.padded_width
= info
->padded_width
;
10673 else if ((info
->padded_width
< info
->res
.width
) && (info
->padded_width
> 0))
10675 return IA_CSS_ERR_INVALID_ARGUMENTS
;
10677 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10683 return IA_CSS_SUCCESS
;
10688 ia_css_unlock_raw_frame(struct ia_css_stream
*stream
, uint32_t exp_id
)
10690 enum ia_css_err ret
;
10694 /* Only continuous streams have a tagger to which we can send the
10695 * unlock message. */
10696 if (stream
== NULL
|| !stream
->config
.continuous
) {
10697 IA_CSS_ERROR("invalid stream pointer");
10698 return IA_CSS_ERR_INVALID_ARGUMENTS
;
10701 if (exp_id
> IA_CSS_ISYS_MAX_EXPOSURE_ID
||
10702 exp_id
< IA_CSS_ISYS_MIN_EXPOSURE_ID
) {
10703 IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id
);
10704 return IA_CSS_ERR_INVALID_ARGUMENTS
;
10707 /* Send the event. Since we verified that the exp_id is valid,
10708 * we can safely assign it to an 8-bit argument here. */
10709 ret
= ia_css_bufq_enqueue_psys_event(
10710 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER
, exp_id
, 0, 0);
10712 IA_CSS_LEAVE_ERR(ret
);
10716 /** @brief Set the state (Enable or Disable) of the Extension stage in the
10720 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe
*pipe
, uint32_t fw_handle
, bool enable
)
10722 unsigned int thread_id
;
10723 struct ia_css_pipeline_stage
*stage
;
10724 enum ia_css_err err
= IA_CSS_SUCCESS
;
10728 /* Parameter Check */
10729 if (pipe
== NULL
|| pipe
->stream
== NULL
) {
10730 IA_CSS_ERROR("Invalid Pipe.");
10731 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10732 } else if (!(pipe
->config
.acc_extension
)) {
10733 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10734 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10735 } else if (!sh_css_sp_is_running()) {
10736 IA_CSS_ERROR("Leaving: queue unavailable.");
10737 err
= IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
10739 /* Query the threadid and stage_num for the Extension firmware*/
10740 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
10741 err
= ia_css_pipeline_get_stage_from_fw(&(pipe
->pipeline
), fw_handle
, &stage
);
10742 if (err
== IA_CSS_SUCCESS
) {
10743 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10744 err
= ia_css_bufq_enqueue_psys_event(
10745 (uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE
,
10746 (uint8_t) thread_id
,
10747 (uint8_t) stage
->stage_num
,
10748 (enable
== true) ? 1 : 0);
10749 if (err
== IA_CSS_SUCCESS
) {
10751 SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group
.pipe
[thread_id
]),stage
->stage_num
);
10753 SH_CSS_QOS_STAGE_DISABLE(&(sh_css_sp_group
.pipe
[thread_id
]),stage
->stage_num
);
10757 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err
, fw_handle
, enable
);
10761 /** @brief Get the state (Enable or Disable) of the Extension stage in the
10765 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe
*pipe
, uint32_t fw_handle
, bool *enable
)
10767 struct ia_css_pipeline_stage
*stage
;
10768 unsigned int thread_id
;
10769 enum ia_css_err err
= IA_CSS_SUCCESS
;
10773 /* Parameter Check */
10774 if (pipe
== NULL
|| pipe
->stream
== NULL
) {
10775 IA_CSS_ERROR("Invalid Pipe.");
10776 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10777 } else if (!(pipe
->config
.acc_extension
)) {
10778 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10779 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10780 } else if (!sh_css_sp_is_running()) {
10781 IA_CSS_ERROR("Leaving: queue unavailable.");
10782 err
= IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
10784 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10785 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
10786 err
= ia_css_pipeline_get_stage_from_fw(&pipe
->pipeline
, fw_handle
, &stage
);
10788 if (err
== IA_CSS_SUCCESS
) {
10789 /* Get the Extension State */
10790 *enable
= (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group
.pipe
[thread_id
]),stage
->stage_num
)) ? true : false;
10793 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err
, fw_handle
, *enable
);
10799 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe
*pipe
, uint32_t fw_handle
,
10800 struct ia_css_isp_param_css_segments
*css_seg
, struct ia_css_isp_param_isp_segments
*isp_seg
)
10802 unsigned int HIVE_ADDR_sp_group
;
10803 static struct sh_css_sp_group sp_group
;
10804 static struct sh_css_sp_stage sp_stage
;
10805 static struct sh_css_isp_stage isp_stage
;
10806 const struct ia_css_fw_info
*fw
;
10807 unsigned int thread_id
;
10808 struct ia_css_pipeline_stage
*stage
;
10809 enum ia_css_err err
= IA_CSS_SUCCESS
;
10811 enum ia_css_isp_memories mem
;
10816 fw
= &sh_css_sp_fw
;
10818 /* Parameter Check */
10819 if (pipe
== NULL
|| pipe
->stream
== NULL
) {
10820 IA_CSS_ERROR("Invalid Pipe.");
10821 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10822 } else if (!(pipe
->config
.acc_extension
)) {
10823 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10824 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10825 } else if (!sh_css_sp_is_running()) {
10826 IA_CSS_ERROR("Leaving: queue unavailable.");
10827 err
= IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
10829 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10830 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe
), &thread_id
);
10831 err
= ia_css_pipeline_get_stage_from_fw(&(pipe
->pipeline
), fw_handle
, &stage
);
10832 if (err
== IA_CSS_SUCCESS
) {
10833 /* Get the Extension State */
10834 enabled
= (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group
.pipe
[thread_id
]), stage
->stage_num
)) ? true : false;
10835 /* Update mapped arg only when extension stage is not enabled */
10837 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10838 err
= IA_CSS_ERR_RESOURCE_NOT_AVAILABLE
;
10840 stage_num
= stage
->stage_num
;
10842 HIVE_ADDR_sp_group
= fw
->info
.sp
.group
;
10843 sp_dmem_load(SP0_ID
,
10844 (unsigned int)sp_address_of(sp_group
),
10845 &sp_group
, sizeof(struct sh_css_sp_group
));
10846 mmgr_load(sp_group
.pipe
[thread_id
].sp_stage_addr
[stage_num
],
10847 &sp_stage
, sizeof(struct sh_css_sp_stage
));
10849 mmgr_load(sp_stage
.isp_stage_addr
,
10850 &isp_stage
, sizeof(struct sh_css_isp_stage
));
10852 for (mem
= 0; mem
< N_IA_CSS_ISP_MEMORIES
; mem
++) {
10853 isp_stage
.mem_initializers
.params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].address
=
10854 css_seg
->params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].address
;
10855 isp_stage
.mem_initializers
.params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].size
=
10856 css_seg
->params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].size
;
10857 isp_stage
.binary_info
.mem_initializers
.params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].address
=
10858 isp_seg
->params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].address
;
10859 isp_stage
.binary_info
.mem_initializers
.params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].size
=
10860 isp_seg
->params
[IA_CSS_PARAM_CLASS_PARAM
][mem
].size
;
10863 mmgr_store(sp_stage
.isp_stage_addr
,
10864 &isp_stage
, sizeof(struct sh_css_isp_stage
));
10868 IA_CSS_LEAVE("err:%d handle:%u", err
, fw_handle
);
10872 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10873 static enum ia_css_err
10874 aspect_ratio_crop_init(struct ia_css_stream
*curr_stream
,
10875 struct ia_css_pipe
*pipes
[],
10876 bool *do_crop_status
)
10878 enum ia_css_err err
= IA_CSS_SUCCESS
;
10880 struct ia_css_pipe
*curr_pipe
;
10881 uint32_t pipe_mask
= 0;
10883 if ((curr_stream
== NULL
) ||
10884 (curr_stream
->num_pipes
== 0) ||
10886 (do_crop_status
== NULL
)) {
10887 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10888 IA_CSS_LEAVE_ERR(err
);
10892 for (i
= 0; i
< curr_stream
->num_pipes
; i
++) {
10893 curr_pipe
= pipes
[i
];
10894 pipe_mask
|= (1 << curr_pipe
->config
.mode
);
10898 (((pipe_mask
& (1 << IA_CSS_PIPE_MODE_PREVIEW
)) ||
10899 (pipe_mask
& (1 << IA_CSS_PIPE_MODE_VIDEO
))) &&
10900 (pipe_mask
& (1 << IA_CSS_PIPE_MODE_CAPTURE
)) &&
10901 curr_stream
->config
.continuous
);
10902 return IA_CSS_SUCCESS
;
10906 aspect_ratio_crop_check(bool enabled
, struct ia_css_pipe
*curr_pipe
)
10908 bool status
= false;
10910 if ((curr_pipe
!= NULL
) && enabled
) {
10911 if ((curr_pipe
->config
.mode
== IA_CSS_PIPE_MODE_PREVIEW
) ||
10912 (curr_pipe
->config
.mode
== IA_CSS_PIPE_MODE_VIDEO
) ||
10913 (curr_pipe
->config
.mode
== IA_CSS_PIPE_MODE_CAPTURE
))
10920 static enum ia_css_err
10921 aspect_ratio_crop(struct ia_css_pipe
*curr_pipe
,
10922 struct ia_css_resolution
*effective_res
)
10924 enum ia_css_err err
= IA_CSS_SUCCESS
;
10925 struct ia_css_resolution crop_res
;
10926 struct ia_css_resolution
*in_res
= NULL
;
10927 struct ia_css_resolution
*out_res
= NULL
;
10928 bool use_bds_output_info
= false;
10929 bool use_vf_pp_in_res
= false;
10930 bool use_capt_pp_in_res
= false;
10932 if ((curr_pipe
== NULL
) ||
10933 (effective_res
== NULL
)) {
10934 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10935 IA_CSS_LEAVE_ERR(err
);
10939 if ((curr_pipe
->config
.mode
!= IA_CSS_PIPE_MODE_PREVIEW
) &&
10940 (curr_pipe
->config
.mode
!= IA_CSS_PIPE_MODE_VIDEO
) &&
10941 (curr_pipe
->config
.mode
!= IA_CSS_PIPE_MODE_CAPTURE
)) {
10942 err
= IA_CSS_ERR_INVALID_ARGUMENTS
;
10943 IA_CSS_LEAVE_ERR(err
);
10947 use_bds_output_info
=
10948 ((curr_pipe
->bds_output_info
.res
.width
!= 0) &&
10949 (curr_pipe
->bds_output_info
.res
.height
!= 0));
10952 ((curr_pipe
->config
.vf_pp_in_res
.width
!= 0) &&
10953 (curr_pipe
->config
.vf_pp_in_res
.height
!= 0));
10955 use_capt_pp_in_res
=
10956 ((curr_pipe
->config
.capt_pp_in_res
.width
!= 0) &&
10957 (curr_pipe
->config
.capt_pp_in_res
.height
!= 0));
10959 in_res
= &curr_pipe
->stream
->config
.input_config
.effective_res
;
10960 out_res
= &curr_pipe
->output_info
[0].res
;
10962 switch (curr_pipe
->config
.mode
) {
10963 case IA_CSS_PIPE_MODE_PREVIEW
:
10964 if (use_bds_output_info
)
10965 out_res
= &curr_pipe
->bds_output_info
.res
;
10966 else if (use_vf_pp_in_res
)
10967 out_res
= &curr_pipe
->config
.vf_pp_in_res
;
10969 case IA_CSS_PIPE_MODE_VIDEO
:
10970 if (use_bds_output_info
)
10971 out_res
= &curr_pipe
->bds_output_info
.res
;
10973 case IA_CSS_PIPE_MODE_CAPTURE
:
10974 if (use_capt_pp_in_res
)
10975 out_res
= &curr_pipe
->config
.capt_pp_in_res
;
10977 case IA_CSS_PIPE_MODE_ACC
:
10978 case IA_CSS_PIPE_MODE_COPY
:
10979 case IA_CSS_PIPE_MODE_YUVPP
:
10981 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10982 curr_pipe
->config
.mode
);
10987 err
= ia_css_frame_find_crop_resolution(in_res
, out_res
, &crop_res
);
10988 if (err
== IA_CSS_SUCCESS
) {
10989 *effective_res
= crop_res
;
10991 /* in case of error fallback to default
10992 * effective resolution from driver. */
10993 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err
);
11001 sh_css_hmm_buffer_record_init(void)
11006 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11007 sh_css_hmm_buffer_record_reset(&hmm_buffer_record
[i
]);
11009 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11010 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11011 sh_css_hmm_buffer_record_reset(&hmm_buffer_record
[i
]);
11018 sh_css_hmm_buffer_record_uninit(void)
11021 struct sh_css_hmm_buffer_record
*buffer_record
= NULL
;
11024 buffer_record
= &hmm_buffer_record
[0];
11025 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11026 if (buffer_record
->in_use
) {
11027 if (buffer_record
->h_vbuf
!= NULL
)
11028 ia_css_rmgr_rel_vbuf(hmm_buffer_pool
, &buffer_record
->h_vbuf
);
11029 sh_css_hmm_buffer_record_reset(buffer_record
);
11031 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11032 buffer_record
= &hmm_buffer_record
[0];
11033 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11034 if (buffer_record
->in_use
) {
11035 if (buffer_record
->h_vbuf
!= NULL
)
11036 ia_css_rmgr_rel_vbuf(hmm_buffer_pool
, &buffer_record
->h_vbuf
);
11037 sh_css_hmm_buffer_record_reset(buffer_record
);
11049 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record
*buffer_record
)
11051 assert(buffer_record
!= NULL
);
11052 buffer_record
->in_use
= false;
11053 buffer_record
->type
= IA_CSS_BUFFER_TYPE_INVALID
;
11054 buffer_record
->h_vbuf
= NULL
;
11055 buffer_record
->kernel_ptr
= 0;
11058 static struct sh_css_hmm_buffer_record
11059 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle
*h_vbuf
,
11060 enum ia_css_buffer_type type
,
11061 hrt_address kernel_ptr
)
11064 struct sh_css_hmm_buffer_record
*buffer_record
= NULL
;
11065 struct sh_css_hmm_buffer_record
*out_buffer_record
= NULL
;
11067 assert(h_vbuf
!= NULL
);
11068 assert((type
> IA_CSS_BUFFER_TYPE_INVALID
) && (type
< IA_CSS_NUM_DYNAMIC_BUFFER_TYPE
));
11069 assert(kernel_ptr
!= 0);
11071 buffer_record
= &hmm_buffer_record
[0];
11072 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11073 if (buffer_record
->in_use
== false) {
11074 buffer_record
->in_use
= true;
11075 buffer_record
->type
= type
;
11076 buffer_record
->h_vbuf
= h_vbuf
;
11077 buffer_record
->kernel_ptr
= kernel_ptr
;
11078 out_buffer_record
= buffer_record
;
11084 return out_buffer_record
;
11087 static struct sh_css_hmm_buffer_record
11088 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr
,
11089 enum ia_css_buffer_type type
)
11092 struct sh_css_hmm_buffer_record
*buffer_record
= NULL
;
11093 bool found_record
= false;
11095 buffer_record
= &hmm_buffer_record
[0];
11096 for (i
= 0; i
< MAX_HMM_BUFFER_NUM
; i
++) {
11097 if ((buffer_record
->in_use
== true) &&
11098 (buffer_record
->type
== type
) &&
11099 (buffer_record
->h_vbuf
!= NULL
) &&
11100 (buffer_record
->h_vbuf
->vptr
== ddr_buffer_addr
)) {
11101 found_record
= true;
11107 if (found_record
== true)
11108 return buffer_record
;