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 #define array_length(array) (sizeof(array)/sizeof(array[0]))
456 /* Verify whether the selected output format is can be produced
457 * by the copy binary given the stream format.
459 static enum ia_css_err
460 verify_copy_out_frame_format(struct ia_css_pipe *pipe)
462 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
463 unsigned int i, found = 0;
465 assert(pipe != NULL);
466 assert(pipe->stream != NULL);
468 switch (pipe->stream->config.input_config.format) {
469 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
470 case IA_CSS_STREAM_FORMAT_YUV420_8:
471 for (i=0; i<array_length(yuv420_copy_formats) && !found; i++)
472 found = (out_fmt == yuv420_copy_formats[i]);
474 case IA_CSS_STREAM_FORMAT_YUV420_10:
475 case IA_CSS_STREAM_FORMAT_YUV420_16:
476 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
478 case IA_CSS_STREAM_FORMAT_YUV422_8:
479 for (i=0; i<array_length(yuv422_copy_formats) && !found; i++)
480 found = (out_fmt == yuv422_copy_formats[i]);
482 case IA_CSS_STREAM_FORMAT_YUV422_10:
483 case IA_CSS_STREAM_FORMAT_YUV422_16:
484 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
485 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
487 case IA_CSS_STREAM_FORMAT_RGB_444:
488 case IA_CSS_STREAM_FORMAT_RGB_555:
489 case IA_CSS_STREAM_FORMAT_RGB_565:
490 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
491 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
493 case IA_CSS_STREAM_FORMAT_RGB_666:
494 case IA_CSS_STREAM_FORMAT_RGB_888:
495 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
496 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
498 case IA_CSS_STREAM_FORMAT_RAW_6:
499 case IA_CSS_STREAM_FORMAT_RAW_7:
500 case IA_CSS_STREAM_FORMAT_RAW_8:
501 case IA_CSS_STREAM_FORMAT_RAW_10:
502 case IA_CSS_STREAM_FORMAT_RAW_12:
503 case IA_CSS_STREAM_FORMAT_RAW_14:
504 case IA_CSS_STREAM_FORMAT_RAW_16:
505 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
506 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
508 case IA_CSS_STREAM_FORMAT_BINARY_8:
509 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
515 return IA_CSS_ERR_INVALID_ARGUMENTS;
516 return IA_CSS_SUCCESS;
520 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
525 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
526 stream->config.pixels_per_clock == 2);
531 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
532 static enum ia_css_err
533 sh_css_config_input_network(struct ia_css_stream *stream)
535 unsigned int fmt_type;
536 struct ia_css_pipe *pipe = stream->last_pipe;
537 struct ia_css_binary *binary = NULL;
538 enum ia_css_err err = IA_CSS_SUCCESS;
540 assert(stream != NULL);
541 assert(pipe != NULL);
543 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
544 "sh_css_config_input_network() enter:\n");
546 if (pipe->pipeline.stages)
547 binary = pipe->pipeline.stages->binary;
549 err = ia_css_isys_convert_stream_format_to_mipi_format(
550 stream->config.input_config.format,
551 stream->csi_rx_config.comp,
553 if (err != IA_CSS_SUCCESS)
555 sh_css_sp_program_input_circuit(fmt_type,
556 stream->config.channel_id,
557 stream->config.mode);
559 if ((binary && (binary->online || stream->config.continuous)) ||
560 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
561 err = ia_css_ifmtr_configure(&stream->config,
563 if (err != IA_CSS_SUCCESS)
567 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
568 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
569 unsigned int hblank_cycles = 100,
574 width = (stream->config.input_config.input_res.width) / (1 + (stream->config.pixels_per_clock == 2));
575 height = stream->config.input_config.input_res.height;
576 vblank_cycles = vblank_lines * (width + hblank_cycles);
577 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
579 #if defined(IS_ISP_2400_SYSTEM)
580 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
581 /* TODO: move define to proper file in tools */
582 #define GP_ISEL_TPG_MODE 0x90058
583 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
587 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
588 "sh_css_config_input_network() leave:\n");
589 return IA_CSS_SUCCESS;
591 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
592 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
593 enum ia_css_stream_format format,
594 unsigned int pixels_per_line)
599 case IA_CSS_STREAM_FORMAT_YUV420_8_LEGACY:
601 * The frame format layout is shown below.
603 * Line 0: UYY0 UYY0 ... UYY0
604 * Line 1: VYY0 VYY0 ... VYY0
605 * Line 2: UYY0 UYY0 ... UYY0
606 * Line 3: VYY0 VYY0 ... VYY0
608 * Line (n-2): UYY0 UYY0 ... UYY0
609 * Line (n-1): VYY0 VYY0 ... VYY0
611 * In this frame format, the even-line is
612 * as wide as the odd-line.
613 * The 0 is introduced by the input system
616 rval = pixels_per_line * 2;
618 case IA_CSS_STREAM_FORMAT_YUV420_8:
619 case IA_CSS_STREAM_FORMAT_YUV420_10:
620 case IA_CSS_STREAM_FORMAT_YUV420_16:
622 * The frame format layout is shown below.
624 * Line 0: YYYY YYYY ... YYYY
625 * Line 1: UYVY UYVY ... UYVY UYVY
626 * Line 2: YYYY YYYY ... YYYY
627 * Line 3: UYVY UYVY ... UYVY UYVY
629 * Line (n-2): YYYY YYYY ... YYYY
630 * Line (n-1): UYVY UYVY ... UYVY UYVY
632 * In this frame format, the odd-line is twice
633 * wider than the even-line.
635 rval = pixels_per_line * 2;
637 case IA_CSS_STREAM_FORMAT_YUV422_8:
638 case IA_CSS_STREAM_FORMAT_YUV422_10:
639 case IA_CSS_STREAM_FORMAT_YUV422_16:
641 * The frame format layout is shown below.
643 * Line 0: UYVY UYVY ... UYVY
644 * Line 1: UYVY UYVY ... UYVY
645 * Line 2: UYVY UYVY ... UYVY
646 * Line 3: UYVY UYVY ... UYVY
648 * Line (n-2): UYVY UYVY ... UYVY
649 * Line (n-1): UYVY UYVY ... UYVY
651 * In this frame format, the even-line is
652 * as wide as the odd-line.
654 rval = pixels_per_line * 2;
656 case IA_CSS_STREAM_FORMAT_RGB_444:
657 case IA_CSS_STREAM_FORMAT_RGB_555:
658 case IA_CSS_STREAM_FORMAT_RGB_565:
659 case IA_CSS_STREAM_FORMAT_RGB_666:
660 case IA_CSS_STREAM_FORMAT_RGB_888:
662 * The frame format layout is shown below.
664 * Line 0: ABGR ABGR ... ABGR
665 * Line 1: ABGR ABGR ... ABGR
666 * Line 2: ABGR ABGR ... ABGR
667 * Line 3: ABGR ABGR ... ABGR
669 * Line (n-2): ABGR ABGR ... ABGR
670 * Line (n-1): ABGR ABGR ... ABGR
672 * In this frame format, the even-line is
673 * as wide as the odd-line.
675 rval = pixels_per_line * 4;
677 case IA_CSS_STREAM_FORMAT_RAW_6:
678 case IA_CSS_STREAM_FORMAT_RAW_7:
679 case IA_CSS_STREAM_FORMAT_RAW_8:
680 case IA_CSS_STREAM_FORMAT_RAW_10:
681 case IA_CSS_STREAM_FORMAT_RAW_12:
682 case IA_CSS_STREAM_FORMAT_RAW_14:
683 case IA_CSS_STREAM_FORMAT_RAW_16:
684 case IA_CSS_STREAM_FORMAT_BINARY_8:
685 case IA_CSS_STREAM_FORMAT_USER_DEF1:
686 case IA_CSS_STREAM_FORMAT_USER_DEF2:
687 case IA_CSS_STREAM_FORMAT_USER_DEF3:
688 case IA_CSS_STREAM_FORMAT_USER_DEF4:
689 case IA_CSS_STREAM_FORMAT_USER_DEF5:
690 case IA_CSS_STREAM_FORMAT_USER_DEF6:
691 case IA_CSS_STREAM_FORMAT_USER_DEF7:
692 case IA_CSS_STREAM_FORMAT_USER_DEF8:
694 * The frame format layout is shown below.
696 * Line 0: Pixel Pixel ... Pixel
697 * Line 1: Pixel Pixel ... Pixel
698 * Line 2: Pixel Pixel ... Pixel
699 * Line 3: Pixel Pixel ... Pixel
701 * Line (n-2): Pixel Pixel ... Pixel
702 * Line (n-1): Pixel Pixel ... Pixel
704 * In this frame format, the even-line is
705 * as wide as the odd-line.
707 rval = pixels_per_line;
717 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
718 struct ia_css_stream_config *stream_cfg,
719 ia_css_isys_descr_t *isys_stream_descr)
724 switch (stream_cfg->mode) {
725 case IA_CSS_INPUT_MODE_TPG:
727 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
728 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
729 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
730 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
731 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
732 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
736 case IA_CSS_INPUT_MODE_PRBS:
738 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
739 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
740 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
741 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
742 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
743 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
747 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
749 if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT0) {
750 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
751 } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT1) {
752 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
753 } else if (stream_cfg->source.port.port == IA_CSS_CSI2_PORT2) {
754 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
766 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
767 struct ia_css_stream_config *stream_cfg,
768 ia_css_isys_descr_t *isys_stream_descr)
773 switch (stream_cfg->mode) {
774 case IA_CSS_INPUT_MODE_TPG:
776 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
779 case IA_CSS_INPUT_MODE_PRBS:
781 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
784 case IA_CSS_INPUT_MODE_SENSOR:
785 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
787 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
798 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
799 struct ia_css_stream_config *stream_cfg,
800 ia_css_isys_descr_t *isys_stream_descr,
806 switch (stream_cfg->mode) {
807 case IA_CSS_INPUT_MODE_TPG:
808 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
809 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
810 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
811 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
812 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
813 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
820 * - Make "color_cfg" as part of "ia_css_tpg_config".
822 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
823 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
824 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
825 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
826 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
827 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
829 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask = stream_cfg->source.tpg.x_mask;
830 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask = stream_cfg->source.tpg.y_mask;
831 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask = stream_cfg->source.tpg.xy_mask;
833 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta = stream_cfg->source.tpg.x_delta;
834 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta = stream_cfg->source.tpg.y_delta;
838 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
840 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
841 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
842 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
843 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
844 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;
845 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;
848 case IA_CSS_INPUT_MODE_PRBS:
850 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
851 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
855 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
857 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
858 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
859 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
860 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
861 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;
862 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;
865 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
868 unsigned int fmt_type;
870 err = ia_css_isys_convert_stream_format_to_mipi_format(
871 stream_cfg->isys_config[isys_stream_idx].format,
874 if (err != IA_CSS_SUCCESS)
877 isys_stream_descr->csi_port_attr.active_lanes = stream_cfg->source.port.num_lanes;
878 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
879 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
880 #ifdef USE_INPUT_SYSTEM_VERSION_2401
881 isys_stream_descr->online = stream_cfg->online;
883 err |= ia_css_isys_convert_compressed_format(
884 &stream_cfg->source.port.compression,
886 if (err != IA_CSS_SUCCESS)
890 isys_stream_descr->metadata.enable = false;
891 if (stream_cfg->metadata_config.resolution.height > 0) {
892 err = ia_css_isys_convert_stream_format_to_mipi_format(
893 stream_cfg->metadata_config.data_type,
896 if (err != IA_CSS_SUCCESS)
898 isys_stream_descr->metadata.fmt_type = fmt_type;
899 isys_stream_descr->metadata.bits_per_pixel =
900 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
901 isys_stream_descr->metadata.pixels_per_line = stream_cfg->metadata_config.resolution.width;
902 isys_stream_descr->metadata.lines_per_frame = stream_cfg->metadata_config.resolution.height;
903 #ifdef USE_INPUT_SYSTEM_VERSION_2401
904 /* For new input system, number of str2mmio requests must be even.
905 * So we round up number of metadata lines to be even. */
906 if (isys_stream_descr->metadata.lines_per_frame > 0)
907 isys_stream_descr->metadata.lines_per_frame +=
908 (isys_stream_descr->metadata.lines_per_frame & 1);
910 isys_stream_descr->metadata.align_req_in_bytes =
911 ia_css_csi2_calculate_input_system_alignment(stream_cfg->metadata_config.data_type);
912 isys_stream_descr->metadata.enable = true;
925 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
926 struct ia_css_stream_config *stream_cfg,
927 ia_css_isys_descr_t *isys_stream_descr,
930 unsigned int bits_per_subpixel;
931 unsigned int max_subpixels_per_line;
932 unsigned int lines_per_frame;
933 unsigned int align_req_in_bytes;
934 enum ia_css_stream_format fmt_type;
936 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
937 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
938 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
939 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
941 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
942 UNCOMPRESSED_BITS_PER_PIXEL_10) {
943 fmt_type = IA_CSS_STREAM_FORMAT_RAW_10;
945 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
946 UNCOMPRESSED_BITS_PER_PIXEL_12) {
947 fmt_type = IA_CSS_STREAM_FORMAT_RAW_12;
954 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
955 if (bits_per_subpixel == 0)
958 max_subpixels_per_line =
959 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
960 stream_cfg->isys_config[isys_stream_idx].input_res.width);
961 if (max_subpixels_per_line == 0)
964 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
965 if (lines_per_frame == 0)
968 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
970 /* HW needs subpixel info for their settings */
971 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
972 isys_stream_descr->input_port_resolution.pixels_per_line = max_subpixels_per_line;
973 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
974 isys_stream_descr->input_port_resolution.align_req_in_bytes = align_req_in_bytes;
979 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
980 struct ia_css_stream_config *stream_cfg,
982 ia_css_isys_descr_t *isys_stream_descr,
987 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
988 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
989 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, isys_stream_descr);
990 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, isys_stream_descr);
991 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, isys_stream_descr, isys_stream_idx);
992 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(stream_cfg, isys_stream_descr, isys_stream_idx);
994 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
995 isys_stream_descr->linked_isys_stream_id = (int8_t) stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
997 * Early polling is required for timestamp accuracy in certain case.
998 * The ISYS HW polling is started on
999 * ia_css_isys_stream_capture_indication() instead of
1000 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
1001 * capture takes longer than getting an ISYS frame
1003 * Only 2401 relevant ??
1005 isys_stream_descr->polling_mode
1006 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1007 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1008 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1009 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1014 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1015 struct ia_css_binary *binary,
1016 ia_css_isys_descr_t *isys_stream_descr)
1021 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1022 isys_stream_descr->output_port_attr.max_isp_input_width = binary->info->sp.input.max_width;
1027 static enum ia_css_err
1028 sh_css_config_input_network(struct ia_css_stream *stream)
1031 ia_css_isys_descr_t isys_stream_descr;
1032 unsigned int sp_thread_id;
1033 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1034 struct ia_css_pipe *pipe = NULL;
1035 struct ia_css_binary *binary = NULL;
1037 uint32_t isys_stream_id;
1038 bool early_polling = false;
1040 assert(stream != NULL);
1041 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1042 "sh_css_config_input_network() enter 0x%p:\n", stream);
1044 if (stream->config.continuous == true) {
1045 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1046 pipe = stream->last_pipe;
1047 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1048 pipe = stream->last_pipe;
1049 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1050 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1051 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1052 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1055 pipe = stream->last_pipe;
1056 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1058 * We need to poll the ISYS HW in capture_indication itself
1059 * for "non-continous" capture usecase for getting accurate
1060 * isys frame capture timestamps.
1061 * This is because the capturepipe propcessing takes longer
1062 * to execute than the input system frame capture.
1065 early_polling = true;
1069 assert(pipe != NULL);
1071 return IA_CSS_ERR_INTERNAL_ERROR;
1073 if (pipe->pipeline.stages != NULL)
1074 if (pipe->pipeline.stages->binary != NULL)
1075 binary = pipe->pipeline.stages->binary;
1080 /* this was being done in ifmtr in 2400.
1081 * online and cont bypass the init_in_frameinfo_memory_defaults
1082 * so need to do it here
1084 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1087 /* get the SP thread id */
1088 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1090 return IA_CSS_ERR_INTERNAL_ERROR;
1091 /* get the target input terminal */
1092 sp_pipeline_input_terminal = &(sh_css_sp_group.pipe_io[sp_thread_id].input);
1094 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
1095 /* initialization */
1096 memset((void*)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1097 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1098 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1100 if (!stream->config.isys_config[i].valid)
1103 /* translate the stream configuration to the Input System (2401) configuration */
1104 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1107 &(isys_stream_descr), i);
1109 if (stream->config.online) {
1110 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1112 &(isys_stream_descr));
1116 return IA_CSS_ERR_INTERNAL_ERROR;
1118 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1120 /* create the virtual Input System (2401) */
1121 rc = ia_css_isys_stream_create(
1122 &(isys_stream_descr),
1123 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1126 return IA_CSS_ERR_INTERNAL_ERROR;
1128 /* calculate the configuration of the virtual Input System (2401) */
1129 rc = ia_css_isys_stream_calculate_cfg(
1130 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1131 &(isys_stream_descr),
1132 &(sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]));
1134 ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]));
1135 return IA_CSS_ERR_INTERNAL_ERROR;
1139 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1140 "sh_css_config_input_network() leave:\n");
1142 return IA_CSS_SUCCESS;
1145 static inline struct ia_css_pipe *stream_get_last_pipe(
1146 struct ia_css_stream *stream)
1148 struct ia_css_pipe *last_pipe = NULL;
1150 last_pipe = stream->last_pipe;
1155 static inline struct ia_css_pipe *stream_get_copy_pipe(
1156 struct ia_css_stream *stream)
1158 struct ia_css_pipe *copy_pipe = NULL;
1159 struct ia_css_pipe *last_pipe = NULL;
1160 enum ia_css_pipe_id pipe_id;
1162 last_pipe = stream_get_last_pipe(stream);
1164 if ((stream != NULL) &&
1165 (last_pipe != NULL) &&
1166 (stream->config.continuous)) {
1168 pipe_id = last_pipe->mode;
1170 case IA_CSS_PIPE_ID_PREVIEW:
1171 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1173 case IA_CSS_PIPE_ID_VIDEO:
1174 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1185 static inline struct ia_css_pipe *stream_get_target_pipe(
1186 struct ia_css_stream *stream)
1188 struct ia_css_pipe *target_pipe;
1190 /* get the pipe that consumes the stream */
1191 if (stream->config.continuous) {
1192 target_pipe = stream_get_copy_pipe(stream);
1194 target_pipe = stream_get_last_pipe(stream);
1200 static enum ia_css_err stream_csi_rx_helper(
1201 struct ia_css_stream *stream,
1202 enum ia_css_err (*func)(enum ia_css_csi2_port, uint32_t))
1204 enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
1205 uint32_t sp_thread_id, stream_id;
1207 struct ia_css_pipe *target_pipe = NULL;
1209 if ((stream == NULL) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1212 target_pipe = stream_get_target_pipe(stream);
1214 if (target_pipe == NULL)
1217 rc = ia_css_pipeline_get_sp_thread_id(
1218 ia_css_pipe_get_pipe_num(target_pipe),
1224 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1227 if (stream->config.isys_config[stream_id].valid) {
1228 uint32_t isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1229 retval = func(stream->config.source.port.port, isys_stream_id);
1232 } while ((retval == IA_CSS_SUCCESS) &&
1233 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1239 static inline enum ia_css_err stream_register_with_csi_rx(
1240 struct ia_css_stream *stream)
1242 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1245 static inline enum ia_css_err stream_unregister_with_csi_rx(
1246 struct ia_css_stream *stream)
1248 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1252 #if WITH_PC_MONITORING
1253 static struct task_struct *my_kthread; /* Handle for the monitoring thread */
1254 static int sh_binary_running; /* Enable sampling in the thread */
1256 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1259 unsigned cnt_run = 0;
1260 unsigned cnt_stall = 0;
1265 sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1266 sh_css_print("%s PC\trun\tstall\n", core_name);
1268 for (i = 0; i < hist->length; i++) {
1269 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1271 sh_css_print("%s %d\t%d\t%d\n",
1272 core_name, i, hist->run[i], hist->stall[i]);
1273 cnt_run += hist->run[i];
1274 cnt_stall += hist->stall[i];
1277 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, "
1278 "hist->length = %d\n",
1279 core_name, cnt_run, cnt_stall, hist->length);
1282 static void print_pc_histogram(void)
1284 struct ia_css_binary_metrics *metrics;
1286 for (metrics = sh_css_metrics.binary_metrics;
1288 metrics = metrics->next) {
1289 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1290 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1291 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1296 sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1297 print_pc_histo(" ISP", &metrics->isp_histogram);
1298 print_pc_histo(" SP", &metrics->sp_histogram);
1299 sh_css_print("print_pc_histogram() done for binay->id = %d, "
1300 "done.\n", metrics->id);
1303 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1306 static int pc_monitoring(void *data)
1312 if (sh_binary_running) {
1313 sh_css_metrics_sample_pcs();
1314 #if MULTIPLE_SAMPLES
1315 for (i = 0; i < NOF_SAMPLES; i++)
1316 sh_css_metrics_sample_pcs();
1319 usleep_range(10, 50);
1324 static void spying_thread_create(void)
1326 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1327 sh_css_metrics_enable_pc_histogram(1);
1330 static void input_frame_info(struct ia_css_frame_info frame_info)
1332 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, "
1333 "frame->info.res.height = %d, format = %d\n",
1334 frame_info.res.width, frame_info.res.height, frame_info.format);
1336 #endif /* WITH_PC_MONITORING */
1339 start_binary(struct ia_css_pipe *pipe,
1340 struct ia_css_binary *binary)
1342 struct ia_css_stream *stream;
1344 assert(pipe != NULL);
1345 /* Acceleration uses firmware, the binary thus can be NULL */
1346 /* assert(binary != NULL); */
1350 #if !defined(HAS_NO_INPUT_SYSTEM)
1351 stream = pipe->stream;
1358 sh_css_metrics_start_binary(&binary->metrics);
1360 #if WITH_PC_MONITORING
1361 sh_css_print("PC_MONITORING: %s() -- binary id = %d , "
1362 "enable_dvs_envelope = %d\n",
1363 __func__, binary->info->sp.id,
1364 binary->info->sp.enable.dvs_envelope);
1365 input_frame_info(binary->in_frame_info);
1367 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1368 sh_binary_running = true;
1371 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1372 if (stream->reconfigure_css_rx) {
1373 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1374 pipe->stream->config.mode);
1375 stream->reconfigure_css_rx = false;
1380 /* start the copy function on the SP */
1381 static enum ia_css_err
1382 start_copy_on_sp(struct ia_css_pipe *pipe,
1383 struct ia_css_frame *out_frame)
1387 assert(pipe != NULL);
1388 assert(pipe->stream != NULL);
1390 if ((pipe == NULL) || (pipe->stream == NULL))
1391 return IA_CSS_ERR_INVALID_ARGUMENTS;
1393 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1394 if (pipe->stream->reconfigure_css_rx)
1395 ia_css_isys_rx_disable();
1398 if (pipe->stream->config.input_config.format != IA_CSS_STREAM_FORMAT_BINARY_8)
1399 return IA_CSS_ERR_INTERNAL_ERROR;
1400 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1402 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1403 if (pipe->stream->reconfigure_css_rx) {
1404 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode);
1405 pipe->stream->reconfigure_css_rx = false;
1409 return IA_CSS_SUCCESS;
1412 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1417 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++)
1419 for (i = 0; i < NUM_TNR_FRAMES; i++)
1421 args->tnr_frames[i] = NULL;
1422 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1423 args->delay_frames[i] = NULL;
1424 args->in_frame = NULL;
1425 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1426 args->out_frame[i] = NULL;
1427 args->out_vf_frame = NULL;
1428 args->copy_vf = false;
1429 args->copy_output = true;
1430 args->vf_downscale_log2 = 0;
1433 static void start_pipe(
1434 struct ia_css_pipe *me,
1435 enum sh_css_pipe_config_override copy_ovrd,
1436 enum ia_css_input_mode input_mode)
1438 #if defined(HAS_NO_INPUT_SYSTEM)
1442 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1443 me, copy_ovrd, input_mode);
1445 assert(me != NULL); /* all callers are in this file and call with non null argument */
1447 sh_css_sp_init_pipeline(&me->pipeline,
1449 (uint8_t)ia_css_pipe_get_pipe_num(me),
1450 me->config.default_capture_config.enable_xnr != 0,
1451 me->stream->config.pixels_per_clock == 2,
1452 me->stream->config.continuous,
1454 me->required_bds_factor,
1457 &me->stream->config.metadata_config,
1458 &me->stream->info.metadata_info
1459 #if !defined(HAS_NO_INPUT_SYSTEM)
1460 ,(input_mode==IA_CSS_INPUT_MODE_MEMORY) ?
1462 me->stream->config.source.port.port
1465 ,&me->config.internal_frame_origin_bqs_on_sctbl,
1466 me->stream->isp_params_configs
1470 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1471 struct ia_css_pipeline_stage *stage;
1472 stage = me->pipeline.stages;
1474 me->pipeline.current_stage = stage;
1475 start_binary(me, stage->binary);
1478 IA_CSS_LEAVE_PRIVATE("void");
1482 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1485 assert(stream != NULL);
1487 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1488 "sh_css_invalidate_shading_tables() enter:\n");
1490 for (i=0; i<stream->num_pipes; i++) {
1491 assert(stream->pipes[i] != NULL);
1492 sh_css_pipe_free_shading_table(stream->pipes[i]);
1495 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1496 "sh_css_invalidate_shading_tables() leave: return_void\n");
1501 enable_interrupts(enum ia_css_irq_type irq_type)
1503 #ifdef USE_INPUT_SYSTEM_VERSION_2
1504 mipi_port_ID_t port;
1506 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1507 IA_CSS_ENTER_PRIVATE("");
1508 /* Enable IRQ on the SP which signals that SP goes to idle
1509 * (aka ready state) */
1510 cnd_sp_irq_enable(SP0_ID, true);
1511 /* Set the IRQ device 0 to either level or pulse */
1512 irq_enable_pulse(IRQ0_ID, enable_pulse);
1514 cnd_virq_enable_channel(virq_sp, true);
1516 /* Enable SW interrupt 0, this is used to signal ISYS events */
1517 cnd_virq_enable_channel(
1518 (virq_id_t)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1520 /* Enable SW interrupt 1, this is used to signal PSYS events */
1521 cnd_virq_enable_channel(
1522 (virq_id_t)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1524 #if !defined(HAS_IRQ_MAP_VERSION_2)
1525 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1526 cnd_virq_enable_channel(
1527 (virq_id_t)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1532 #ifdef USE_INPUT_SYSTEM_VERSION_2
1533 for (port = 0; port < N_MIPI_PORT_ID; port++)
1534 ia_css_isys_rx_enable_all_interrupts(port);
1537 IA_CSS_LEAVE_PRIVATE("");
1542 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1543 const char * program,
1544 ia_css_spctrl_cfg *spctrl_cfg)
1546 if((fw == NULL)||(spctrl_cfg == NULL))
1548 spctrl_cfg->sp_entry = 0;
1549 spctrl_cfg->program_name = (char *)(program);
1551 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1552 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1553 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1554 spctrl_cfg->data_size = fw->blob.data_size ;
1555 spctrl_cfg->bss_size = fw->blob.bss_size;
1557 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1558 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1560 spctrl_cfg->code_size = fw->blob.size;
1561 spctrl_cfg->code = fw->blob.code;
1562 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1567 ia_css_unload_firmware(void)
1569 if (sh_css_num_binaries)
1571 /* we have already loaded before so get rid of the old stuff */
1572 ia_css_binary_uninit();
1573 sh_css_unload_firmware();
1575 fw_explicitly_loaded = false;
1579 ia_css_reset_defaults(struct sh_css* css)
1581 struct sh_css default_css;
1583 /* Reset everything to zero */
1584 memset(&default_css, 0, sizeof(default_css));
1586 /* Initialize the non zero values*/
1587 default_css.check_system_idle = true;
1588 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1590 /* All should be 0: but memset does it already.
1591 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1594 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1596 /*Set the defaults to the output */
1601 ia_css_check_firmware_version(const struct ia_css_fw *fw)
1603 bool retval = false;
1606 retval = sh_css_check_firmware_version(fw->data);
1612 ia_css_load_firmware(const struct ia_css_env *env,
1613 const struct ia_css_fw *fw)
1615 enum ia_css_err err;
1618 return IA_CSS_ERR_INVALID_ARGUMENTS;
1620 return IA_CSS_ERR_INVALID_ARGUMENTS;
1622 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1624 /* make sure we initialize my_css */
1625 if (my_css.flush != env->cpu_mem_env.flush) {
1626 ia_css_reset_defaults(&my_css);
1627 my_css.flush = env->cpu_mem_env.flush;
1630 ia_css_unload_firmware(); /* in case we are called twice */
1631 err = sh_css_load_firmware(fw->data, fw->bytes);
1632 if (err == IA_CSS_SUCCESS) {
1633 err = ia_css_binary_init_infos();
1634 if (err == IA_CSS_SUCCESS)
1635 fw_explicitly_loaded = true;
1638 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave \n");
1643 ia_css_init(const struct ia_css_env *env,
1644 const struct ia_css_fw *fw,
1645 uint32_t mmu_l1_base,
1646 enum ia_css_irq_type irq_type)
1648 enum ia_css_err err;
1649 ia_css_spctrl_cfg spctrl_cfg;
1651 void (*flush_func)(struct ia_css_acc_fw *fw);
1652 hrt_data select, enable;
1655 * The C99 standard does not specify the exact object representation of structs;
1656 * the representation is compiler dependent.
1658 * The structs that are communicated between host and SP/ISP should have the
1659 * exact same object representation. The compiler that is used to compile the
1660 * firmware is hivecc.
1662 * To check if a different compiler, used to compile a host application, uses
1663 * another object representation, macros are defined specifying the size of
1664 * the structs as expected by the firmware.
1666 * A host application shall verify that a sizeof( ) of the struct is equal to
1667 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1668 * equal, functionality will break.
1670 /* Check struct sh_css_ddr_address_map */
1671 COMPILATION_ERROR_IF( sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT );
1672 /* Check struct host_sp_queues */
1673 COMPILATION_ERROR_IF( sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT );
1674 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT );
1675 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT );
1677 /* Check struct host_sp_communication */
1678 COMPILATION_ERROR_IF( sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT );
1679 COMPILATION_ERROR_IF( sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT );
1681 /* Check struct sh_css_hmm_buffer */
1682 COMPILATION_ERROR_IF( sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT );
1683 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT );
1684 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT );
1685 COMPILATION_ERROR_IF( sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT );
1687 /* Check struct ia_css_init_dmem_cfg */
1688 COMPILATION_ERROR_IF( sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT );
1690 if (fw == NULL && !fw_explicitly_loaded)
1691 return IA_CSS_ERR_INVALID_ARGUMENTS;
1693 return IA_CSS_ERR_INVALID_ARGUMENTS;
1695 sh_css_printf = env->print_env.debug_print;
1697 IA_CSS_ENTER("void");
1699 flush_func = env->cpu_mem_env.flush;
1702 ia_css_pipeline_init();
1703 ia_css_queue_map_init();
1705 ia_css_device_access_init(&env->hw_access_env);
1707 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1708 & (~GPIO_FLASH_PIN_MASK);
1709 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1710 | GPIO_FLASH_PIN_MASK;
1711 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1713 my_css_save.mmu_base = mmu_l1_base;
1715 ia_css_save_mmu_base_addr(mmu_l1_base);
1718 ia_css_reset_defaults(&my_css);
1720 my_css_save.driver_env = *env;
1721 my_css.flush = flush_func;
1723 err = ia_css_rmgr_init();
1724 if (err != IA_CSS_SUCCESS) {
1725 IA_CSS_LEAVE_ERR(err);
1730 IA_CSS_LOG("init: %d", my_css_save_initialized);
1732 ia_css_save_restore_data_init();
1736 if (!my_css_save_initialized)
1738 my_css_save_initialized = true;
1739 my_css_save.mode = sh_css_mode_working;
1740 memset(my_css_save.stream_seeds, 0, sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1741 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1747 /* In case this has been programmed already, update internal
1748 data structure ... DEPRECATED */
1749 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1752 my_css.irq_type = irq_type;
1754 my_css_save.irq_type = irq_type;
1756 ia_css_save_irq_type(irq_type);
1758 enable_interrupts(my_css.irq_type);
1760 /* configure GPIO to output mode */
1761 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1762 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1763 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1765 err = ia_css_refcount_init(REFCOUNT_SIZE);
1766 if (err != IA_CSS_SUCCESS) {
1767 IA_CSS_LEAVE_ERR(err);
1770 err = sh_css_params_init();
1771 if (err != IA_CSS_SUCCESS) {
1772 IA_CSS_LEAVE_ERR(err);
1777 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1778 err = sh_css_load_firmware(fw->data, fw->bytes);
1779 if (err != IA_CSS_SUCCESS) {
1780 IA_CSS_LEAVE_ERR(err);
1783 err = ia_css_binary_init_infos();
1784 if (err != IA_CSS_SUCCESS) {
1785 IA_CSS_LEAVE_ERR(err);
1788 fw_explicitly_loaded = false;
1790 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1793 if(!sh_css_setup_spctrl_config(&sh_css_sp_fw,SP_PROG_NAME,&spctrl_cfg))
1794 return IA_CSS_ERR_INTERNAL_ERROR;
1796 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1797 if (err != IA_CSS_SUCCESS) {
1798 IA_CSS_LEAVE_ERR(err);
1802 #if WITH_PC_MONITORING
1803 if (!thread_alive) {
1805 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1807 spying_thread_create();
1810 if (!sh_css_hrt_system_is_idle()) {
1811 IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE);
1812 return IA_CSS_ERR_SYSTEM_NOT_IDLE;
1814 /* can be called here, queuing works, but:
1815 - when sp is started later, it will wipe queued items
1816 so for now we leave it for later and make sure
1817 updates are not called to frequently.
1818 sh_css_init_buffer_queues();
1821 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1822 #if defined(USE_INPUT_SYSTEM_VERSION_2)
1823 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1824 #elif defined (USE_INPUT_SYSTEM_VERSION_2401)
1825 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1829 #if !defined(HAS_NO_INPUT_SYSTEM)
1830 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1831 ISP_DMA_MAX_BURST_LENGTH);
1833 if(ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1834 err = IA_CSS_ERR_INVALID_ARGUMENTS;
1837 sh_css_params_map_and_store_default_gdc_lut();
1839 IA_CSS_LEAVE_ERR(err);
1843 enum ia_css_err ia_css_suspend(void)
1846 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() enter\n");
1847 my_css_save.mode = sh_css_mode_suspend;
1848 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1849 if (my_css_save.stream_seeds[i].stream != NULL)
1851 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> unloading seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1852 ia_css_stream_unload(my_css_save.stream_seeds[i].stream);
1854 my_css_save.mode = sh_css_mode_working;
1857 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1858 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> after 1: seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1859 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() leave\n");
1860 return IA_CSS_SUCCESS;
1867 enum ia_css_err err;
1868 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() enter: void\n");
1870 err = ia_css_init(&(my_css_save.driver_env), my_css_save.loaded_fw, my_css_save.mmu_base, my_css_save.irq_type);
1871 if (err != IA_CSS_SUCCESS)
1873 err = ia_css_start_sp();
1874 if (err != IA_CSS_SUCCESS)
1876 my_css_save.mode = sh_css_mode_resume;
1877 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1879 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> seed stream %p\n", my_css_save.stream_seeds[i].stream);
1880 if (my_css_save.stream_seeds[i].stream != NULL)
1882 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> loading seed %d\n", i);
1883 err = ia_css_stream_load(my_css_save.stream_seeds[i].stream);
1884 if (err != IA_CSS_SUCCESS)
1888 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1891 err = ia_css_stream_start(my_css_save.stream_seeds[i].stream);
1892 if (err != IA_CSS_SUCCESS)
1896 ia_css_stream_stop(my_css_save.stream_seeds[j].stream);
1897 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1901 *my_css_save.stream_seeds[i].orig_stream = my_css_save.stream_seeds[i].stream;
1902 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
1903 *(my_css_save.stream_seeds[i].orig_pipes[j]) = my_css_save.stream_seeds[i].pipes[j];
1906 my_css_save.mode = sh_css_mode_working;
1907 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() leave: return_void\n");
1908 return IA_CSS_SUCCESS;
1912 ia_css_enable_isys_event_queue(bool enable)
1914 if (sh_css_sp_is_running())
1915 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
1916 sh_css_sp_enable_isys_event_queue(enable);
1917 return IA_CSS_SUCCESS;
1920 void *sh_css_malloc(size_t size)
1922 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",size);
1923 /* FIXME: This first test can probably go away */
1926 if (size > PAGE_SIZE)
1927 return vmalloc(size);
1928 return kmalloc(size, GFP_KERNEL);
1931 void *sh_css_calloc(size_t N, size_t size)
1935 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%zu, size=%zu\n",N,size);
1937 /* FIXME: this test can probably go away */
1939 p = sh_css_malloc(N*size);
1947 void sh_css_free(void *ptr)
1949 if (is_vmalloc_addr(ptr))
1955 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1957 sh_css_flush(struct ia_css_acc_fw *fw)
1959 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1960 if ((fw != NULL) && (my_css.flush != NULL))
1964 /* Mapping sp threads. Currently, this is done when a stream is created and
1965 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1966 * doing it from stream_create since we could run out of sp threads due to
1967 * allocation on inactive pipelines. */
1968 static enum ia_css_err
1969 map_sp_threads(struct ia_css_stream *stream, bool map)
1971 struct ia_css_pipe *main_pipe = NULL;
1972 struct ia_css_pipe *copy_pipe = NULL;
1973 struct ia_css_pipe *capture_pipe = NULL;
1974 struct ia_css_pipe *acc_pipe = NULL;
1975 enum ia_css_err err = IA_CSS_SUCCESS;
1976 enum ia_css_pipe_id pipe_id;
1978 assert(stream != NULL);
1979 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1980 stream, map ? "true" : "false");
1982 if (stream == NULL) {
1983 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1984 return IA_CSS_ERR_INVALID_ARGUMENTS;
1987 main_pipe = stream->last_pipe;
1988 pipe_id = main_pipe->mode;
1990 ia_css_pipeline_map(main_pipe->pipe_num, map);
1993 case IA_CSS_PIPE_ID_PREVIEW:
1994 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1995 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1996 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1999 case IA_CSS_PIPE_ID_VIDEO:
2000 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2001 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2004 case IA_CSS_PIPE_ID_CAPTURE:
2005 case IA_CSS_PIPE_ID_ACC:
2011 ia_css_pipeline_map(acc_pipe->pipe_num, map);
2015 ia_css_pipeline_map(capture_pipe->pipe_num, map);
2018 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
2020 ia_css_pipeline_map(copy_pipe->pipe_num, map);
2022 /* DH regular multi pipe - not continuous mode: map the next pipes too */
2023 if (!stream->config.continuous) {
2025 for (i = 1; i < stream->num_pipes; i++)
2026 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
2029 IA_CSS_LEAVE_ERR_PRIVATE(err);
2033 /* creates a host pipeline skeleton for all pipes in a stream. Called during
2035 static enum ia_css_err
2036 create_host_pipeline_structure(struct ia_css_stream *stream)
2038 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2039 struct ia_css_pipe *acc_pipe = NULL;
2040 enum ia_css_pipe_id pipe_id;
2041 struct ia_css_pipe *main_pipe = NULL;
2042 enum ia_css_err err = IA_CSS_SUCCESS;
2043 unsigned int copy_pipe_delay = 0,
2044 capture_pipe_delay = 0;
2046 assert(stream != NULL);
2047 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2049 if (stream == NULL) {
2050 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2051 return IA_CSS_ERR_INVALID_ARGUMENTS;
2054 main_pipe = stream->last_pipe;
2055 assert(main_pipe != NULL);
2056 if (main_pipe == NULL) {
2057 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2058 return IA_CSS_ERR_INVALID_ARGUMENTS;
2061 pipe_id = main_pipe->mode;
2064 case IA_CSS_PIPE_ID_PREVIEW:
2065 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2066 copy_pipe_delay = main_pipe->dvs_frame_delay;
2067 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2068 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2069 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2070 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2073 case IA_CSS_PIPE_ID_VIDEO:
2074 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2075 copy_pipe_delay = main_pipe->dvs_frame_delay;
2076 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2077 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2078 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2081 case IA_CSS_PIPE_ID_CAPTURE:
2082 capture_pipe = main_pipe;
2083 capture_pipe_delay = main_pipe->dvs_frame_delay;
2086 case IA_CSS_PIPE_ID_YUVPP:
2087 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2088 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2091 case IA_CSS_PIPE_ID_ACC:
2092 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2096 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2099 if ((IA_CSS_SUCCESS == err) && copy_pipe) {
2100 err = ia_css_pipeline_create(©_pipe->pipeline,
2102 copy_pipe->pipe_num,
2106 if ((IA_CSS_SUCCESS == err) && capture_pipe) {
2107 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2109 capture_pipe->pipe_num,
2110 capture_pipe_delay);
2113 if ((IA_CSS_SUCCESS == err) && acc_pipe) {
2114 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2117 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2118 if (!stream->config.continuous) {
2120 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2121 main_pipe = stream->pipes[i];
2122 err = ia_css_pipeline_create(&main_pipe->pipeline,
2124 main_pipe->pipe_num,
2125 main_pipe->dvs_frame_delay);
2129 IA_CSS_LEAVE_ERR_PRIVATE(err);
2133 /* creates a host pipeline for all pipes in a stream. Called during
2135 static enum ia_css_err
2136 create_host_pipeline(struct ia_css_stream *stream)
2138 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2139 struct ia_css_pipe *acc_pipe = NULL;
2140 enum ia_css_pipe_id pipe_id;
2141 struct ia_css_pipe *main_pipe = NULL;
2142 enum ia_css_err err = IA_CSS_SUCCESS;
2143 unsigned max_input_width = 0;
2145 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2146 if (stream == NULL) {
2147 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2148 return IA_CSS_ERR_INVALID_ARGUMENTS;
2151 main_pipe = stream->last_pipe;
2152 pipe_id = main_pipe->mode;
2154 /* No continuous frame allocation for capture pipe. It uses the
2155 * "main" pipe's frames. */
2156 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2157 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
2158 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2159 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2160 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2161 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2162 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2164 if (stream->config.continuous ||
2165 (pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2166 err = alloc_continuous_frames(main_pipe, true);
2167 if (err != IA_CSS_SUCCESS)
2173 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2174 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2175 if (pipe_id != IA_CSS_PIPE_ID_ACC) {
2176 err = allocate_mipi_frames(main_pipe, &stream->info);
2177 if (err != IA_CSS_SUCCESS)
2180 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2181 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2182 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
2183 err = allocate_mipi_frames(main_pipe, &stream->info);
2184 if (err != IA_CSS_SUCCESS)
2190 case IA_CSS_PIPE_ID_PREVIEW:
2191 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2192 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2193 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2195 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2197 err = create_host_preview_pipeline(main_pipe);
2198 if (err != IA_CSS_SUCCESS)
2203 case IA_CSS_PIPE_ID_VIDEO:
2204 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2205 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2207 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2209 err = create_host_video_pipeline(main_pipe);
2210 if (err != IA_CSS_SUCCESS)
2215 case IA_CSS_PIPE_ID_CAPTURE:
2216 capture_pipe = main_pipe;
2220 case IA_CSS_PIPE_ID_YUVPP:
2221 err = create_host_yuvpp_pipeline(main_pipe);
2222 if (err != IA_CSS_SUCCESS)
2227 case IA_CSS_PIPE_ID_ACC:
2228 err = create_host_acc_pipeline(main_pipe);
2229 if (err != IA_CSS_SUCCESS)
2234 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2236 if (err != IA_CSS_SUCCESS)
2240 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2241 main_pipe->continuous_frames[0]);
2242 if (err != IA_CSS_SUCCESS)
2247 err = create_host_capture_pipeline(capture_pipe);
2248 if (err != IA_CSS_SUCCESS)
2253 err = create_host_acc_pipeline(acc_pipe);
2254 if (err != IA_CSS_SUCCESS)
2258 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2259 if (!stream->config.continuous) {
2261 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2262 switch (stream->pipes[i]->mode) {
2263 case IA_CSS_PIPE_ID_PREVIEW:
2264 err = create_host_preview_pipeline(stream->pipes[i]);
2266 case IA_CSS_PIPE_ID_VIDEO:
2267 err = create_host_video_pipeline(stream->pipes[i]);
2269 case IA_CSS_PIPE_ID_CAPTURE:
2270 err = create_host_capture_pipeline(stream->pipes[i]);
2272 case IA_CSS_PIPE_ID_YUVPP:
2273 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2275 case IA_CSS_PIPE_ID_ACC:
2276 err = create_host_acc_pipeline(stream->pipes[i]);
2279 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2281 if (err != IA_CSS_SUCCESS)
2287 IA_CSS_LEAVE_ERR_PRIVATE(err);
2291 static enum ia_css_err
2292 init_pipe_defaults(enum ia_css_pipe_mode mode,
2293 struct ia_css_pipe *pipe,
2296 static struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
2297 static struct ia_css_preview_settings prev = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2298 static struct ia_css_capture_settings capt = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2299 static struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2300 static struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2303 IA_CSS_ERROR("NULL pipe parameter");
2304 return IA_CSS_ERR_INVALID_ARGUMENTS;
2307 /* Initialize pipe to pre-defined defaults */
2308 *pipe = default_pipe;
2310 /* TODO: JB should not be needed, but temporary backward reference */
2312 case IA_CSS_PIPE_MODE_PREVIEW:
2313 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2314 pipe->pipe_settings.preview = prev;
2316 case IA_CSS_PIPE_MODE_CAPTURE:
2318 pipe->mode = IA_CSS_PIPE_ID_COPY;
2320 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2322 pipe->pipe_settings.capture = capt;
2324 case IA_CSS_PIPE_MODE_VIDEO:
2325 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2326 pipe->pipe_settings.video = video;
2328 case IA_CSS_PIPE_MODE_ACC:
2329 pipe->mode = IA_CSS_PIPE_ID_ACC;
2331 case IA_CSS_PIPE_MODE_COPY:
2332 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2334 case IA_CSS_PIPE_MODE_YUVPP:
2335 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2336 pipe->pipe_settings.yuvpp = yuvpp;
2339 return IA_CSS_ERR_INVALID_ARGUMENTS;
2342 return IA_CSS_SUCCESS;
2346 pipe_global_init(void)
2350 my_css.pipe_counter = 0;
2351 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2352 my_css.all_pipes[i] = NULL;
2356 static enum ia_css_err
2357 pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number)
2359 const uint8_t INVALID_PIPE_NUM = (uint8_t)~(0);
2360 uint8_t pipe_num = INVALID_PIPE_NUM;
2364 IA_CSS_ERROR("NULL pipe parameter");
2365 return IA_CSS_ERR_INVALID_ARGUMENTS;
2368 /* Assign a new pipe_num .... search for empty place */
2369 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2370 if (my_css.all_pipes[i] == NULL) {
2371 /*position is reserved */
2372 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2377 if (pipe_num == INVALID_PIPE_NUM) {
2378 /* Max number of pipes already allocated */
2379 IA_CSS_ERROR("Max number of pipes already created");
2380 return IA_CSS_ERR_RESOURCE_EXHAUSTED;
2383 my_css.pipe_counter++;
2385 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2387 *pipe_number = pipe_num;
2388 return IA_CSS_SUCCESS;
2392 pipe_release_pipe_num(unsigned int pipe_num)
2394 my_css.all_pipes[pipe_num] = NULL;
2395 my_css.pipe_counter--;
2396 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2397 "pipe_release_pipe_num (%d)\n", pipe_num);
2400 static enum ia_css_err
2401 create_pipe(enum ia_css_pipe_mode mode,
2402 struct ia_css_pipe **pipe,
2405 enum ia_css_err err = IA_CSS_SUCCESS;
2406 struct ia_css_pipe *me;
2409 IA_CSS_ERROR("NULL pipe parameter");
2410 return IA_CSS_ERR_INVALID_ARGUMENTS;
2413 me = kmalloc(sizeof(*me), GFP_KERNEL);
2415 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
2417 err = init_pipe_defaults(mode, me, copy_pipe);
2418 if (err != IA_CSS_SUCCESS) {
2423 err = pipe_generate_pipe_num(me, &(me->pipe_num));
2424 if (err != IA_CSS_SUCCESS) {
2430 return IA_CSS_SUCCESS;
2433 struct ia_css_pipe *
2434 find_pipe_by_num(uint32_t pipe_num)
2437 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++){
2438 if (my_css.all_pipes[i] &&
2439 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2440 return my_css.all_pipes[i];
2446 static void sh_css_pipe_free_acc_binaries (
2447 struct ia_css_pipe *pipe)
2449 struct ia_css_pipeline *pipeline;
2450 struct ia_css_pipeline_stage *stage;
2452 assert(pipe != NULL);
2454 IA_CSS_ERROR("NULL input pointer");
2457 pipeline = &pipe->pipeline;
2459 /* loop through the stages and unload them */
2460 for (stage = pipeline->stages; stage; stage = stage->next) {
2461 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2464 ia_css_pipe_unload_extension(pipe, firmware);
2469 ia_css_pipe_destroy(struct ia_css_pipe *pipe)
2471 enum ia_css_err err = IA_CSS_SUCCESS;
2472 IA_CSS_ENTER("pipe = %p", pipe);
2475 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2476 return IA_CSS_ERR_INVALID_ARGUMENTS;
2479 if (pipe->stream != NULL) {
2480 IA_CSS_LOG("ia_css_stream_destroy not called!");
2481 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2482 return IA_CSS_ERR_INVALID_ARGUMENTS;
2485 switch (pipe->config.mode) {
2486 case IA_CSS_PIPE_MODE_PREVIEW:
2487 /* need to take into account that this function is also called
2488 on the internal copy pipe */
2489 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2490 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2491 pipe->continuous_frames);
2492 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2493 pipe->cont_md_buffers);
2494 if (pipe->pipe_settings.preview.copy_pipe) {
2495 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2496 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2497 "destroyed internal copy pipe err=%d\n", err);
2501 case IA_CSS_PIPE_MODE_VIDEO:
2502 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2503 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2504 pipe->continuous_frames);
2505 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2506 pipe->cont_md_buffers);
2507 if (pipe->pipe_settings.video.copy_pipe) {
2508 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2509 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2510 "destroyed internal copy pipe err=%d\n", err);
2514 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2516 ia_css_frame_free_multiple(NUM_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2518 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames);
2520 case IA_CSS_PIPE_MODE_CAPTURE:
2521 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.capture.delay_frames);
2523 case IA_CSS_PIPE_MODE_ACC:
2524 sh_css_pipe_free_acc_binaries(pipe);
2526 case IA_CSS_PIPE_MODE_COPY:
2528 case IA_CSS_PIPE_MODE_YUVPP:
2532 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2533 pipe->scaler_pp_lut = mmgr_NULL;
2535 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2536 sh_css_pipe_free_shading_table(pipe);
2538 ia_css_pipeline_destroy(&pipe->pipeline);
2539 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2541 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2542 if (pipe->config.acc_extension) {
2543 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2546 IA_CSS_LEAVE("err = %d", err);
2553 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2554 #if WITH_PC_MONITORING
2555 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2556 print_pc_histogram();
2559 sh_css_params_free_default_gdc_lut();
2562 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2563 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2564 /* cleanup generic data */
2565 sh_css_params_uninit();
2566 ia_css_refcount_uninit();
2568 ia_css_rmgr_uninit();
2570 #if !defined(HAS_NO_INPUT_FORMATTER)
2571 /* needed for reprogramming the inputformatter after power cycle of css */
2572 ifmtr_set_if_blocking_mode_reset = true;
2575 if (fw_explicitly_loaded == false) {
2576 ia_css_unload_firmware();
2578 ia_css_spctrl_unload_fw(SP0_ID);
2579 sh_css_sp_set_sp_running(false);
2580 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2581 /* check and free any remaining mipi frames */
2582 free_mipi_frames(NULL);
2585 sh_css_sp_reset_global_vars();
2587 #if !defined(HAS_NO_INPUT_SYSTEM)
2588 ia_css_isys_uninit();
2591 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2594 #if defined(HAS_IRQ_MAP_VERSION_2)
2595 enum ia_css_err ia_css_irq_translate(
2596 unsigned int *irq_infos)
2599 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2600 unsigned int infos = 0;
2602 /* irq_infos can be NULL, but that would make the function useless */
2603 /* assert(irq_infos != NULL); */
2604 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() enter: irq_infos=%p\n",irq_infos);
2606 while (status == hrt_isp_css_irq_status_more_irqs) {
2607 status = virq_get_channel_id(&irq);
2608 if (status == hrt_isp_css_irq_status_error)
2609 return IA_CSS_ERR_INTERNAL_ERROR;
2611 #if WITH_PC_MONITORING
2612 sh_css_print("PC_MONITORING: %s() irq = %d, "
2613 "sh_binary_running set to 0\n", __func__, irq);
2614 sh_binary_running = 0 ;
2619 /* When SP goes to idle, info is available in the
2621 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2625 #if !defined(HAS_NO_INPUT_SYSTEM)
2627 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2630 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2633 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2636 #if !defined(HAS_NO_INPUT_FORMATTER)
2638 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2642 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2645 infos |= sh_css_get_sw_interrupt_value(0);
2648 infos |= sh_css_get_sw_interrupt_value(1);
2649 /* pqiao TODO: also assumption here */
2659 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() "
2660 "leave: irq_infos=%u\n", infos);
2662 return IA_CSS_SUCCESS;
2665 enum ia_css_err ia_css_irq_enable(
2666 enum ia_css_irq_info info,
2669 virq_id_t irq = N_virq_id;
2670 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2673 #if !defined(HAS_NO_INPUT_FORMATTER)
2674 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2675 irq = virq_isys_sof;
2677 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2678 irq = virq_isys_eof;
2680 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2681 irq = virq_isys_csi;
2684 #if !defined(HAS_NO_INPUT_FORMATTER)
2685 case IA_CSS_IRQ_INFO_IF_ERROR:
2686 irq = virq_ifmt0_id;
2689 case IA_CSS_IRQ_INFO_DMA_ERROR:
2692 case IA_CSS_IRQ_INFO_SW_0:
2693 irq = virq_sw_pin_0;
2695 case IA_CSS_IRQ_INFO_SW_1:
2696 irq = virq_sw_pin_1;
2699 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2700 return IA_CSS_ERR_INVALID_ARGUMENTS;
2703 cnd_virq_enable_channel(irq, enable);
2705 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS);
2706 return IA_CSS_SUCCESS;
2710 #error "sh_css.c: IRQ MAP must be one of \
2711 {IRQ_MAP_VERSION_2}"
2715 sh_css_get_sw_interrupt_value(unsigned int irq)
2717 unsigned int irq_value;
2718 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() enter: irq=%d\n",irq);
2719 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2720 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n",irq_value);
2724 /* configure and load the copy binary, the next binary is used to
2725 determine whether the copy binary needs to do left padding. */
2726 static enum ia_css_err load_copy_binary(
2727 struct ia_css_pipe *pipe,
2728 struct ia_css_binary *copy_binary,
2729 struct ia_css_binary *next_binary)
2731 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2732 unsigned int left_padding;
2733 enum ia_css_err err;
2734 struct ia_css_binary_descr copy_descr;
2736 /* next_binary can be NULL */
2737 assert(pipe != NULL);
2738 assert(copy_binary != NULL);
2739 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2740 "load_copy_binary() enter:\n");
2742 if (next_binary != NULL) {
2743 copy_out_info = next_binary->in_frame_info;
2744 left_padding = next_binary->left_padding;
2746 copy_out_info = pipe->output_info[0];
2747 copy_vf_info = pipe->vf_output_info[0];
2748 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2752 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2753 ©_in_info, ©_out_info, (next_binary != NULL) ? NULL : NULL/*TODO: ©_vf_info*/);
2754 err = ia_css_binary_find(©_descr, copy_binary);
2755 if (err != IA_CSS_SUCCESS)
2757 copy_binary->left_padding = left_padding;
2758 return IA_CSS_SUCCESS;
2761 static enum ia_css_err
2762 alloc_continuous_frames(
2763 struct ia_css_pipe *pipe, bool init_time)
2765 enum ia_css_err err = IA_CSS_SUCCESS;
2766 struct ia_css_frame_info ref_info;
2767 enum ia_css_pipe_id pipe_id;
2769 unsigned int i, idx;
2770 unsigned int num_frames;
2771 struct ia_css_pipe *capture_pipe = NULL;
2773 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2775 if ((pipe == NULL) || (pipe->stream == NULL)) {
2776 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2777 return IA_CSS_ERR_INVALID_ARGUMENTS;
2780 pipe_id = pipe->mode;
2781 continuous = pipe->stream->config.continuous;
2785 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2786 pipe->stream->continuous_pipe = pipe;
2788 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2790 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2793 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2794 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2795 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2796 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2799 /* should not happen */
2800 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2801 return IA_CSS_ERR_INTERNAL_ERROR;
2804 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2805 /* For CSI2+, the continuous frame will hold the full input frame */
2806 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2807 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2809 /* Ensure padded width is aligned for 2401 */
2810 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2813 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2814 if (pipe->stream->config.pack_raw_pixels) {
2815 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2816 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2817 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2822 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2823 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2826 /* Write format back to binary */
2827 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2828 pipe->pipe_settings.preview.preview_binary.in_frame_info.format = ref_info.format;
2829 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2830 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2831 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2832 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2834 /* should not happen */
2835 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2836 return IA_CSS_ERR_INTERNAL_ERROR;
2842 idx = pipe->stream->config.init_num_cont_raw_buf;
2844 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
2845 /* free previous frame */
2846 if (pipe->continuous_frames[i]) {
2847 ia_css_frame_free(pipe->continuous_frames[i]);
2848 pipe->continuous_frames[i] = NULL;
2850 /* free previous metadata buffer */
2851 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2852 pipe->cont_md_buffers[i] = NULL;
2854 /* check if new frame needed */
2855 if (i < num_frames) {
2856 /* allocate new frame */
2857 err = ia_css_frame_allocate_from_info(
2858 &pipe->continuous_frames[i],
2860 if (err != IA_CSS_SUCCESS) {
2861 IA_CSS_LEAVE_ERR_PRIVATE(err);
2864 /* allocate metadata buffer */
2865 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2866 &pipe->stream->info.metadata_info);
2869 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
2870 return IA_CSS_SUCCESS;
2874 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
2877 return IA_CSS_ERR_INVALID_ARGUMENTS;
2878 return alloc_continuous_frames(stream->continuous_pipe, false);
2881 static enum ia_css_err
2882 load_preview_binaries(struct ia_css_pipe *pipe)
2884 struct ia_css_frame_info prev_in_info,
2888 struct ia_css_binary_descr preview_descr;
2890 enum ia_css_err err = IA_CSS_SUCCESS;
2891 bool continuous, need_vf_pp = false;
2892 bool need_isp_copy_binary = false;
2893 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2894 bool sensor = false;
2896 /* preview only have 1 output pin now */
2897 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2898 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2900 IA_CSS_ENTER_PRIVATE("");
2901 assert(pipe != NULL);
2902 assert(pipe->stream != NULL);
2903 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2905 online = pipe->stream->config.online;
2906 continuous = pipe->stream->config.continuous;
2907 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2908 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2911 if (mycs->preview_binary.info)
2912 return IA_CSS_SUCCESS;
2914 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2915 if (err != IA_CSS_SUCCESS)
2917 err = ia_css_frame_check_info(pipe_out_info);
2918 if (err != IA_CSS_SUCCESS)
2921 /* Note: the current selection of vf_pp binary and
2922 * parameterization of the preview binary contains a few pieces
2923 * of hardcoded knowledge. This needs to be cleaned up such that
2924 * the binary selection becomes more generic.
2925 * The vf_pp binary is needed if one or more of the following features
2927 * 1. YUV downscaling.
2929 * 3. An output format that is not supported by the preview binary.
2930 * In practice this means something other than yuv_line or nv12.
2931 * The decision if the vf_pp binary is needed for YUV downscaling is
2932 * made after the preview binary selection, since some preview binaries
2933 * can perform the requested YUV downscaling.
2935 need_vf_pp = pipe->config.enable_dz;
2936 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2937 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2938 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2939 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2941 /* Preview step 1 */
2942 if (pipe->vf_yuv_ds_input_info.res.width)
2943 prev_vf_info = pipe->vf_yuv_ds_input_info;
2945 prev_vf_info = *pipe_out_info;
2946 /* If vf_pp is needed, then preview must output yuv_line.
2947 * The exception is when vf_pp is manually disabled, that is only
2948 * used in combination with a pipeline extension that requires
2949 * yuv_line as input.
2952 ia_css_frame_info_set_format(&prev_vf_info,
2953 IA_CSS_FRAME_FORMAT_YUV_LINE);
2955 err = ia_css_pipe_get_preview_binarydesc(
2962 if (err != IA_CSS_SUCCESS)
2964 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2965 if (err != IA_CSS_SUCCESS)
2969 /* The delay latency determines the number of invalid frames after
2970 * a stream is started. */
2971 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2972 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2974 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2975 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2976 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2979 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2980 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2981 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2983 /* When vf_pp is needed, then the output format of the selected
2984 * preview binary must be yuv_line. If this is not the case,
2985 * then the preview binary selection is done again.
2988 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
2990 /* Preview step 2 */
2991 if (pipe->vf_yuv_ds_input_info.res.width)
2992 prev_vf_info = pipe->vf_yuv_ds_input_info;
2994 prev_vf_info = *pipe_out_info;
2996 ia_css_frame_info_set_format(&prev_vf_info,
2997 IA_CSS_FRAME_FORMAT_YUV_LINE);
2999 err = ia_css_pipe_get_preview_binarydesc(
3006 if (err != IA_CSS_SUCCESS)
3008 err = ia_css_binary_find(&preview_descr,
3009 &mycs->preview_binary);
3010 if (err != IA_CSS_SUCCESS)
3015 struct ia_css_binary_descr vf_pp_descr;
3017 /* Viewfinder post-processing */
3018 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
3019 &mycs->preview_binary.out_frame_info[0],
3021 err = ia_css_binary_find(&vf_pp_descr,
3022 &mycs->vf_pp_binary);
3023 if (err != IA_CSS_SUCCESS)
3027 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3028 /* When the input system is 2401, only the Direct Sensor Mode
3029 * Offline Preview uses the ISP copy binary.
3031 need_isp_copy_binary = !online && sensor;
3034 need_isp_copy_binary = !online && !continuous;
3036 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3037 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3038 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3039 * copies sensor data to DDR) does not have much use.
3041 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3046 if (need_isp_copy_binary) {
3047 err = load_copy_binary(pipe,
3049 &mycs->preview_binary);
3050 if (err != IA_CSS_SUCCESS)
3054 if (pipe->shading_table) {
3055 ia_css_shading_table_free(pipe->shading_table);
3056 pipe->shading_table = NULL;
3059 return IA_CSS_SUCCESS;
3063 ia_css_binary_unload(struct ia_css_binary *binary)
3065 ia_css_binary_destroy_isp_parameters(binary);
3068 static enum ia_css_err
3069 unload_preview_binaries(struct ia_css_pipe *pipe)
3071 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3073 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3074 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3075 return IA_CSS_ERR_INVALID_ARGUMENTS;
3077 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3078 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3079 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3081 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
3082 return IA_CSS_SUCCESS;
3085 static const struct ia_css_fw_info *last_output_firmware(
3086 const struct ia_css_fw_info *fw)
3088 const struct ia_css_fw_info *last_fw = NULL;
3089 /* fw can be NULL */
3090 IA_CSS_ENTER_LEAVE_PRIVATE("");
3092 for (; fw; fw = fw->next) {
3093 const struct ia_css_fw_info *info = fw;
3094 if (info->info.isp.sp.enable.output)
3100 static enum ia_css_err add_firmwares(
3101 struct ia_css_pipeline *me,
3102 struct ia_css_binary *binary,
3103 const struct ia_css_fw_info *fw,
3104 const struct ia_css_fw_info *last_fw,
3105 unsigned int binary_mode,
3106 struct ia_css_frame *in_frame,
3107 struct ia_css_frame *out_frame,
3108 struct ia_css_frame *vf_frame,
3109 struct ia_css_pipeline_stage **my_stage,
3110 struct ia_css_pipeline_stage **vf_stage)
3112 enum ia_css_err err = IA_CSS_SUCCESS;
3113 struct ia_css_pipeline_stage *extra_stage = NULL;
3114 struct ia_css_pipeline_stage_desc stage_desc;
3116 /* all args can be NULL ??? */
3117 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3118 "add_firmwares() enter:\n");
3120 for (; fw; fw = fw->next) {
3121 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3122 struct ia_css_frame *in = NULL;
3123 struct ia_css_frame *vf = NULL;
3124 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3127 if (fw->info.isp.sp.enable.in_frame != 0) {
3130 if (fw->info.isp.sp.enable.out_frame != 0) {
3133 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3134 out, in, vf, fw, binary_mode);
3135 err = ia_css_pipeline_create_and_add_stage(me,
3138 if (err != IA_CSS_SUCCESS)
3140 if (fw->info.isp.sp.enable.output != 0)
3141 in_frame = extra_stage->args.out_frame[0];
3142 if (my_stage && !*my_stage && extra_stage)
3143 *my_stage = extra_stage;
3144 if (vf_stage && !*vf_stage && extra_stage &&
3145 fw->info.isp.sp.enable.vf_veceven)
3146 *vf_stage = extra_stage;
3151 static enum ia_css_err add_vf_pp_stage(
3152 struct ia_css_pipe *pipe,
3153 struct ia_css_frame *in_frame,
3154 struct ia_css_frame *out_frame,
3155 struct ia_css_binary *vf_pp_binary,
3156 struct ia_css_pipeline_stage **vf_pp_stage)
3159 struct ia_css_pipeline *me = NULL;
3160 const struct ia_css_fw_info *last_fw = NULL;
3161 enum ia_css_err err = IA_CSS_SUCCESS;
3162 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3163 struct ia_css_pipeline_stage_desc stage_desc;
3165 /* out_frame can be NULL ??? */
3168 return IA_CSS_ERR_INVALID_ARGUMENTS;
3169 if (in_frame == NULL)
3170 return IA_CSS_ERR_INVALID_ARGUMENTS;
3171 if (vf_pp_binary == NULL)
3172 return IA_CSS_ERR_INVALID_ARGUMENTS;
3173 if (vf_pp_stage == NULL)
3174 return IA_CSS_ERR_INVALID_ARGUMENTS;
3176 ia_css_pipe_util_create_output_frames(out_frames);
3177 me = &pipe->pipeline;
3179 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3180 "add_vf_pp_stage() enter:\n");
3182 *vf_pp_stage = NULL;
3184 last_fw = last_output_firmware(pipe->vf_stage);
3185 if (!pipe->extra_config.disable_vf_pp) {
3187 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3188 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3189 out_frames, in_frame, NULL);
3191 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3192 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3193 out_frames, in_frame, NULL);
3195 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3196 if (err != IA_CSS_SUCCESS)
3198 in_frame = (*vf_pp_stage)->args.out_frame[0];
3200 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3201 IA_CSS_BINARY_MODE_VF_PP,
3202 in_frame, out_frame, NULL,
3207 static enum ia_css_err add_yuv_scaler_stage(
3208 struct ia_css_pipe *pipe,
3209 struct ia_css_pipeline *me,
3210 struct ia_css_frame *in_frame,
3211 struct ia_css_frame *out_frame,
3212 struct ia_css_frame *internal_out_frame,
3213 struct ia_css_binary *yuv_scaler_binary,
3214 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3216 const struct ia_css_fw_info *last_fw;
3217 enum ia_css_err err = IA_CSS_SUCCESS;
3218 struct ia_css_frame *vf_frame = NULL;
3219 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3220 struct ia_css_pipeline_stage_desc stage_desc;
3222 /* out_frame can be NULL ??? */
3223 assert(in_frame != NULL);
3224 assert(pipe != NULL);
3226 assert(yuv_scaler_binary != NULL);
3227 assert(pre_vf_pp_stage != NULL);
3228 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3229 "add_yuv_scaler_stage() enter:\n");
3231 *pre_vf_pp_stage = NULL;
3232 ia_css_pipe_util_create_output_frames(out_frames);
3234 last_fw = last_output_firmware(pipe->output_stage);
3237 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3238 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3239 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3241 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3242 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3243 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3244 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3246 err = ia_css_pipeline_create_and_add_stage(me,
3249 if (err != IA_CSS_SUCCESS)
3251 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3253 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3254 IA_CSS_BINARY_MODE_CAPTURE_PP,
3255 in_frame, out_frame, vf_frame,
3256 NULL, pre_vf_pp_stage);
3257 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3258 (*pre_vf_pp_stage)->args.vf_downscale_log2 = yuv_scaler_binary->vf_downscale_log2;
3260 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3261 "add_yuv_scaler_stage() leave:\n");
3265 static enum ia_css_err add_capture_pp_stage(
3266 struct ia_css_pipe *pipe,
3267 struct ia_css_pipeline *me,
3268 struct ia_css_frame *in_frame,
3269 struct ia_css_frame *out_frame,
3270 struct ia_css_binary *capture_pp_binary,
3271 struct ia_css_pipeline_stage **capture_pp_stage)
3273 const struct ia_css_fw_info *last_fw = NULL;
3274 enum ia_css_err err = IA_CSS_SUCCESS;
3275 struct ia_css_frame *vf_frame = NULL;
3276 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3277 struct ia_css_pipeline_stage_desc stage_desc;
3279 /* out_frame can be NULL ??? */
3280 assert(in_frame != NULL);
3281 assert(pipe != NULL);
3283 assert(capture_pp_binary != NULL);
3284 assert(capture_pp_stage != NULL);
3285 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3286 "add_capture_pp_stage() enter:\n");
3288 *capture_pp_stage = NULL;
3289 ia_css_pipe_util_create_output_frames(out_frames);
3291 last_fw = last_output_firmware(pipe->output_stage);
3292 err = ia_css_frame_allocate_from_info(&vf_frame,
3293 &capture_pp_binary->vf_frame_info);
3294 if (err != IA_CSS_SUCCESS)
3297 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3298 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3299 capture_pp_binary, out_frames, NULL, vf_frame);
3301 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3302 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3303 capture_pp_binary, out_frames, NULL, vf_frame);
3305 err = ia_css_pipeline_create_and_add_stage(me,
3308 if (err != IA_CSS_SUCCESS)
3310 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3311 IA_CSS_BINARY_MODE_CAPTURE_PP,
3312 in_frame, out_frame, vf_frame,
3313 NULL, capture_pp_stage);
3314 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3315 if (*capture_pp_stage) {
3316 (*capture_pp_stage)->args.vf_downscale_log2 =
3317 capture_pp_binary->vf_downscale_log2;
3322 static void sh_css_setup_queues(void)
3324 const struct ia_css_fw_info *fw;
3325 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3327 sh_css_hmm_buffer_record_init();
3329 sh_css_event_init_irq_mask();
3332 HIVE_ADDR_host_sp_queues_initialized =
3333 fw->info.sp.host_sp_queues_initialized;
3337 /* set "host_sp_queues_initialized" to "true" */
3338 sp_dmem_store_uint32(SP0_ID,
3339 (unsigned int)sp_address_of(host_sp_queues_initialized),
3341 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3344 static enum ia_css_err
3345 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3346 struct ia_css_frame *vf_frame, unsigned int idx)
3348 enum ia_css_err err = IA_CSS_SUCCESS;
3349 unsigned int thread_id;
3350 enum sh_css_queue_id queue_id;
3352 assert(vf_frame != NULL);
3354 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3355 vf_frame->contiguous = false;
3356 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3357 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3358 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3359 vf_frame->dynamic_queue_id = queue_id;
3360 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3362 err = ia_css_frame_init_planes(vf_frame);
3366 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3368 get_crop_lines_for_bayer_order (
3369 const struct ia_css_stream_config *config)
3371 assert(config != NULL);
3372 if ((IA_CSS_BAYER_ORDER_BGGR == config->input_config.bayer_order)
3373 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3380 get_crop_columns_for_bayer_order (
3381 const struct ia_css_stream_config *config)
3383 assert(config != NULL);
3384 if ((IA_CSS_BAYER_ORDER_RGGB == config->input_config.bayer_order)
3385 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3391 /* This function is to get the sum of all extra pixels in addition to the effective
3392 * input, it includes dvs envelop and filter run-in */
3393 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3394 unsigned int *extra_row, unsigned int *extra_column)
3396 enum ia_css_pipe_id pipe_id = pipe->mode;
3397 unsigned int left_cropping = 0, top_cropping = 0;
3399 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3401 /* The dvs envelope info may not be correctly sent down via pipe config
3402 * The check is made and the correct value is populated in the binary info
3403 * Use this value when computing crop, else excess lines may get trimmed
3406 case IA_CSS_PIPE_ID_PREVIEW:
3407 if (pipe->pipe_settings.preview.preview_binary.info) {
3408 left_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3409 top_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3411 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3413 case IA_CSS_PIPE_ID_VIDEO:
3414 if (pipe->pipe_settings.video.video_binary.info) {
3415 left_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3416 top_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3418 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3420 case IA_CSS_PIPE_ID_CAPTURE:
3421 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3422 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3423 left_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3424 top_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3426 dvs_env.width += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3427 dvs_env.height += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3434 *extra_row = top_cropping + dvs_env.height;
3435 *extra_column = left_cropping + dvs_env.width;
3439 ia_css_get_crop_offsets (
3440 struct ia_css_pipe *pipe,
3441 struct ia_css_frame_info *in_frame)
3443 unsigned int row = 0;
3444 unsigned int column = 0;
3445 struct ia_css_resolution *input_res;
3446 struct ia_css_resolution *effective_res;
3447 unsigned int extra_row = 0, extra_col = 0;
3448 unsigned int min_reqd_height, min_reqd_width;
3450 assert(pipe != NULL);
3451 assert(pipe->stream != NULL);
3452 assert(in_frame != NULL);
3454 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3455 pipe, pipe->config.input_effective_res.width,
3456 pipe->config.input_effective_res.height);
3458 input_res = &pipe->stream->config.input_config.input_res;
3460 effective_res = &pipe->stream->config.input_config.effective_res;
3462 effective_res = &pipe->config.input_effective_res;
3465 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3467 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3469 min_reqd_height = effective_res->height + extra_row;
3470 min_reqd_width = effective_res->width + extra_col;
3472 if (input_res->height > min_reqd_height) {
3473 row = (input_res->height - min_reqd_height) / 2;
3476 if (input_res->width > min_reqd_width) {
3477 column = (input_res->width - min_reqd_width) / 2;
3483 * 1. Require the special support for RAW10 packed mode.
3484 * 2. Require the special support for the online use cases.
3487 /* ISP expects GRBG bayer order, we skip one line and/or one row
3488 * to correct in case the input bayer order is different.
3490 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3491 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3493 in_frame->crop_info.start_column = column;
3494 in_frame->crop_info.start_line = row;
3496 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3502 static enum ia_css_err
3503 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3504 struct ia_css_frame *frame, enum ia_css_frame_format format)
3506 struct ia_css_frame *in_frame;
3507 enum ia_css_err err = IA_CSS_SUCCESS;
3508 unsigned int thread_id;
3509 enum sh_css_queue_id queue_id;
3511 assert(frame != NULL);
3514 in_frame->info.format = format;
3516 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3517 if (format == IA_CSS_FRAME_FORMAT_RAW)
3518 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3519 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3523 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3524 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3525 in_frame->info.raw_bit_depth =
3526 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3527 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3528 in_frame->contiguous = false;
3529 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3530 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3531 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3532 in_frame->dynamic_queue_id = queue_id;
3533 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3534 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3535 ia_css_get_crop_offsets(pipe, &in_frame->info);
3537 err = ia_css_frame_init_planes(in_frame);
3539 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3540 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3545 static enum ia_css_err
3546 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3547 struct ia_css_frame *out_frame, unsigned int idx)
3549 enum ia_css_err err = IA_CSS_SUCCESS;
3550 unsigned int thread_id;
3551 enum sh_css_queue_id queue_id;
3553 assert(out_frame != NULL);
3555 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3556 out_frame->contiguous = false;
3557 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3558 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3559 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3560 out_frame->dynamic_queue_id = queue_id;
3561 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3562 err = ia_css_frame_init_planes(out_frame);
3567 /* Create stages for video pipe */
3568 static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe)
3570 struct ia_css_pipeline_stage_desc stage_desc;
3571 struct ia_css_binary *copy_binary, *video_binary,
3572 *yuv_scaler_binary, *vf_pp_binary;
3573 struct ia_css_pipeline_stage *copy_stage = NULL;
3574 struct ia_css_pipeline_stage *video_stage = NULL;
3575 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3576 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3577 struct ia_css_pipeline *me;
3578 struct ia_css_frame *in_frame = NULL;
3579 struct ia_css_frame *out_frame;
3580 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3581 struct ia_css_frame *vf_frame = NULL;
3582 enum ia_css_err err = IA_CSS_SUCCESS;
3583 bool need_copy = false;
3584 bool need_vf_pp = false;
3585 bool need_yuv_pp = false;
3586 unsigned num_output_pins;
3587 bool need_in_frameinfo_memory = false;
3589 unsigned int i, num_yuv_scaler;
3590 bool *is_output_stage = NULL;
3592 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3593 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3594 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3595 return IA_CSS_ERR_INVALID_ARGUMENTS;
3597 ia_css_pipe_util_create_output_frames(out_frames);
3598 out_frame = &pipe->out_frame_struct;
3600 /* pipeline already created as part of create_host_pipeline_structure */
3601 me = &pipe->pipeline;
3602 ia_css_pipeline_clean(me);
3604 me->dvs_frame_delay = pipe->dvs_frame_delay;
3606 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3607 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3608 * except for the following: online or continuous
3610 need_in_frameinfo_memory = !(pipe->stream->config.online || pipe->stream->config.continuous);
3612 /* Construct in_frame info (only in case we have dynamic input */
3613 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3616 /* Construct in_frame info (only in case we have dynamic input */
3617 if (need_in_frameinfo_memory) {
3618 in_frame = &pipe->in_frame_struct;
3619 err = init_in_frameinfo_memory_defaults(pipe, in_frame, IA_CSS_FRAME_FORMAT_RAW);
3620 if (err != IA_CSS_SUCCESS)
3624 out_frame->data = 0;
3625 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3626 if (err != IA_CSS_SUCCESS)
3629 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3630 vf_frame = &pipe->vf_frame_struct;
3632 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3633 if (err != IA_CSS_SUCCESS)
3637 copy_binary = &pipe->pipe_settings.video.copy_binary;
3638 video_binary = &pipe->pipe_settings.video.video_binary;
3639 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3640 num_output_pins = video_binary->info->num_output_pins;
3642 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3643 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3644 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3646 need_copy = (copy_binary != NULL && copy_binary->info != NULL);
3647 need_vf_pp = (vf_pp_binary != NULL && vf_pp_binary->info != NULL);
3648 need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL);
3651 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3652 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3653 out_frames, NULL, NULL);
3654 err = ia_css_pipeline_create_and_add_stage(me,
3657 if (err != IA_CSS_SUCCESS)
3659 in_frame = me->stages->args.out_frame[0];
3660 } else if (pipe->stream->config.continuous) {
3661 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3662 /* When continous is enabled, configure in_frame with the
3663 * last pipe, which is the copy pipe.
3665 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3667 in_frame = pipe->continuous_frames[0];
3671 ia_css_pipe_util_set_output_frames(out_frames, 0, need_yuv_pp ? NULL : out_frame);
3673 /* when the video binary supports a second output pin,
3674 it can directly produce the vf_frame. */
3676 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3677 out_frames, in_frame, NULL);
3679 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3680 out_frames, in_frame, vf_frame);
3682 err = ia_css_pipeline_create_and_add_stage(me,
3685 if (err != IA_CSS_SUCCESS)
3688 /* If we use copy iso video, the input must be yuv iso raw */
3690 video_stage->args.copy_vf =
3691 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3692 video_stage->args.copy_output = video_stage->args.copy_vf;
3695 /* when the video binary supports only 1 output pin, vf_pp is needed to
3696 produce the vf_frame.*/
3697 if (need_vf_pp && video_stage) {
3698 in_frame = video_stage->args.out_vf_frame;
3699 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3701 if (err != IA_CSS_SUCCESS)
3707 for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) {
3709 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3711 video_stage->args.tnr_frames[frm] =
3712 pipe->pipe_settings.video.tnr_frames[frm];
3714 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3715 video_stage->args.delay_frames[frm] =
3716 pipe->pipe_settings.video.delay_frames[frm];
3720 /* Append Extension on Video out, if enabled */
3721 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3722 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT))
3724 struct ia_css_frame *out = NULL;
3725 struct ia_css_frame *in = NULL;
3727 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3728 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3729 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3731 /* In/Out Frame mapping to support output frame extension.*/
3732 out = video_stage->args.out_frame[0];
3733 err = ia_css_frame_allocate_from_info(&in, &(pipe->output_info[0]));
3734 if (err != IA_CSS_SUCCESS)
3736 video_stage->args.out_frame[0] = in;
3739 err = add_firmwares( me, video_binary, pipe->output_stage,
3740 last_output_firmware(pipe->output_stage),
3741 IA_CSS_BINARY_MODE_VIDEO,
3742 in, out, NULL, &video_stage, NULL);
3743 if (err != IA_CSS_SUCCESS)
3747 if (need_yuv_pp && video_stage) {
3748 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3749 struct ia_css_frame *tmp_out_frame = NULL;
3751 for (i = 0; i < num_yuv_scaler; i++) {
3752 if (is_output_stage[i] == true) {
3753 tmp_out_frame = out_frame;
3755 tmp_out_frame = NULL;
3757 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3759 &yuv_scaler_binary[i],
3762 if (err != IA_CSS_SUCCESS) {
3763 IA_CSS_LEAVE_ERR_PRIVATE(err);
3766 /* we use output port 1 as internal output port */
3767 if (yuv_scaler_stage)
3768 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3772 pipe->pipeline.acquire_isp_each_stage = false;
3773 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3776 IA_CSS_LEAVE_ERR_PRIVATE(err);
3780 static enum ia_css_err
3781 create_host_acc_pipeline(struct ia_css_pipe *pipe)
3783 enum ia_css_err err = IA_CSS_SUCCESS;
3786 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3787 if ((pipe == NULL) || (pipe->stream == NULL)) {
3788 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3789 return IA_CSS_ERR_INVALID_ARGUMENTS;
3792 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3793 /* Reset pipe_qos_config to default disable all QOS extension stages */
3794 if (pipe->config.acc_extension)
3795 pipe->pipeline.pipe_qos_config = 0;
3798 const struct ia_css_fw_info *fw = pipe->vf_stage;
3799 for (i = 0; fw; fw = fw->next){
3800 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3801 if (err != IA_CSS_SUCCESS)
3806 for (i=0; i<pipe->config.num_acc_stages; i++) {
3807 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3808 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3809 if (err != IA_CSS_SUCCESS)
3813 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3816 IA_CSS_LEAVE_ERR_PRIVATE(err);
3820 /* Create stages for preview */
3821 static enum ia_css_err
3822 create_host_preview_pipeline(struct ia_css_pipe *pipe)
3824 struct ia_css_pipeline_stage *copy_stage = NULL;
3825 struct ia_css_pipeline_stage *preview_stage = NULL;
3826 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3827 struct ia_css_pipeline_stage_desc stage_desc;
3828 struct ia_css_pipeline *me = NULL;
3829 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3830 struct ia_css_frame *in_frame = NULL;
3831 enum ia_css_err err = IA_CSS_SUCCESS;
3832 struct ia_css_frame *out_frame;
3833 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3834 bool need_in_frameinfo_memory = false;
3835 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3836 bool sensor = false;
3837 bool buffered_sensor = false;
3838 bool online = false;
3839 bool continuous = false;
3842 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3843 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3844 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3845 return IA_CSS_ERR_INVALID_ARGUMENTS;
3849 ia_css_pipe_util_create_output_frames(out_frames);
3850 /* pipeline already created as part of create_host_pipeline_structure */
3851 me = &pipe->pipeline;
3852 ia_css_pipeline_clean(me);
3854 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3855 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3856 * except for the following:
3857 * - Direct Sensor Mode Online Preview
3858 * - Buffered Sensor Mode Online Preview
3859 * - Direct Sensor Mode Continuous Preview
3860 * - Buffered Sensor Mode Continous Preview
3862 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3863 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3864 online = pipe->stream->config.online;
3865 continuous = pipe->stream->config.continuous;
3866 need_in_frameinfo_memory =
3867 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3869 /* Construct in_frame info (only in case we have dynamic input */
3870 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3872 if (need_in_frameinfo_memory) {
3873 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW);
3874 if (err != IA_CSS_SUCCESS)
3877 in_frame = &me->in_frame;
3882 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3883 if (err != IA_CSS_SUCCESS)
3885 out_frame = &me->out_frame[0];
3887 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3888 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3889 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3890 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3892 if (pipe->pipe_settings.preview.copy_binary.info) {
3893 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3894 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3895 out_frames, NULL, NULL);
3896 err = ia_css_pipeline_create_and_add_stage(me,
3899 if (err != IA_CSS_SUCCESS)
3901 in_frame = me->stages->args.out_frame[0];
3905 } else if (pipe->stream->config.continuous) {
3907 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3908 /* When continuous is enabled, configure in_frame with the
3909 * last pipe, which is the copy pipe.
3911 if (continuous || !online){
3912 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3915 in_frame = pipe->continuous_frames[0];
3920 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3921 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3922 out_frames, in_frame, NULL);
3924 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3925 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3926 out_frames, in_frame, NULL);
3928 err = ia_css_pipeline_create_and_add_stage(me,
3931 if (err != IA_CSS_SUCCESS)
3933 /* If we use copy iso preview, the input must be yuv iso raw */
3934 preview_stage->args.copy_vf =
3935 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3936 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3937 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3938 /* in case of copy, use the vf frame as output frame */
3939 preview_stage->args.out_vf_frame =
3940 preview_stage->args.out_frame[0];
3943 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3944 in_frame = preview_stage->args.out_vf_frame;
3946 in_frame = preview_stage->args.out_frame[0];
3947 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3949 if (err != IA_CSS_SUCCESS)
3953 pipe->pipeline.acquire_isp_each_stage = false;
3954 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3957 IA_CSS_LEAVE_ERR_PRIVATE(err);
3961 static void send_raw_frames(struct ia_css_pipe *pipe)
3963 if (pipe->stream->config.continuous) {
3966 sh_css_update_host2sp_cont_num_raw_frames
3967 (pipe->stream->config.init_num_cont_raw_buf, true);
3968 sh_css_update_host2sp_cont_num_raw_frames
3969 (pipe->stream->config.target_num_cont_raw_buf, false);
3971 /* Hand-over all the SP-internal buffers */
3972 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3973 sh_css_update_host2sp_offline_frame(i,
3974 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3981 static enum ia_css_err
3982 preview_start(struct ia_css_pipe *pipe)
3984 struct ia_css_pipeline *me ;
3985 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3986 enum ia_css_err err = IA_CSS_SUCCESS;
3987 struct ia_css_pipe *copy_pipe, *capture_pipe;
3988 struct ia_css_pipe *acc_pipe;
3989 enum sh_css_pipe_config_override copy_ovrd;
3990 enum ia_css_input_mode preview_pipe_input_mode;
3992 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3993 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3994 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3995 return IA_CSS_ERR_INVALID_ARGUMENTS;
3998 me = &pipe->pipeline;
4000 preview_pipe_input_mode = pipe->stream->config.mode;
4002 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4003 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4004 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4006 copy_binary = &pipe->pipe_settings.preview.copy_binary;
4007 preview_binary = &pipe->pipe_settings.preview.preview_binary;
4008 if (pipe->pipe_settings.preview.vf_pp_binary.info)
4009 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4011 sh_css_metrics_start_frame();
4013 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4014 /* multi stream video needs mipi buffers */
4015 err = send_mipi_frames(pipe);
4016 if (err != IA_CSS_SUCCESS)
4019 send_raw_frames(pipe);
4022 unsigned int thread_id;
4024 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4025 copy_ovrd = 1 << thread_id;
4027 if (pipe->stream->cont_capt) {
4028 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4029 copy_ovrd |= 1 << thread_id;
4033 /* Construct and load the copy pipe */
4034 if (pipe->stream->config.continuous) {
4035 sh_css_sp_init_pipeline(©_pipe->pipeline,
4036 IA_CSS_PIPE_ID_COPY,
4037 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4039 pipe->stream->config.pixels_per_clock == 2, false,
4040 false, pipe->required_bds_factor,
4042 pipe->stream->config.mode,
4043 &pipe->stream->config.metadata_config,
4045 &pipe->stream->info.metadata_info
4047 &pipe->stream->info.metadata_info,
4049 #if !defined(HAS_NO_INPUT_SYSTEM)
4051 , pipe->stream->config.source.port.port
4053 pipe->stream->config.source.port.port,
4059 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4060 pipe->stream->isp_params_configs);
4063 /* make the preview pipe start with mem mode input, copy handles
4065 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4068 /* Construct and load the capture pipe */
4069 if (pipe->stream->cont_capt) {
4070 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4071 IA_CSS_PIPE_ID_CAPTURE,
4072 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4073 capture_pipe->config.default_capture_config.enable_xnr != 0,
4074 capture_pipe->stream->config.pixels_per_clock == 2,
4075 true, /* continuous */
4076 false, /* offline */
4077 capture_pipe->required_bds_factor,
4079 IA_CSS_INPUT_MODE_MEMORY,
4080 &pipe->stream->config.metadata_config,
4082 &pipe->stream->info.metadata_info
4084 &pipe->stream->info.metadata_info,
4086 #if !defined(HAS_NO_INPUT_SYSTEM)
4096 &capture_pipe->config.internal_frame_origin_bqs_on_sctbl,
4097 capture_pipe->stream->isp_params_configs);
4102 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4104 (uint8_t) ia_css_pipe_get_pipe_num(acc_pipe),
4106 pipe->stream->config.pixels_per_clock == 2,
4107 false, /* continuous */
4108 false, /* offline */
4109 pipe->required_bds_factor,
4111 IA_CSS_INPUT_MODE_MEMORY,
4118 #if !defined(HAS_NO_INPUT_SYSTEM)
4120 , (mipi_port_ID_t) 0
4128 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4129 pipe->stream->isp_params_configs);
4133 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4135 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4138 IA_CSS_LEAVE_ERR_PRIVATE(err);
4143 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4144 const struct ia_css_buffer *buffer)
4146 enum ia_css_err return_err = IA_CSS_SUCCESS;
4147 unsigned int thread_id;
4148 enum sh_css_queue_id queue_id;
4149 struct ia_css_pipeline *pipeline;
4150 struct ia_css_pipeline_stage *stage;
4151 struct ia_css_rmgr_vbuf_handle p_vbuf;
4152 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4153 struct sh_css_hmm_buffer ddr_buffer;
4154 enum ia_css_buffer_type buf_type;
4155 enum ia_css_pipe_id pipe_id;
4158 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4160 if ((pipe == NULL) || (buffer == NULL)) {
4161 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4162 return IA_CSS_ERR_INVALID_ARGUMENTS;
4165 buf_type = buffer->type;
4166 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4169 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4170 bool found_pipe = false;
4171 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4172 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4173 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4180 return IA_CSS_ERR_INVALID_ARGUMENTS;
4182 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
4183 bool found_pipe = false;
4184 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4185 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4186 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4193 return IA_CSS_ERR_INVALID_ARGUMENTS;
4196 pipe_id = pipe->mode;
4198 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4201 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4202 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4203 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4204 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4205 (pipe_id >= IA_CSS_PIPE_ID_NUM)) {
4206 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4207 return IA_CSS_ERR_INTERNAL_ERROR;
4210 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4212 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4213 return IA_CSS_ERR_INVALID_ARGUMENTS;
4216 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4218 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4219 return IA_CSS_ERR_INVALID_ARGUMENTS;
4222 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4223 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4224 return IA_CSS_ERR_INVALID_ARGUMENTS;
4227 if (!sh_css_sp_is_running()) {
4228 IA_CSS_LOG("SP is not running!");
4229 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4230 /* SP is not running. The queues are not valid */
4231 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4235 pipeline = &pipe->pipeline;
4237 assert(pipeline != NULL ||
4238 pipe_id == IA_CSS_PIPE_ID_COPY ||
4239 pipe_id == IA_CSS_PIPE_ID_ACC);
4241 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4242 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4243 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4244 ddr_buffer.timing_data = buffer->timing_data;
4246 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
4247 if (buffer->data.stats_3a == NULL) {
4248 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4249 return IA_CSS_ERR_INVALID_ARGUMENTS;
4251 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4252 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4253 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
4254 if (buffer->data.stats_dvs == NULL) {
4255 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4256 return IA_CSS_ERR_INVALID_ARGUMENTS;
4258 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4259 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4260 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
4261 if (buffer->data.metadata == NULL) {
4262 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4263 return IA_CSS_ERR_INVALID_ARGUMENTS;
4265 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4266 ddr_buffer.payload.metadata = *buffer->data.metadata;
4267 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4268 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4269 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4270 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4271 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) {
4272 if (buffer->data.frame == NULL) {
4273 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4274 return IA_CSS_ERR_INVALID_ARGUMENTS;
4276 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4277 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4278 ddr_buffer.payload.frame.flashed = 0;
4280 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4281 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4282 buf_type, buffer->data.frame->data);
4285 #if CONFIG_ON_FRAME_ENQUEUE()
4286 return_err = set_config_on_frame_enqueue(
4287 &buffer->data.frame->info,
4288 &ddr_buffer.payload.frame);
4289 if (IA_CSS_SUCCESS != return_err) {
4290 IA_CSS_LEAVE_ERR(return_err);
4296 /* start of test for using rmgr for acq/rel memory */
4299 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4301 /* TODO: change next to correct pool for optimization */
4302 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4304 assert(h_vbuf != NULL);
4305 assert(h_vbuf->vptr != 0x0);
4307 if ((h_vbuf == NULL) || (h_vbuf->vptr == 0x0)) {
4308 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4309 return IA_CSS_ERR_INTERNAL_ERROR;
4312 mmgr_store(h_vbuf->vptr,
4313 (void *)(&ddr_buffer),
4314 sizeof(struct sh_css_hmm_buffer));
4315 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4316 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4317 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) {
4318 if (pipeline == NULL) {
4319 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4320 IA_CSS_LOG("pipeline is empty!");
4321 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4322 return IA_CSS_ERR_INTERNAL_ERROR;
4325 for (stage = pipeline->stages; stage; stage = stage->next) {
4326 /* The SP will read the params
4327 after it got empty 3a and dis */
4328 if (STATS_ENABLED(stage)) {
4329 /* there is a stage that needs it */
4330 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4332 (uint32_t)h_vbuf->vptr);
4335 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4336 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4337 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4338 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4339 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4340 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) {
4341 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4343 (uint32_t)h_vbuf->vptr);
4344 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4345 if ((return_err == IA_CSS_SUCCESS) && (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type)) {
4346 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4347 ddr_buffer.payload.frame.frame_data,
4348 queue_id, thread_id);
4354 if (return_err == IA_CSS_SUCCESS) {
4355 if (sh_css_hmm_buffer_record_acquire(
4357 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4358 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4360 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4361 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4366 * Tell the SP which queues are not empty,
4367 * by sending the software event.
4369 if (return_err == IA_CSS_SUCCESS) {
4370 if (!sh_css_sp_is_running()) {
4371 /* SP is not running. The queues are not valid */
4372 IA_CSS_LOG("SP is not running!");
4373 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4374 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4376 return_err = ia_css_bufq_enqueue_psys_event(
4377 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4382 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4383 IA_CSS_ERROR("buffer not enqueued");
4386 IA_CSS_LEAVE("return value = %d", return_err);
4392 * TODO: Free up the hmm memory space.
4395 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4396 struct ia_css_buffer *buffer)
4398 enum ia_css_err return_err;
4399 enum sh_css_queue_id queue_id;
4400 hrt_vaddress ddr_buffer_addr = (hrt_vaddress)0;
4401 struct sh_css_hmm_buffer ddr_buffer;
4402 enum ia_css_buffer_type buf_type;
4403 enum ia_css_pipe_id pipe_id;
4404 unsigned int thread_id;
4405 hrt_address kernel_ptr = 0;
4408 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4410 if ((pipe == NULL) || (buffer == NULL)) {
4411 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4412 return IA_CSS_ERR_INVALID_ARGUMENTS;
4415 pipe_id = pipe->mode;
4417 buf_type = buffer->type;
4419 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4421 ddr_buffer.kernel_ptr = 0;
4423 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4425 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4426 return IA_CSS_ERR_INVALID_ARGUMENTS;
4429 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4431 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4432 return IA_CSS_ERR_INVALID_ARGUMENTS;
4435 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4436 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4437 return IA_CSS_ERR_INVALID_ARGUMENTS;
4440 if (!sh_css_sp_is_running()) {
4441 IA_CSS_LOG("SP is not running!");
4442 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4443 /* SP is not running. The queues are not valid */
4444 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4447 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4448 (uint32_t *)&ddr_buffer_addr);
4450 if (return_err == IA_CSS_SUCCESS) {
4451 struct ia_css_frame *frame;
4452 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4454 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4456 /* Validate the ddr_buffer_addr and buf_type */
4457 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4458 ddr_buffer_addr, buf_type);
4459 if (hmm_buffer_record != NULL) {
4460 /* valid hmm_buffer_record found. Save the kernel_ptr
4461 * for validation after performing mmgr_load. The
4462 * vbuf handle and buffer_record can be released.
4464 kernel_ptr = hmm_buffer_record->kernel_ptr;
4465 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4466 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4468 IA_CSS_ERROR("hmm_buffer_record not found (0x%u) buf_type(%d)",
4469 ddr_buffer_addr, buf_type);
4470 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4471 return IA_CSS_ERR_INTERNAL_ERROR;
4474 mmgr_load(ddr_buffer_addr,
4476 sizeof(struct sh_css_hmm_buffer));
4478 /* if the kernel_ptr is 0 or an invalid, return an error.
4479 * do not access the buffer via the kernal_ptr.
4481 if ((ddr_buffer.kernel_ptr == 0) ||
4482 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4483 IA_CSS_ERROR("kernel_ptr invalid");
4484 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4485 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4486 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4487 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4488 return IA_CSS_ERR_INTERNAL_ERROR;
4491 if (ddr_buffer.kernel_ptr != 0) {
4492 /* buffer->exp_id : all instances to be removed later once the driver change
4493 * is completed. See patch #5758 for reference */
4495 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4496 buffer->timing_data = ddr_buffer.timing_data;
4498 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4499 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4500 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4504 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4505 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4506 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4507 if ((pipe) && (pipe->stop_requested == true))
4510 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4511 /* free mipi frames only for old input system
4512 * for 2401 it is done in ia_css_stream_destroy call
4514 return_err = free_mipi_frames(pipe);
4515 if (return_err != IA_CSS_SUCCESS) {
4516 IA_CSS_LOG("free_mipi_frames() failed");
4517 IA_CSS_LEAVE_ERR(return_err);
4521 pipe->stop_requested = false;
4523 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4524 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4525 frame = (struct ia_css_frame*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4526 buffer->data.frame = frame;
4527 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4528 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4529 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4530 if (ddr_buffer.payload.frame.flashed == 1)
4531 frame->flash_state =
4532 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4533 if (ddr_buffer.payload.frame.flashed == 2)
4534 frame->flash_state =
4535 IA_CSS_FRAME_FLASH_STATE_FULL;
4536 frame->valid = pipe->num_invalid_frames == 0;
4538 pipe->num_invalid_frames--;
4540 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4541 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4542 frame->planes.binary.size = frame->data_bytes;
4544 frame->planes.binary.size =
4545 sh_css_sp_get_binary_copy_size();
4548 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4549 if (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type) {
4550 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4551 frame->data, frame->isp_config_id, thread_id);
4555 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4556 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4557 buf_type, buffer->data.frame->data);
4560 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4561 buffer->data.stats_3a =
4562 (struct ia_css_isp_3a_statistics*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4563 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4564 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4565 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4567 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4568 buffer->data.stats_dvs =
4569 (struct ia_css_isp_dvs_statistics*)
4570 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4571 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4572 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4574 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4576 case IA_CSS_BUFFER_TYPE_METADATA:
4577 buffer->data.metadata =
4578 (struct ia_css_metadata*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4579 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4580 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4583 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4590 * Tell the SP which queues are not full,
4591 * by sending the software event.
4593 if (return_err == IA_CSS_SUCCESS){
4594 if (!sh_css_sp_is_running()) {
4595 IA_CSS_LOG("SP is not running!");
4596 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4597 /* SP is not running. The queues are not valid */
4598 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4600 ia_css_bufq_enqueue_psys_event(
4601 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4606 IA_CSS_LEAVE("buffer=%p", buffer);
4612 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4613 * TODO: modify and move it if possible.
4615 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4616 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4617 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4618 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4619 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4621 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4622 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /**< Output frame ready. */
4623 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /**< Second output frame ready. */
4624 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /**< Viewfinder Output frame ready. */
4625 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /**< Second viewfinder Output frame ready. */
4626 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /**< Indication that 3A statistics are available. */
4627 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /**< Indication that DIS statistics are available. */
4628 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /**< Pipeline Done event, sent after last pipeline stage. */
4629 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /**< Frame tagged. */
4630 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /**< Input frame ready. */
4631 IA_CSS_EVENT_TYPE_METADATA_DONE, /**< Metadata ready. */
4632 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /**< Indication that LACE statistics are available. */
4633 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /**< Extension stage executed. */
4634 IA_CSS_EVENT_TYPE_TIMER, /**< Timing measurement data. */
4635 IA_CSS_EVENT_TYPE_PORT_EOF, /**< End Of Frame event, sent when in buffered sensor mode. */
4636 IA_CSS_EVENT_TYPE_FW_WARNING, /**< Performance warning encountered by FW */
4637 IA_CSS_EVENT_TYPE_FW_ASSERT, /**< Assertion hit by FW */
4638 0, /** error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4642 ia_css_dequeue_event(struct ia_css_event *event)
4644 return ia_css_dequeue_psys_event(event);
4648 ia_css_dequeue_psys_event(struct ia_css_event *event)
4650 enum ia_css_pipe_id pipe_id = 0;
4651 uint8_t payload[4] = {0,0,0,0};
4652 enum ia_css_err ret_err;
4655 * a) use generic decoding function , same as the one used by sp.
4656 * b) group decode and dequeue into eventQueue module
4658 * We skip the IA_CSS_ENTER logging call
4659 * to avoid flooding the logs when the host application
4662 return IA_CSS_ERR_INVALID_ARGUMENTS;
4664 if (!sh_css_sp_is_running()) {
4665 /* SP is not running. The queues are not valid */
4666 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4669 /* dequeue the event (if any) from the psys event queue */
4670 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4671 if (ret_err != IA_CSS_SUCCESS)
4674 IA_CSS_LOG("event dequeued from psys event queue");
4676 /* Tell the SP that we dequeued an event from the event queue. */
4677 ia_css_bufq_enqueue_psys_event(
4678 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4680 /* Events are decoded into 4 bytes of payload, the first byte
4681 * contains the sp event type. This is converted to a host enum.
4682 * TODO: can this enum conversion be eliminated */
4683 event->type = convert_event_sp_to_host_domain[payload[0]];
4684 /* Some sane default values since not all events use all fields. */
4686 event->port = IA_CSS_CSI2_PORT0;
4688 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4689 event->fw_handle = 0;
4690 event->timer_data = 0;
4691 event->timer_code = 0;
4692 event->timer_subcode = 0;
4694 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4695 /* timer event ??? get the 2nd event and decode the data into the event struct */
4697 /* 1st event: LSB 16-bit timer data and code */
4698 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4699 event->timer_code = payload[2];
4700 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4701 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4702 if (ret_err != IA_CSS_SUCCESS) {
4703 /* no 2nd event ??? an error */
4704 /* Putting IA_CSS_ERROR is resulting in failures in
4705 * Merrifield smoke testing */
4706 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4709 ia_css_bufq_enqueue_psys_event(
4710 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4711 event->type = convert_event_sp_to_host_domain[payload[0]];
4713 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4714 /* 2nd event data: MSB 16-bit timer and subcode */
4715 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4716 event->timer_data |= (tmp_data << 16);
4717 event->timer_subcode = payload[2];
4719 /* It's a non timer event. So clear first half of the timer event data.
4720 * If the second part of the TIMER event is not recieved, we discard
4721 * the first half of the timer data and process the non timer event without
4722 * affecting the flow. So the non timer event falls through
4725 event->timer_data = 0;
4726 event->timer_code = 0;
4727 event->timer_subcode = 0;
4728 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4731 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4732 event->port = (enum ia_css_csi2_port)payload[1];
4733 event->exp_id = payload[3];
4734 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4735 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4736 /* exp_id is only available in these warning types */
4737 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4738 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4739 event->exp_id = payload[3];
4740 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4741 event->fw_assert_module_id = payload[1]; /* module */
4742 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4743 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4744 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4745 /* pipe related events.
4746 * payload[1] contains the pipe_num,
4747 * payload[2] contains the pipe_id. These are different. */
4748 event->pipe = find_pipe_by_num(payload[1]);
4749 pipe_id = (enum ia_css_pipe_id)payload[2];
4750 /* Check to see if pipe still exists */
4752 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4754 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4755 /* find the capture pipe that goes with this */
4757 n = event->pipe->stream->num_pipes;
4758 for (i = 0; i < n; i++) {
4759 struct ia_css_pipe *p =
4760 event->pipe->stream->pipes[i];
4761 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4766 event->exp_id = payload[3];
4768 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4769 /* payload[3] contains the acc fw handle. */
4770 uint32_t stage_num = (uint32_t)payload[3];
4771 ret_err = ia_css_pipeline_get_fw_from_stage(
4772 &(event->pipe->pipeline),
4774 &(event->fw_handle));
4775 if (ret_err != IA_CSS_SUCCESS) {
4776 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4784 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4786 IA_CSS_LEAVE("event_id=%d", event->type);
4788 return IA_CSS_SUCCESS;
4792 ia_css_dequeue_isys_event(struct ia_css_event *event)
4794 uint8_t payload[4] = {0, 0, 0, 0};
4795 enum ia_css_err err = IA_CSS_SUCCESS;
4797 /* We skip the IA_CSS_ENTER logging call
4798 * to avoid flooding the logs when the host application
4801 return IA_CSS_ERR_INVALID_ARGUMENTS;
4803 if (!sh_css_sp_is_running()) {
4804 /* SP is not running. The queues are not valid */
4805 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4808 err = ia_css_bufq_dequeue_isys_event(payload);
4809 if (err != IA_CSS_SUCCESS)
4812 IA_CSS_LOG("event dequeued from isys event queue");
4814 /* Update SP state to indicate that element was dequeued. */
4815 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4817 /* Fill return struct with appropriate info */
4818 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4819 /* EOF events are associated with a CSI port, not with a pipe */
4821 event->port = payload[1];
4822 event->exp_id = payload[3];
4824 IA_CSS_LEAVE_ERR(err);
4829 acc_start(struct ia_css_pipe *pipe)
4831 assert(pipe != NULL);
4832 assert(pipe->stream != NULL);
4834 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4835 pipe->stream->config.mode);
4838 static enum ia_css_err
4839 sh_css_pipe_start(struct ia_css_stream *stream)
4841 enum ia_css_err err = IA_CSS_SUCCESS;
4843 struct ia_css_pipe *pipe;
4844 enum ia_css_pipe_id pipe_id;
4845 unsigned int thread_id;
4847 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4849 if (stream == NULL) {
4850 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4851 return IA_CSS_ERR_INVALID_ARGUMENTS;
4853 pipe = stream->last_pipe;
4855 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4856 return IA_CSS_ERR_INVALID_ARGUMENTS;
4859 pipe_id = pipe->mode;
4861 if(stream->started == true) {
4862 IA_CSS_WARNING("Cannot start stream that is already started");
4863 IA_CSS_LEAVE_ERR(err);
4867 pipe->stop_requested = false;
4870 case IA_CSS_PIPE_ID_PREVIEW:
4871 err = preview_start(pipe);
4873 case IA_CSS_PIPE_ID_VIDEO:
4874 err = video_start(pipe);
4876 case IA_CSS_PIPE_ID_CAPTURE:
4877 err = capture_start(pipe);
4879 case IA_CSS_PIPE_ID_YUVPP:
4880 err = yuvpp_start(pipe);
4882 case IA_CSS_PIPE_ID_ACC:
4886 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4888 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4889 if (!stream->config.continuous) {
4891 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) {
4892 switch (stream->pipes[i]->mode) {
4893 case IA_CSS_PIPE_ID_PREVIEW:
4894 stream->pipes[i]->stop_requested = false;
4895 err = preview_start(stream->pipes[i]);
4897 case IA_CSS_PIPE_ID_VIDEO:
4898 stream->pipes[i]->stop_requested = false;
4899 err = video_start(stream->pipes[i]);
4901 case IA_CSS_PIPE_ID_CAPTURE:
4902 stream->pipes[i]->stop_requested = false;
4903 err = capture_start(stream->pipes[i]);
4905 case IA_CSS_PIPE_ID_YUVPP:
4906 stream->pipes[i]->stop_requested = false;
4907 err = yuvpp_start(stream->pipes[i]);
4909 case IA_CSS_PIPE_ID_ACC:
4910 stream->pipes[i]->stop_requested = false;
4911 acc_start(stream->pipes[i]);
4914 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4918 if (err != IA_CSS_SUCCESS) {
4919 IA_CSS_LEAVE_ERR_PRIVATE(err);
4923 /* Force ISP parameter calculation after a mode change
4924 * Acceleration API examples pass NULL for stream but they
4925 * don't use ISP parameters anyway. So this should be okay.
4926 * The SP binary (jpeg) copy does not use any parameters.
4928 if (!copy_on_sp(pipe)) {
4929 sh_css_invalidate_params(stream);
4930 err = sh_css_param_update_isp_params(pipe,
4931 stream->isp_params_configs, true, NULL);
4932 if (err != IA_CSS_SUCCESS) {
4933 IA_CSS_LEAVE_ERR_PRIVATE(err);
4938 ia_css_debug_pipe_graph_dump_epilogue();
4940 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4942 if (!sh_css_sp_is_running()) {
4943 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4944 /* SP is not running. The queues are not valid */
4945 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4947 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4948 (uint8_t)thread_id, 0, 0);
4950 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4951 if (!stream->config.continuous) {
4953 for (i = 1; i < stream->num_pipes; i++) {
4954 ia_css_pipeline_get_sp_thread_id(
4955 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4957 ia_css_bufq_enqueue_psys_event(
4958 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4959 (uint8_t)thread_id, 0, 0);
4963 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4964 if (pipe->stream->config.continuous) {
4965 struct ia_css_pipe *copy_pipe = NULL;
4967 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4968 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4969 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4970 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4972 if (copy_pipe == NULL) {
4973 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4974 return IA_CSS_ERR_INTERNAL_ERROR;
4976 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), &thread_id);
4977 /* by the time we reach here q is initialized and handle is available.*/
4978 ia_css_bufq_enqueue_psys_event(
4979 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4980 (uint8_t)thread_id, 0, 0);
4982 if (pipe->stream->cont_capt) {
4983 struct ia_css_pipe *capture_pipe = NULL;
4984 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4985 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4986 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4987 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4989 if (capture_pipe == NULL) {
4990 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4991 return IA_CSS_ERR_INTERNAL_ERROR;
4993 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4994 /* by the time we reach here q is initialized and handle is available.*/
4995 ia_css_bufq_enqueue_psys_event(
4996 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4997 (uint8_t)thread_id, 0, 0);
5000 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
5001 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
5002 struct ia_css_pipe *acc_pipe = NULL;
5003 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5006 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), &thread_id);
5007 /* by the time we reach here q is initialized and handle is available.*/
5008 ia_css_bufq_enqueue_psys_event(
5009 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5010 (uint8_t) thread_id, 0, 0);
5014 stream->started = true;
5016 IA_CSS_LEAVE_ERR_PRIVATE(err);
5022 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5024 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5025 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5026 //my_css.cont_capt = enable;
5027 my_css.stop_copy_preview = stop_copy_preview;
5031 sh_css_continuous_is_enabled(uint8_t pipe_num)
5034 * @brief Stop all "ia_css_pipe" instances in the target
5035 * "ia_css_stream" instance.
5037 * Refer to "Local prototypes" for more info.
5039 static enum ia_css_err
5040 sh_css_pipes_stop(struct ia_css_stream *stream)
5044 struct ia_css_pipe *pipe;
5047 enum ia_css_err err = IA_CSS_SUCCESS;
5048 struct ia_css_pipe *main_pipe;
5049 enum ia_css_pipe_id main_pipe_id;
5054 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5056 assert(stream != NULL);
5057 if (stream == NULL) {
5058 IA_CSS_LOG("stream does NOT exist!");
5059 err = IA_CSS_ERR_INTERNAL_ERROR;
5065 pipe = find_pipe_by_num(pipe_num);
5066 continuous = pipe && pipe->stream->config.continuous;
5067 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5068 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5073 main_pipe = stream->last_pipe;
5074 assert(main_pipe != NULL);
5075 if (main_pipe == NULL) {
5076 IA_CSS_LOG("main_pipe does NOT exist!");
5077 err = IA_CSS_ERR_INTERNAL_ERROR;
5084 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5086 if (buffer_depth == NULL)
5087 return IA_CSS_ERR_INVALID_ARGUMENTS;
5088 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5090 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5091 return IA_CSS_SUCCESS;
5094 main_pipe_id = main_pipe->mode;
5095 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5100 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5102 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5104 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5105 return IA_CSS_ERR_INVALID_ARGUMENTS;
5106 /* ok, value allowed */
5107 stream->config.target_num_cont_raw_buf = buffer_depth;
5108 /* TODO: check what to regarding initialization */
5109 return IA_CSS_SUCCESS;
5113 * Stop all "ia_css_pipe" instances in this target
5114 * "ia_css_stream" instance.
5116 for (i = 0; i < stream->num_pipes; i++) {
5117 /* send the "stop" request to the "ia_css_pipe" instance */
5118 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5119 stream->pipes[i]->pipeline.pipe_id);
5120 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5125 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5127 if (buffer_depth == NULL)
5128 return IA_CSS_ERR_INVALID_ARGUMENTS;
5129 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5132 * Exit this loop if "ia_css_pipeline_request_stop()"
5133 * returns the error code.
5135 * The error code would be generated in the following
5137 * (1) The Scalar Processor has already been stopped.
5138 * (2) The "Host->SP" event queue is full.
5140 * As the convention of using CSS API 2.0/2.1, such CSS
5141 * error code would be propogated from the CSS-internal
5142 * API returned value to the CSS API returned value. Then
5143 * the CSS driver should capture these error code and
5144 * handle it in the driver exception handling mechanism.
5146 if (err != IA_CSS_SUCCESS) {
5152 * In the CSS firmware use scenario "Continuous Preview"
5153 * as well as "Continuous Video", the "ia_css_pipe" instance
5154 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5155 * the CSS firmware so that it is not listed in the target
5156 * "ia_css_stream" instance.
5158 * We need to stop this "Copy Pipe", as well.
5160 if (main_pipe->stream->config.continuous) {
5161 struct ia_css_pipe *copy_pipe = NULL;
5163 /* get the reference to "Copy Pipe" */
5164 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5165 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5166 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5167 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5169 /* return the error code if "Copy Pipe" does NOT exist */
5170 assert(copy_pipe != NULL);
5171 if (copy_pipe == NULL) {
5172 IA_CSS_LOG("Copy Pipe does NOT exist!");
5173 err = IA_CSS_ERR_INTERNAL_ERROR;
5177 /* send the "stop" request to "Copy Pipe" */
5178 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5179 copy_pipe->pipeline.pipe_id);
5180 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
5184 IA_CSS_LEAVE_ERR_PRIVATE(err);
5189 * @brief Check if all "ia_css_pipe" instances in the target
5190 * "ia_css_stream" instance have stopped.
5192 * Refer to "Local prototypes" for more info.
5195 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5199 struct ia_css_pipe *main_pipe;
5200 enum ia_css_pipe_id main_pipe_id;
5204 assert(stream != NULL);
5205 if (stream == NULL) {
5206 IA_CSS_LOG("stream does NOT exist!");
5211 main_pipe = stream->last_pipe;
5212 assert(main_pipe != NULL);
5214 if (main_pipe == NULL) {
5215 IA_CSS_LOG("main_pipe does NOT exist!");
5220 main_pipe_id = main_pipe->mode;
5221 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5224 * Check if every "ia_css_pipe" instance in this target
5225 * "ia_css_stream" instance has stopped.
5227 for (i = 0; i < stream->num_pipes; i++) {
5228 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5229 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5230 stream->pipes[i]->pipeline.pipe_id,
5235 * In the CSS firmware use scenario "Continuous Preview"
5236 * as well as "Continuous Video", the "ia_css_pipe" instance
5237 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5238 * the CSS firmware so that it is not listed in the target
5239 * "ia_css_stream" instance.
5241 * We need to check if this "Copy Pipe" has stopped, as well.
5243 if (main_pipe->stream->config.continuous) {
5244 struct ia_css_pipe *copy_pipe = NULL;
5246 /* get the reference to "Copy Pipe" */
5247 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5248 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5249 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5250 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5252 /* return if "Copy Pipe" does NOT exist */
5253 assert(copy_pipe != NULL);
5254 if (copy_pipe == NULL) {
5255 IA_CSS_LOG("Copy Pipe does NOT exist!");
5261 /* check if "Copy Pipe" has stopped or not */
5262 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5263 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5264 copy_pipe->pipeline.pipe_id,
5269 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5274 sh_css_continuous_is_enabled(uint8_t pipe_num)
5276 struct ia_css_pipe *pipe;
5279 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5281 pipe = find_pipe_by_num(pipe_num);
5282 continuous = pipe && pipe->stream->config.continuous;
5283 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5284 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5290 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5292 if (buffer_depth == NULL)
5293 return IA_CSS_ERR_INVALID_ARGUMENTS;
5294 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5296 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5297 return IA_CSS_SUCCESS;
5301 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5303 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5305 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5306 return IA_CSS_ERR_INVALID_ARGUMENTS;
5307 /* ok, value allowed */
5308 stream->config.target_num_cont_raw_buf = buffer_depth;
5309 /* TODO: check what to regarding initialization */
5310 return IA_CSS_SUCCESS;
5314 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5316 if (buffer_depth == NULL)
5317 return IA_CSS_ERR_INVALID_ARGUMENTS;
5318 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5321 *buffer_depth = stream->config.target_num_cont_raw_buf;
5322 return IA_CSS_SUCCESS;
5325 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5327 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5329 OP___assert(port < N_CSI_PORTS);
5330 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5331 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5332 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5333 return my_css.mipi_sizes_for_check[port][idx];
5337 static enum ia_css_err sh_css_pipe_configure_output(
5338 struct ia_css_pipe *pipe,
5340 unsigned int height,
5341 unsigned int padded_width,
5342 enum ia_css_frame_format format,
5345 enum ia_css_err err = IA_CSS_SUCCESS;
5347 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d",
5348 pipe, width, height, padded_width, format, idx);
5350 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5351 return IA_CSS_ERR_INVALID_ARGUMENTS;
5354 err = ia_css_util_check_res(width, height);
5355 if (err != IA_CSS_SUCCESS) {
5356 IA_CSS_LEAVE_ERR_PRIVATE(err);
5359 if (pipe->output_info[idx].res.width != width ||
5360 pipe->output_info[idx].res.height != height ||
5361 pipe->output_info[idx].format != format)
5363 ia_css_frame_info_init(
5364 &pipe->output_info[idx],
5370 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5371 return IA_CSS_SUCCESS;
5374 static enum ia_css_err
5375 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5377 struct ia_css_shading_info *info)
5379 struct ia_css_shading_info *shading_info,
5380 struct ia_css_pipe_config *pipe_config)
5383 enum ia_css_err err = IA_CSS_SUCCESS;
5384 struct ia_css_binary *binary = NULL;
5386 assert(pipe != NULL);
5388 assert(info != NULL);
5390 assert(shading_info != NULL);
5391 assert(pipe_config != NULL);
5393 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5394 "sh_css_pipe_get_shading_info() enter:\n");
5396 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5399 err = ia_css_binary_get_shading_info(binary,
5400 IA_CSS_SHADING_CORRECTION_TYPE_1,
5401 pipe->required_bds_factor,
5402 (const struct ia_css_stream_config *)&pipe->stream->config,
5406 shading_info, pipe_config);
5408 /* Other function calls can be added here when other shading correction types will be added
5412 /* When the pipe does not have a binary which has the shading
5413 * correction, this function does not need to fill the shading
5414 * information. It is not a error case, and then
5415 * this function should return IA_CSS_SUCCESS.
5418 memset(info, 0, sizeof(*info));
5420 memset(shading_info, 0, sizeof(*shading_info));
5426 static enum ia_css_err
5427 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5428 struct ia_css_grid_info *info)
5430 enum ia_css_err err = IA_CSS_SUCCESS;
5431 struct ia_css_binary *binary = NULL;
5433 assert(pipe != NULL);
5434 assert(info != NULL);
5436 IA_CSS_ENTER_PRIVATE("");
5438 binary = ia_css_pipe_get_s3a_binary(pipe);
5441 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5442 if (err != IA_CSS_SUCCESS)
5445 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5447 binary = ia_css_pipe_get_sdis_binary(pipe);
5450 ia_css_binary_dvs_grid_info(binary, info, pipe);
5451 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5453 memset(&info->dvs_grid.dvs_grid_info, 0,
5454 sizeof(info->dvs_grid.dvs_grid_info));
5455 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5456 sizeof(info->dvs_grid.dvs_stat_grid_info));
5459 if (binary != NULL) {
5460 /* copy pipe does not have ISP binary*/
5461 info->isp_in_width = binary->internal_frame_info.res.width;
5462 info->isp_in_height = binary->internal_frame_info.res.height;
5465 #if defined(HAS_VAMEM_VERSION_2)
5466 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5467 #elif defined(HAS_VAMEM_VERSION_1)
5468 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5470 #error "Unknown VAMEM version"
5474 IA_CSS_LEAVE_ERR_PRIVATE(err);
5480 * @brief Check if a format is supported by the pipe.
5483 static enum ia_css_err
5484 ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format)
5486 const enum ia_css_frame_format *supported_formats;
5487 int number_of_formats;
5491 IA_CSS_ENTER_PRIVATE("");
5493 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
5494 IA_CSS_ERROR("Pipe or binary info is not set");
5495 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5496 return IA_CSS_ERR_INVALID_ARGUMENTS;
5499 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5500 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats)/sizeof(enum ia_css_frame_format);
5502 for (i = 0; i < number_of_formats && !found; i++) {
5503 if (supported_formats[i] == format) {
5509 IA_CSS_ERROR("Requested format is not supported by binary");
5510 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5511 return IA_CSS_ERR_INVALID_ARGUMENTS;
5513 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5514 return IA_CSS_SUCCESS;
5519 static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe)
5521 struct ia_css_frame_info video_in_info, tnr_info,
5522 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5524 enum ia_css_err err = IA_CSS_SUCCESS;
5525 bool continuous = pipe->stream->config.continuous;
5527 unsigned num_output_pins;
5528 struct ia_css_frame_info video_bin_out_info;
5529 bool need_scaler = false;
5530 bool vf_res_different_than_output = false;
5531 bool need_vf_pp = false;
5533 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5535 IA_CSS_ENTER_PRIVATE("");
5536 assert(pipe != NULL);
5537 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5538 /* we only test the video_binary because offline video doesn't need a
5539 * vf_pp binary and online does not (always use) the copy_binary.
5540 * All are always reset at the same time anyway.
5542 if (mycs->video_binary.info)
5543 return IA_CSS_SUCCESS;
5545 online = pipe->stream->config.online;
5546 pipe_out_info = &pipe->output_info[0];
5547 pipe_vf_out_info = &pipe->vf_output_info[0];
5549 assert(pipe_out_info != NULL);
5552 * There is no explicit input format requirement for raw or yuv
5553 * What matters is that there is a binary that supports the stream format.
5554 * This is checked in the binary_find(), so no need to check it here
5556 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5557 if (err != IA_CSS_SUCCESS)
5559 /* cannot have online video and input_mode memory */
5560 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5561 return IA_CSS_ERR_INVALID_ARGUMENTS;
5562 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5563 err = ia_css_util_check_vf_out_info(pipe_out_info,
5565 if (err != IA_CSS_SUCCESS)
5568 err = ia_css_frame_check_info(pipe_out_info);
5569 if (err != IA_CSS_SUCCESS)
5573 if (pipe->out_yuv_ds_input_info.res.width)
5574 video_bin_out_info = pipe->out_yuv_ds_input_info;
5576 video_bin_out_info = *pipe_out_info;
5579 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]){
5580 video_vf_info = pipe_vf_out_info;
5581 vf_res_different_than_output = (video_vf_info->res.width != video_bin_out_info.res.width) ||
5582 (video_vf_info->res.height != video_bin_out_info.res.height);
5585 video_vf_info = NULL;
5588 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5590 /* we build up the pipeline starting at the end */
5591 /* YUV post-processing if needed */
5593 struct ia_css_cas_binary_descr cas_scaler_descr
5594 = IA_CSS_DEFAULT_CAS_BINARY_DESCR;
5596 /* NV12 is the common format that is supported by both */
5597 /* yuv_scaler and the video_xx_isp2_min binaries. */
5598 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5600 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5601 &video_bin_out_info,
5605 if (err != IA_CSS_SUCCESS)
5607 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5608 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5609 sizeof(struct ia_css_binary), GFP_KERNEL);
5610 if (mycs->yuv_scaler_binary == NULL) {
5611 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5614 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5615 * sizeof(bool), GFP_KERNEL);
5616 if (mycs->is_output_stage == NULL) {
5617 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5620 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5621 struct ia_css_binary_descr yuv_scaler_descr;
5622 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5623 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5624 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5625 &cas_scaler_descr.out_info[i],
5626 &cas_scaler_descr.internal_out_info[i],
5627 &cas_scaler_descr.vf_info[i]);
5628 err = ia_css_binary_find(&yuv_scaler_descr,
5629 &mycs->yuv_scaler_binary[i]);
5630 if (err != IA_CSS_SUCCESS) {
5631 kfree(mycs->is_output_stage);
5632 mycs->is_output_stage = NULL;
5636 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5641 struct ia_css_binary_descr video_descr;
5642 enum ia_css_frame_format vf_info_format;
5644 err = ia_css_pipe_get_video_binarydesc(pipe,
5645 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, video_vf_info,
5646 pipe->stream->config.left_padding);
5647 if (err != IA_CSS_SUCCESS)
5650 /* In the case where video_vf_info is not NULL, this allows
5651 * us to find a potential video library with desired vf format.
5652 * If success, no vf_pp binary is needed.
5653 * If failed, we will look up video binary with YUV_LINE vf format
5655 err = ia_css_binary_find(&video_descr,
5656 &mycs->video_binary);
5658 if (err != IA_CSS_SUCCESS) {
5659 if (video_vf_info) {
5660 /* This will do another video binary lookup later for YUV_LINE format*/
5664 } else if (video_vf_info) {
5665 /* The first video binary lookup is successful, but we may
5666 * still need vf_pp binary based on additiona check */
5667 num_output_pins = mycs->video_binary.info->num_output_pins;
5668 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5670 /* If the binary has dual output pins, we need vf_pp if the resolution
5672 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5674 /* If the binary has single output pin, we need vf_pp if additional
5675 * scaling is needed for vf */
5676 need_vf_pp |= ((num_output_pins == 1) &&
5677 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5678 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5682 /* save the current vf_info format for restoration later */
5683 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5684 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5686 vf_info_format = video_vf_info->format;
5688 if (!pipe->config.enable_vfpp_bci)
5689 ia_css_frame_info_set_format(video_vf_info,
5690 IA_CSS_FRAME_FORMAT_YUV_LINE);
5692 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5694 err = ia_css_binary_find(&video_descr,
5695 &mycs->video_binary);
5697 /* restore original vf_info format */
5698 ia_css_frame_info_set_format(video_vf_info,
5700 if (err != IA_CSS_SUCCESS)
5705 /* If a video binary does not use a ref_frame, we set the frame delay
5706 * to 0. This is the case for the 1-stage low-power video binary. */
5707 if (!mycs->video_binary.info->sp.enable.ref_frame)
5708 pipe->dvs_frame_delay = 0;
5710 /* The delay latency determines the number of invalid frames after
5711 * a stream is started. */
5712 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5713 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5715 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5716 * outputs a viewfinder output, then we need double the number of
5719 pipe->num_invalid_frames *= 2;
5721 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5722 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5723 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5725 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5726 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5728 if (!online && !continuous) {
5729 /* TODO: what exactly needs doing, prepend the copy binary to
5730 * video base this only on !online?
5732 err = load_copy_binary(pipe,
5734 &mycs->video_binary);
5735 if (err != IA_CSS_SUCCESS)
5742 #if !defined(HAS_OUTPUT_SYSTEM)
5743 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5744 struct ia_css_binary_descr vf_pp_descr;
5746 if (mycs->video_binary.vf_frame_info.format
5747 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5748 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5749 &mycs->video_binary.vf_frame_info,
5752 /* output from main binary is not yuv line. currently this is
5753 * possible only when bci is enabled on vfpp output */
5754 assert(pipe->config.enable_vfpp_bci == true);
5755 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5756 &mycs->video_binary.vf_frame_info,
5757 pipe_vf_out_info, NULL, NULL);
5760 err = ia_css_binary_find(&vf_pp_descr,
5761 &mycs->vf_pp_binary);
5762 if (err != IA_CSS_SUCCESS)
5767 err = allocate_delay_frames(pipe);
5769 if (err != IA_CSS_SUCCESS)
5772 if (mycs->video_binary.info->sp.enable.block_output) {
5774 unsigned int tnr_width;
5775 unsigned int tnr_height;
5777 tnr_info = mycs->video_binary.out_frame_info[0];
5780 /* Select resolution for TNR. If
5781 * output_system_in_resolution(GDC_out_resolution) is
5782 * being used, then select that as it will also be in resolution for
5783 * TNR. At present, it only make sense for Skycam */
5784 if (pipe->config.output_system_in_res.width && pipe->config.output_system_in_res.height) {
5785 tnr_width = pipe->config.output_system_in_res.width;
5786 tnr_height = pipe->config.output_system_in_res.height;
5788 tnr_width = tnr_info.res.width;
5789 tnr_height = tnr_info.res.height;
5792 /* Make tnr reference buffers output block width(in pix) align */
5793 tnr_info.res.width =
5795 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5796 tnr_info.padded_width = tnr_info.res.width;
5799 /* Make tnr reference buffers output block height align */
5800 tnr_info.res.height =
5802 CEIL_MUL(tnr_info.res.height,
5804 CEIL_MUL(tnr_height,
5806 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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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);
9448 if (curr_stream == NULL) {
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 == NULL) {
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 == NULL)
9787 IA_CSS_LOG("entered stream into loc=%d", i);
9788 my_css_save.stream_seeds[i].orig_stream = stream;
9789 my_css_save.stream_seeds[i].stream = curr_stream;
9790 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9791 my_css_save.stream_seeds[i].stream_config = *stream_config;
9792 for(j = 0; j < num_pipes; j++)
9794 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9795 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9796 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9801 if (err == IA_CSS_SUCCESS) {
9802 err = ia_css_save_stream(curr_stream);
9805 ia_css_stream_destroy(curr_stream);
9808 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9810 IA_CSS_LEAVE("return_err=%d", err);
9816 ia_css_stream_destroy(struct ia_css_stream *stream)
9819 enum ia_css_err err = IA_CSS_SUCCESS;
9821 enum ia_css_err err1 = IA_CSS_SUCCESS;
9822 enum ia_css_err err2 = IA_CSS_SUCCESS;
9825 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9826 if (stream == NULL) {
9827 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9828 IA_CSS_LEAVE_ERR_PRIVATE(err);
9832 ia_css_stream_isp_parameters_uninit(stream);
9834 if ((stream->last_pipe != NULL) &&
9835 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
9836 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9837 for (i = 0; i < stream->num_pipes; i++) {
9838 struct ia_css_pipe *entry = stream->pipes[i];
9839 unsigned int sp_thread_id;
9840 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9842 assert(entry != NULL);
9843 if (entry != NULL) {
9844 /* get the SP thread id */
9845 if (ia_css_pipeline_get_sp_thread_id(
9846 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9847 return IA_CSS_ERR_INTERNAL_ERROR;
9848 /* get the target input terminal */
9849 sp_pipeline_input_terminal =
9850 &(sh_css_sp_group.pipe_io[sp_thread_id].input);
9852 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9853 ia_css_isys_stream_h isys_stream =
9854 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
9855 if (stream->config.isys_config[i].valid && isys_stream->valid)
9856 ia_css_isys_stream_destroy(isys_stream);
9861 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9863 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
9864 stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
9865 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
9867 for (i = 0; i < stream->num_pipes; i++) {
9868 struct ia_css_pipe *entry = stream->pipes[i];
9869 /* free any mipi frames that are remaining:
9870 * some test stream create-destroy cycles do not generate output frames
9871 * and the mipi buffer is not freed in the deque function
9874 free_mipi_frames(entry);
9877 stream_unregister_with_csi_rx(stream);
9880 for (i = 0; i < stream->num_pipes; i++) {
9881 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9882 assert(curr_pipe != NULL);
9883 ia_css_pipe_map_queue(curr_pipe, false);
9886 err = map_sp_threads(stream, false);
9887 if (err != IA_CSS_SUCCESS) {
9888 IA_CSS_LEAVE_ERR_PRIVATE(err);
9893 /* remove references from pipes to stream */
9894 for (i = 0; i < stream->num_pipes; i++) {
9895 struct ia_css_pipe *entry = stream->pipes[i];
9896 assert(entry != NULL);
9897 if (entry != NULL) {
9898 /* clear reference to stream */
9899 entry->stream = NULL;
9900 /* check internal copy pipe */
9901 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9902 entry->pipe_settings.preview.copy_pipe) {
9903 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9904 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9906 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9907 entry->pipe_settings.video.copy_pipe) {
9908 IA_CSS_LOG("clearing stream on internal video copy pipe");
9909 entry->pipe_settings.video.copy_pipe->stream = NULL;
9911 err = sh_css_pipe_unload_binaries(entry);
9914 /* free associated memory of stream struct */
9915 kfree(stream->pipes);
9916 stream->pipes = NULL;
9917 stream->num_pipes = 0;
9919 /* working mode: take out of the seed list */
9920 if (my_css_save.mode == sh_css_mode_working)
9921 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
9922 if (my_css_save.stream_seeds[i].stream == stream)
9924 IA_CSS_LOG("took out stream %d", i);
9925 my_css_save.stream_seeds[i].stream = NULL;
9929 err2 = ia_css_save_restore_remove_stream(stream);
9931 err1 = (err != IA_CSS_SUCCESS) ? err : err2;
9935 IA_CSS_LEAVE_ERR(err);
9937 IA_CSS_LEAVE_ERR(err1);
9948 ia_css_stream_get_info(const struct ia_css_stream *stream,
9949 struct ia_css_stream_info *stream_info)
9951 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9952 assert(stream != NULL);
9953 assert(stream_info != NULL);
9955 *stream_info = stream->info;
9956 return IA_CSS_SUCCESS;
9960 * Rebuild a stream, including allocating structs, setting configuration and
9961 * building the required pipes.
9962 * The data is taken from the css_save struct updated upon stream creation.
9963 * The stream handle is used to identify the correct entry in the css_save struct
9966 ia_css_stream_load(struct ia_css_stream *stream)
9970 enum ia_css_err err;
9971 assert(stream != NULL);
9972 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter, \n");
9973 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
9974 if (my_css_save.stream_seeds[i].stream == stream)
9977 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
9978 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)
9984 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9988 err = ia_css_stream_create(&(my_css_save.stream_seeds[i].stream_config), my_css_save.stream_seeds[i].num_pipes,
9989 my_css_save.stream_seeds[i].pipes, &(my_css_save.stream_seeds[i].stream));
9990 if (err != IA_CSS_SUCCESS)
9992 ia_css_stream_destroy(stream);
9993 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
9994 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9999 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit, \n");
10000 return IA_CSS_SUCCESS;
10002 /* TODO remove function - DEPRECATED */
10004 return IA_CSS_ERR_NOT_SUPPORTED;
10009 ia_css_stream_start(struct ia_css_stream *stream)
10011 enum ia_css_err err = IA_CSS_SUCCESS;
10012 IA_CSS_ENTER("stream = %p", stream);
10013 if ((stream == NULL) || (stream->last_pipe == NULL)) {
10014 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
10015 return IA_CSS_ERR_INVALID_ARGUMENTS;
10017 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
10019 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
10021 /* Create host side pipeline. */
10022 err = create_host_pipeline(stream);
10023 if (err != IA_CSS_SUCCESS) {
10024 IA_CSS_LEAVE_ERR(err);
10028 #if !defined(HAS_NO_INPUT_SYSTEM)
10029 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10030 if((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10031 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10032 stream_register_with_csi_rx(stream);
10036 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10037 /* Initialize mipi size checks */
10038 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10041 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10043 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10044 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = sh_css_get_mipi_sizes_for_check(port, idx);
10049 #if !defined(HAS_NO_INPUT_SYSTEM)
10050 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
10051 err = sh_css_config_input_network(stream);
10052 if (err != IA_CSS_SUCCESS)
10055 #endif /* !HAS_NO_INPUT_SYSTEM */
10057 err = sh_css_pipe_start(stream);
10058 IA_CSS_LEAVE_ERR(err);
10063 ia_css_stream_stop(struct ia_css_stream *stream)
10065 enum ia_css_err err = IA_CSS_SUCCESS;
10067 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10068 assert(stream != NULL);
10069 assert(stream->last_pipe != NULL);
10070 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10071 stream->last_pipe->mode);
10073 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10074 /* De-initialize mipi size checks */
10075 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10078 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10080 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10081 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10086 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10089 err = sh_css_pipes_stop(stream);
10091 if (err != IA_CSS_SUCCESS)
10094 /* Ideally, unmapping should happen after pipeline_stop, but current
10095 * semantics do not allow that. */
10096 /* err = map_sp_threads(stream, false); */
10102 ia_css_stream_has_stopped(struct ia_css_stream *stream)
10105 assert(stream != NULL);
10108 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10110 stopped = sh_css_pipes_have_stopped(stream);
10118 * Destroy the stream and all the pipes related to it.
10119 * The stream handle is used to identify the correct entry in the css_save struct
10122 ia_css_stream_unload(struct ia_css_stream *stream)
10125 assert(stream != NULL);
10126 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter, \n");
10128 assert (stream != NULL);
10129 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
10130 if (my_css_save.stream_seeds[i].stream == stream)
10133 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
10134 ia_css_stream_destroy(stream);
10135 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
10136 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10137 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);
10140 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit, \n");
10141 return IA_CSS_SUCCESS;
10146 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, enum ia_css_pipe_id *pipe_id)
10148 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10150 *pipe_id = pipe->mode;
10152 *pipe_id = IA_CSS_PIPE_ID_COPY;
10154 return IA_CSS_SUCCESS;
10157 enum ia_css_stream_format
10158 ia_css_stream_get_format(const struct ia_css_stream *stream)
10160 return stream->config.input_config.format;
10164 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
10166 return (stream->config.pixels_per_clock == 2);
10169 struct ia_css_binary *
10170 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream *stream)
10172 struct ia_css_pipe *pipe;
10174 assert(stream != NULL);
10176 pipe = stream->pipes[0];
10178 if (stream->num_pipes == 2) {
10179 assert(stream->pipes[1] != NULL);
10180 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10181 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10182 pipe = stream->pipes[1];
10185 return ia_css_pipe_get_shading_correction_binary(pipe);
10188 struct ia_css_binary *
10189 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
10192 struct ia_css_pipe *video_pipe = NULL;
10194 /* First we find the video pipe */
10195 for (i=0; i<stream->num_pipes; i++) {
10196 struct ia_css_pipe *pipe = stream->pipes[i];
10197 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10203 return &video_pipe->pipe_settings.video.video_binary;
10207 struct ia_css_binary *
10208 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
10210 struct ia_css_pipe *pipe;
10211 struct ia_css_binary *s3a_binary = NULL;
10213 assert(stream != NULL);
10215 pipe = stream->pipes[0];
10217 if (stream->num_pipes == 2) {
10218 assert(stream->pipes[1] != NULL);
10219 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10220 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10221 pipe = stream->pipes[1];
10224 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10231 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int output_padded_width)
10233 enum ia_css_err err = IA_CSS_SUCCESS;
10235 struct ia_css_pipe *pipe;
10237 assert(stream != NULL);
10239 pipe = stream->last_pipe;
10241 assert(pipe != NULL);
10243 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10244 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10245 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10250 static struct ia_css_binary *
10251 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
10253 struct ia_css_binary *binary = NULL;
10255 assert(pipe != NULL);
10257 switch (pipe->config.mode) {
10258 case IA_CSS_PIPE_MODE_PREVIEW:
10259 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10261 case IA_CSS_PIPE_MODE_VIDEO:
10262 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10264 case IA_CSS_PIPE_MODE_CAPTURE:
10265 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10268 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10269 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10270 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10275 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10276 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10277 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10278 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10279 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10280 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10281 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10282 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10289 if (binary && binary->info->sp.enable.sc)
10295 static struct ia_css_binary *
10296 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
10298 struct ia_css_binary *binary = NULL;
10300 assert(pipe != NULL);
10302 switch (pipe->config.mode) {
10303 case IA_CSS_PIPE_MODE_PREVIEW:
10304 binary = (struct ia_css_binary*)&pipe->pipe_settings.preview.preview_binary;
10306 case IA_CSS_PIPE_MODE_VIDEO:
10307 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10309 case IA_CSS_PIPE_MODE_CAPTURE:
10310 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10312 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10313 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10314 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10319 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10320 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10321 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10322 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10323 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10324 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10325 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10326 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10335 if (binary && !binary->info->sp.enable.s3a)
10341 static struct ia_css_binary *
10342 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
10344 struct ia_css_binary *binary = NULL;
10346 assert(pipe != NULL);
10348 switch (pipe->config.mode) {
10349 case IA_CSS_PIPE_MODE_VIDEO:
10350 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10356 if (binary && !binary->info->sp.enable.dis)
10362 struct ia_css_pipeline *
10363 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
10365 assert(pipe != NULL);
10367 return (struct ia_css_pipeline*)&pipe->pipeline;
10371 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
10373 assert(pipe != NULL);
10375 /* KW was not sure this function was not returning a value
10376 that was out of range; so added an assert, and, for the
10377 case when asserts are not enabled, clip to the largest
10378 value; pipe_num is unsigned so the value cannot be too small
10380 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10382 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10383 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10385 return pipe->pipe_num;
10390 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
10392 assert(pipe != NULL);
10394 return (unsigned int)pipe->config.isp_pipe_version;
10397 #define SP_START_TIMEOUT_US 30000000
10400 ia_css_start_sp(void)
10402 unsigned long timeout;
10403 enum ia_css_err err = IA_CSS_SUCCESS;
10406 sh_css_sp_start_isp();
10408 /* waiting for the SP is completely started */
10409 timeout = SP_START_TIMEOUT_US;
10410 while((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
10414 if (timeout == 0) {
10415 IA_CSS_ERROR("timeout during SP initialization");
10416 return IA_CSS_ERR_INTERNAL_ERROR;
10419 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10420 /* TODO: Fix this. */
10422 sh_css_init_host_sp_control_vars();
10424 /* buffers should be initialized only when sp is started */
10425 /* AM: At the moment it will be done only when there is no stream active. */
10427 sh_css_setup_queues();
10428 ia_css_bufq_dump_queue_info();
10431 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10432 ia_css_set_system_mode(IA_CSS_SYS_MODE_WORKING);
10435 IA_CSS_LEAVE_ERR(err);
10440 * Time to wait SP for termincate. Only condition when this can happen
10441 * is a fatal hw failure, but we must be able to detect this and emit
10442 * a proper error trace.
10444 #define SP_SHUTDOWN_TIMEOUT_US 200000
10447 ia_css_stop_sp(void)
10449 unsigned long timeout;
10450 enum ia_css_err err = IA_CSS_SUCCESS;
10452 IA_CSS_ENTER("void");
10454 if (!sh_css_sp_is_running()) {
10455 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10456 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10458 /* Return an error - stop SP should not have been called by driver */
10462 /* For now, stop whole SP */
10464 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10466 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
10467 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10468 ia_css_debug_dump_sp_sw_debug_info();
10469 ia_css_debug_dump_debug_info(NULL);
10472 sh_css_sp_set_sp_running(false);
10474 timeout = SP_SHUTDOWN_TIMEOUT_US;
10475 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
10479 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10480 IA_CSS_WARNING("SP has not terminated (SW)");
10482 if (timeout == 0) {
10483 IA_CSS_WARNING("SP is not idle");
10484 ia_css_debug_dump_sp_sw_debug_info();
10486 timeout = SP_SHUTDOWN_TIMEOUT_US;
10487 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
10491 if (timeout == 0) {
10492 IA_CSS_WARNING("ISP is not idle");
10493 ia_css_debug_dump_sp_sw_debug_info();
10496 sh_css_hmm_buffer_record_uninit();
10499 /* clear pending param sets from refcount */
10500 sh_css_param_clear_param_sets();
10502 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10503 /* clear pending param sets from refcount */
10504 sh_css_param_clear_param_sets();
10505 ia_css_set_system_mode(IA_CSS_SYS_MODE_INIT); /* System is initialized but not 'running' */
10509 IA_CSS_LEAVE_ERR(err);
10514 ia_css_update_continuous_frames(struct ia_css_stream *stream)
10516 struct ia_css_pipe *pipe;
10519 ia_css_debug_dtrace(
10520 IA_CSS_DEBUG_TRACE,
10521 "sh_css_update_continuous_frames() enter:\n");
10523 if (stream == NULL) {
10524 ia_css_debug_dtrace(
10525 IA_CSS_DEBUG_TRACE,
10526 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10527 return IA_CSS_ERR_INVALID_ARGUMENTS;
10530 pipe = stream->continuous_pipe;
10532 for (i = stream->config.init_num_cont_raw_buf;
10533 i < stream->config.target_num_cont_raw_buf; i++) {
10534 sh_css_update_host2sp_offline_frame(i,
10535 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10537 sh_css_update_host2sp_cont_num_raw_frames
10538 (stream->config.target_num_cont_raw_buf, true);
10539 ia_css_debug_dtrace(
10540 IA_CSS_DEBUG_TRACE,
10541 "sh_css_update_continuous_frames() leave: return_void\n");
10543 return IA_CSS_SUCCESS;
10546 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10548 unsigned int thread_id;
10549 enum ia_css_pipe_id pipe_id;
10550 unsigned int pipe_num;
10551 bool need_input_queue;
10554 assert(pipe != NULL);
10556 pipe_id = pipe->mode;
10557 pipe_num = pipe->pipe_num;
10559 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10561 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10562 need_input_queue = true;
10564 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10567 /* map required buffer queues to resources */
10568 /* TODO: to be improved */
10569 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10570 if (need_input_queue)
10571 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10572 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10573 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10574 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10575 #if defined SH_CSS_ENABLE_METADATA
10576 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10578 if (pipe->pipe_settings.preview.preview_binary.info &&
10579 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10580 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10581 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10584 if (need_input_queue)
10585 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10586 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10587 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10588 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10589 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10590 #if defined SH_CSS_ENABLE_METADATA
10591 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10593 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10594 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10595 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10596 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10597 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10601 } else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10602 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10603 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10604 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10605 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10606 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10608 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10609 if (need_input_queue)
10610 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10611 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10612 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10613 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10614 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10615 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10616 #if defined SH_CSS_ENABLE_METADATA
10617 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10619 if (pipe->pipe_settings.video.video_binary.info &&
10620 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10621 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10622 if (pipe->pipe_settings.video.video_binary.info &&
10623 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10625 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10626 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10627 if (need_input_queue)
10628 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10629 if (!pipe->stream->config.continuous)
10630 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10631 #if defined SH_CSS_ENABLE_METADATA
10632 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10634 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10635 if (need_input_queue)
10636 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10637 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10638 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10639 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10640 #if defined SH_CSS_ENABLE_METADATA
10641 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10643 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10645 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10646 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10647 if (pipe->enable_viewfinder[idx])
10648 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10650 if (need_input_queue)
10651 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10652 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10653 #if defined SH_CSS_ENABLE_METADATA
10654 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10660 #if CONFIG_ON_FRAME_ENQUEUE()
10661 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame)
10663 frame->config_on_frame_enqueue.padded_width = 0;
10665 /* currently we support configuration on frame enqueue only on YUV formats */
10666 /* on other formats the padded_width is zeroed for no configuration override */
10667 switch (info->format) {
10668 case IA_CSS_FRAME_FORMAT_YUV420:
10669 case IA_CSS_FRAME_FORMAT_NV12:
10670 if (info->padded_width > info->res.width)
10672 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10674 else if ((info->padded_width < info->res.width) && (info->padded_width > 0))
10676 return IA_CSS_ERR_INVALID_ARGUMENTS;
10678 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10684 return IA_CSS_SUCCESS;
10689 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
10691 enum ia_css_err ret;
10695 /* Only continuous streams have a tagger to which we can send the
10696 * unlock message. */
10697 if (stream == NULL || !stream->config.continuous) {
10698 IA_CSS_ERROR("invalid stream pointer");
10699 return IA_CSS_ERR_INVALID_ARGUMENTS;
10702 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10703 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
10704 IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id);
10705 return IA_CSS_ERR_INVALID_ARGUMENTS;
10708 /* Send the event. Since we verified that the exp_id is valid,
10709 * we can safely assign it to an 8-bit argument here. */
10710 ret = ia_css_bufq_enqueue_psys_event(
10711 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10713 IA_CSS_LEAVE_ERR(ret);
10717 /** @brief Set the state (Enable or Disable) of the Extension stage in the
10721 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool enable)
10723 unsigned int thread_id;
10724 struct ia_css_pipeline_stage *stage;
10725 enum ia_css_err err = IA_CSS_SUCCESS;
10729 /* Parameter Check */
10730 if (pipe == NULL || pipe->stream == NULL) {
10731 IA_CSS_ERROR("Invalid Pipe.");
10732 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10733 } else if (!(pipe->config.acc_extension)) {
10734 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10735 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10736 } else if (!sh_css_sp_is_running()) {
10737 IA_CSS_ERROR("Leaving: queue unavailable.");
10738 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10740 /* Query the threadid and stage_num for the Extension firmware*/
10741 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10742 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10743 if (err == IA_CSS_SUCCESS) {
10744 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10745 err = ia_css_bufq_enqueue_psys_event(
10746 (uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10747 (uint8_t) thread_id,
10748 (uint8_t) stage->stage_num,
10749 (enable == true) ? 1 : 0);
10750 if (err == IA_CSS_SUCCESS) {
10752 SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10754 SH_CSS_QOS_STAGE_DISABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10758 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10762 /** @brief Get the state (Enable or Disable) of the Extension stage in the
10766 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool *enable)
10768 struct ia_css_pipeline_stage *stage;
10769 unsigned int thread_id;
10770 enum ia_css_err err = IA_CSS_SUCCESS;
10774 /* Parameter Check */
10775 if (pipe == NULL || pipe->stream == NULL) {
10776 IA_CSS_ERROR("Invalid Pipe.");
10777 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10778 } else if (!(pipe->config.acc_extension)) {
10779 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10780 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10781 } else if (!sh_css_sp_is_running()) {
10782 IA_CSS_ERROR("Leaving: queue unavailable.");
10783 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10785 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10786 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10787 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10789 if (err == IA_CSS_SUCCESS) {
10790 /* Get the Extension State */
10791 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num)) ? true : false;
10794 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10800 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, uint32_t fw_handle,
10801 struct ia_css_isp_param_css_segments *css_seg, struct ia_css_isp_param_isp_segments *isp_seg)
10803 unsigned int HIVE_ADDR_sp_group;
10804 static struct sh_css_sp_group sp_group;
10805 static struct sh_css_sp_stage sp_stage;
10806 static struct sh_css_isp_stage isp_stage;
10807 const struct ia_css_fw_info *fw;
10808 unsigned int thread_id;
10809 struct ia_css_pipeline_stage *stage;
10810 enum ia_css_err err = IA_CSS_SUCCESS;
10812 enum ia_css_isp_memories mem;
10817 fw = &sh_css_sp_fw;
10819 /* Parameter Check */
10820 if (pipe == NULL || pipe->stream == NULL) {
10821 IA_CSS_ERROR("Invalid Pipe.");
10822 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10823 } else if (!(pipe->config.acc_extension)) {
10824 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10825 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10826 } else if (!sh_css_sp_is_running()) {
10827 IA_CSS_ERROR("Leaving: queue unavailable.");
10828 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10830 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10831 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10832 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10833 if (err == IA_CSS_SUCCESS) {
10834 /* Get the Extension State */
10835 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]), stage->stage_num)) ? true : false;
10836 /* Update mapped arg only when extension stage is not enabled */
10838 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10839 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10841 stage_num = stage->stage_num;
10843 HIVE_ADDR_sp_group = fw->info.sp.group;
10844 sp_dmem_load(SP0_ID,
10845 (unsigned int)sp_address_of(sp_group),
10846 &sp_group, sizeof(struct sh_css_sp_group));
10847 mmgr_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10848 &sp_stage, sizeof(struct sh_css_sp_stage));
10850 mmgr_load(sp_stage.isp_stage_addr,
10851 &isp_stage, sizeof(struct sh_css_isp_stage));
10853 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10854 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10855 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10856 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10857 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10858 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10859 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10860 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10861 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10864 mmgr_store(sp_stage.isp_stage_addr,
10865 &isp_stage, sizeof(struct sh_css_isp_stage));
10869 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10873 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10874 static enum ia_css_err
10875 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10876 struct ia_css_pipe *pipes[],
10877 bool *do_crop_status)
10879 enum ia_css_err err = IA_CSS_SUCCESS;
10881 struct ia_css_pipe *curr_pipe;
10882 uint32_t pipe_mask = 0;
10884 if ((curr_stream == NULL) ||
10885 (curr_stream->num_pipes == 0) ||
10887 (do_crop_status == NULL)) {
10888 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10889 IA_CSS_LEAVE_ERR(err);
10893 for (i = 0; i < curr_stream->num_pipes; i++) {
10894 curr_pipe = pipes[i];
10895 pipe_mask |= (1 << curr_pipe->config.mode);
10899 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10900 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10901 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10902 curr_stream->config.continuous);
10903 return IA_CSS_SUCCESS;
10907 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe)
10909 bool status = false;
10911 if ((curr_pipe != NULL) && enabled) {
10912 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10913 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10914 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10921 static enum ia_css_err
10922 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10923 struct ia_css_resolution *effective_res)
10925 enum ia_css_err err = IA_CSS_SUCCESS;
10926 struct ia_css_resolution crop_res;
10927 struct ia_css_resolution *in_res = NULL;
10928 struct ia_css_resolution *out_res = NULL;
10929 bool use_bds_output_info = false;
10930 bool use_vf_pp_in_res = false;
10931 bool use_capt_pp_in_res = false;
10933 if ((curr_pipe == NULL) ||
10934 (effective_res == NULL)) {
10935 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10936 IA_CSS_LEAVE_ERR(err);
10940 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10941 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10942 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) {
10943 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10944 IA_CSS_LEAVE_ERR(err);
10948 use_bds_output_info =
10949 ((curr_pipe->bds_output_info.res.width != 0) &&
10950 (curr_pipe->bds_output_info.res.height != 0));
10953 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10954 (curr_pipe->config.vf_pp_in_res.height != 0));
10956 use_capt_pp_in_res =
10957 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10958 (curr_pipe->config.capt_pp_in_res.height != 0));
10960 in_res = &curr_pipe->stream->config.input_config.effective_res;
10961 out_res = &curr_pipe->output_info[0].res;
10963 switch (curr_pipe->config.mode) {
10964 case IA_CSS_PIPE_MODE_PREVIEW:
10965 if (use_bds_output_info)
10966 out_res = &curr_pipe->bds_output_info.res;
10967 else if (use_vf_pp_in_res)
10968 out_res = &curr_pipe->config.vf_pp_in_res;
10970 case IA_CSS_PIPE_MODE_VIDEO:
10971 if (use_bds_output_info)
10972 out_res = &curr_pipe->bds_output_info.res;
10974 case IA_CSS_PIPE_MODE_CAPTURE:
10975 if (use_capt_pp_in_res)
10976 out_res = &curr_pipe->config.capt_pp_in_res;
10978 case IA_CSS_PIPE_MODE_ACC:
10979 case IA_CSS_PIPE_MODE_COPY:
10980 case IA_CSS_PIPE_MODE_YUVPP:
10982 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10983 curr_pipe->config.mode);
10988 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10989 if (err == IA_CSS_SUCCESS) {
10990 *effective_res = crop_res;
10992 /* in case of error fallback to default
10993 * effective resolution from driver. */
10994 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
11002 sh_css_hmm_buffer_record_init(void)
11007 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11008 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11010 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11011 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11012 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11019 sh_css_hmm_buffer_record_uninit(void)
11022 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11025 buffer_record = &hmm_buffer_record[0];
11026 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11027 if (buffer_record->in_use) {
11028 if (buffer_record->h_vbuf != NULL)
11029 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11030 sh_css_hmm_buffer_record_reset(buffer_record);
11032 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11033 buffer_record = &hmm_buffer_record[0];
11034 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11035 if (buffer_record->in_use) {
11036 if (buffer_record->h_vbuf != NULL)
11037 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11038 sh_css_hmm_buffer_record_reset(buffer_record);
11050 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
11052 assert(buffer_record != NULL);
11053 buffer_record->in_use = false;
11054 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11055 buffer_record->h_vbuf = NULL;
11056 buffer_record->kernel_ptr = 0;
11059 static struct sh_css_hmm_buffer_record
11060 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11061 enum ia_css_buffer_type type,
11062 hrt_address kernel_ptr)
11065 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11066 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11068 assert(h_vbuf != NULL);
11069 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11070 assert(kernel_ptr != 0);
11072 buffer_record = &hmm_buffer_record[0];
11073 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11074 if (buffer_record->in_use == false) {
11075 buffer_record->in_use = true;
11076 buffer_record->type = type;
11077 buffer_record->h_vbuf = h_vbuf;
11078 buffer_record->kernel_ptr = kernel_ptr;
11079 out_buffer_record = buffer_record;
11085 return out_buffer_record;
11088 static struct sh_css_hmm_buffer_record
11089 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
11090 enum ia_css_buffer_type type)
11093 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11094 bool found_record = false;
11096 buffer_record = &hmm_buffer_record[0];
11097 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11098 if ((buffer_record->in_use == true) &&
11099 (buffer_record->type == type) &&
11100 (buffer_record->h_vbuf != NULL) &&
11101 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11102 found_record = true;
11108 if (found_record == true)
11109 return buffer_record;