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 struct sh_css my_css;
117 int (*sh_css_printf) (const char *fmt, va_list args) = NULL;
119 /* modes of work: stream_create and stream_destroy will update the save/restore data
120 only when in working mode, not suspend/resume
122 enum ia_sh_css_modes {
123 sh_css_mode_none = 0,
129 /* a stream seed, to save and restore the stream data.
130 the stream seed contains all the data required to "grow" the seed again after it was closed.
132 struct sh_css_stream_seed {
133 struct ia_css_stream **orig_stream; /* pointer to restore the original handle */
134 struct ia_css_stream *stream; /* handle, used as ID too.*/
135 struct ia_css_stream_config stream_config; /* stream config struct */
137 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */
138 struct ia_css_pipe **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */
139 struct ia_css_pipe_config pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */
142 #define MAX_ACTIVE_STREAMS 5
143 /* A global struct for save/restore to hold all the data that should sustain power-down:
144 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
147 enum ia_sh_css_modes mode;
148 uint32_t mmu_base; /* the last mmu_base */
149 enum ia_css_irq_type irq_type;
150 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
151 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
152 struct ia_css_env driver_env; /* driver-supplied env copy */
155 static bool my_css_save_initialized; /* if my_css_save was initialized */
156 static struct sh_css_save my_css_save;
158 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
159 this array is temporary and will be replaced by resource manager*/
160 /* Taking the biggest Size for number of Elements */
161 #define MAX_HMM_BUFFER_NUM \
162 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
164 struct sh_css_hmm_buffer_record {
166 enum ia_css_buffer_type type;
167 struct ia_css_rmgr_vbuf_handle *h_vbuf;
168 hrt_address kernel_ptr;
171 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
173 #define GPIO_FLASH_PIN_MASK (1 << HIVE_GPIO_STROBE_TRIGGER_PIN)
175 static bool fw_explicitly_loaded = false;
181 static enum ia_css_err
182 allocate_delay_frames(struct ia_css_pipe *pipe);
184 static enum ia_css_err
185 sh_css_pipe_start(struct ia_css_stream *stream);
189 * @brief Stop all "ia_css_pipe" instances in the target
190 * "ia_css_stream" instance.
192 * @param[in] stream Point to the target "ia_css_stream" instance.
195 * - IA_CSS_SUCCESS, if the "stop" requests have been successfully sent out.
196 * - CSS error code, otherwise.
200 * This API sends the "stop" requests to the "ia_css_pipe"
201 * instances in the same "ia_css_stream" instance. It will
202 * return without waiting for all "ia_css_pipe" instatnces
205 static enum ia_css_err
206 sh_css_pipes_stop(struct ia_css_stream *stream);
209 * @brief Check if all "ia_css_pipe" instances in the target
210 * "ia_css_stream" instance have stopped.
212 * @param[in] stream Point to the target "ia_css_stream" instance.
215 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
216 * instance have ben stopped.
217 * - false, otherwise.
220 sh_css_pipes_have_stopped(struct ia_css_stream *stream);
222 static enum ia_css_err
223 ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format);
225 static enum ia_css_err
226 check_pipe_resolutions(const struct ia_css_pipe *pipe);
230 static enum ia_css_err
231 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
232 struct ia_css_fw_info *firmware);
235 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
236 struct ia_css_fw_info *firmware);
238 ia_css_reset_defaults(struct sh_css* css);
241 sh_css_init_host_sp_control_vars(void);
243 static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version);
246 need_capture_pp(const struct ia_css_pipe *pipe);
249 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
251 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
252 struct ia_css_frame_info *cas_scaler_in_info,
253 struct ia_css_frame_info *cas_scaler_out_info,
254 struct ia_css_frame_info *cas_scaler_vf_info,
255 struct ia_css_cas_binary_descr *descr);
257 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr);
260 need_downscaling(const struct ia_css_resolution in_res,
261 const struct ia_css_resolution out_res);
263 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
265 static enum ia_css_err
266 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
269 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
270 struct ia_css_pipe *pipe,
271 struct ia_css_frame_info *info,
274 static enum ia_css_err
275 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
276 struct ia_css_frame_info *info,
279 static enum ia_css_err
280 capture_start(struct ia_css_pipe *pipe);
282 static enum ia_css_err
283 video_start(struct ia_css_pipe *pipe);
285 static enum ia_css_err
286 preview_start(struct ia_css_pipe *pipe);
288 static enum ia_css_err
289 yuvpp_start(struct ia_css_pipe *pipe);
291 static bool copy_on_sp(struct ia_css_pipe *pipe);
293 static enum ia_css_err
294 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
295 struct ia_css_frame *vf_frame, unsigned int idx);
297 static enum ia_css_err
298 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
299 struct ia_css_frame *frame, enum ia_css_frame_format format);
301 static enum ia_css_err
302 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
303 struct ia_css_frame *out_frame, unsigned int idx);
305 static enum ia_css_err
306 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
309 static enum ia_css_err
310 alloc_continuous_frames(
311 struct ia_css_pipe *pipe, bool init_time);
314 pipe_global_init(void);
316 static enum ia_css_err
317 pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number);
320 pipe_release_pipe_num(unsigned int pipe_num);
322 static enum ia_css_err
323 create_host_pipeline_structure(struct ia_css_stream *stream);
325 static enum ia_css_err
326 create_host_pipeline(struct ia_css_stream *stream);
328 static enum ia_css_err
329 create_host_preview_pipeline(struct ia_css_pipe *pipe);
331 static enum ia_css_err
332 create_host_video_pipeline(struct ia_css_pipe *pipe);
334 static enum ia_css_err
335 create_host_copy_pipeline(struct ia_css_pipe *pipe,
336 unsigned max_input_width,
337 struct ia_css_frame *out_frame);
339 static enum ia_css_err
340 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
342 static enum ia_css_err
343 create_host_capture_pipeline(struct ia_css_pipe *pipe);
345 static enum ia_css_err
346 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
348 static enum ia_css_err
349 create_host_acc_pipeline(struct ia_css_pipe *pipe);
352 sh_css_get_sw_interrupt_value(unsigned int irq);
354 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe);
356 static struct ia_css_binary *
357 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
359 static struct ia_css_binary *
360 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
363 sh_css_hmm_buffer_record_init(void);
366 sh_css_hmm_buffer_record_uninit(void);
369 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
371 static struct sh_css_hmm_buffer_record
372 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
373 enum ia_css_buffer_type type,
374 hrt_address kernel_ptr);
376 static struct sh_css_hmm_buffer_record
377 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
378 enum ia_css_buffer_type type);
381 ia_css_get_acc_configs(
382 struct ia_css_pipe *pipe,
383 struct ia_css_isp_config *config);
386 #if CONFIG_ON_FRAME_ENQUEUE()
387 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame);
390 #ifdef USE_INPUT_SYSTEM_VERSION_2401
391 static unsigned int get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config);
392 static unsigned int get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config);
393 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
394 unsigned int *extra_row, unsigned int *extra_column);
398 #ifdef USE_INPUT_SYSTEM_VERSION_2401
399 static enum ia_css_err
400 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
401 struct ia_css_pipe *pipes[],
402 bool *do_crop_status);
405 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe);
407 static enum ia_css_err
408 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
409 struct ia_css_resolution *effective_res);
414 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
416 assert(pipe != NULL);
418 IA_CSS_ERROR("NULL input parameter");
422 if (pipe->shading_table)
423 ia_css_shading_table_free(pipe->shading_table);
424 pipe->shading_table = NULL;
427 static enum ia_css_frame_format yuv420_copy_formats[] = {
428 IA_CSS_FRAME_FORMAT_NV12,
429 IA_CSS_FRAME_FORMAT_NV21,
430 IA_CSS_FRAME_FORMAT_YV12,
431 IA_CSS_FRAME_FORMAT_YUV420,
432 IA_CSS_FRAME_FORMAT_YUV420_16,
433 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
434 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
437 static enum ia_css_frame_format yuv422_copy_formats[] = {
438 IA_CSS_FRAME_FORMAT_NV12,
439 IA_CSS_FRAME_FORMAT_NV16,
440 IA_CSS_FRAME_FORMAT_NV21,
441 IA_CSS_FRAME_FORMAT_NV61,
442 IA_CSS_FRAME_FORMAT_YV12,
443 IA_CSS_FRAME_FORMAT_YV16,
444 IA_CSS_FRAME_FORMAT_YUV420,
445 IA_CSS_FRAME_FORMAT_YUV420_16,
446 IA_CSS_FRAME_FORMAT_YUV422,
447 IA_CSS_FRAME_FORMAT_YUV422_16,
448 IA_CSS_FRAME_FORMAT_UYVY,
449 IA_CSS_FRAME_FORMAT_YUYV
452 /* Verify whether the selected output format is can be produced
453 * by the copy binary given the stream format.
455 static enum ia_css_err
456 verify_copy_out_frame_format(struct ia_css_pipe *pipe)
458 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
459 unsigned int i, found = 0;
461 assert(pipe != NULL);
462 assert(pipe->stream != NULL);
464 switch (pipe->stream->config.input_config.format) {
465 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
466 case ATOMISP_INPUT_FORMAT_YUV420_8:
467 for (i=0; i<ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
468 found = (out_fmt == yuv420_copy_formats[i]);
470 case ATOMISP_INPUT_FORMAT_YUV420_10:
471 case ATOMISP_INPUT_FORMAT_YUV420_16:
472 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
474 case ATOMISP_INPUT_FORMAT_YUV422_8:
475 for (i=0; i<ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
476 found = (out_fmt == yuv422_copy_formats[i]);
478 case ATOMISP_INPUT_FORMAT_YUV422_10:
479 case ATOMISP_INPUT_FORMAT_YUV422_16:
480 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
481 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
483 case ATOMISP_INPUT_FORMAT_RGB_444:
484 case ATOMISP_INPUT_FORMAT_RGB_555:
485 case ATOMISP_INPUT_FORMAT_RGB_565:
486 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
487 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
489 case ATOMISP_INPUT_FORMAT_RGB_666:
490 case ATOMISP_INPUT_FORMAT_RGB_888:
491 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
492 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
494 case ATOMISP_INPUT_FORMAT_RAW_6:
495 case ATOMISP_INPUT_FORMAT_RAW_7:
496 case ATOMISP_INPUT_FORMAT_RAW_8:
497 case ATOMISP_INPUT_FORMAT_RAW_10:
498 case ATOMISP_INPUT_FORMAT_RAW_12:
499 case ATOMISP_INPUT_FORMAT_RAW_14:
500 case ATOMISP_INPUT_FORMAT_RAW_16:
501 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
502 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
504 case ATOMISP_INPUT_FORMAT_BINARY_8:
505 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
511 return IA_CSS_ERR_INVALID_ARGUMENTS;
512 return IA_CSS_SUCCESS;
516 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
521 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
522 stream->config.pixels_per_clock == 2);
527 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
528 static enum ia_css_err
529 sh_css_config_input_network(struct ia_css_stream *stream)
531 unsigned int fmt_type;
532 struct ia_css_pipe *pipe = stream->last_pipe;
533 struct ia_css_binary *binary = NULL;
534 enum ia_css_err err = IA_CSS_SUCCESS;
536 assert(stream != NULL);
537 assert(pipe != NULL);
539 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
540 "sh_css_config_input_network() enter:\n");
542 if (pipe->pipeline.stages)
543 binary = pipe->pipeline.stages->binary;
545 err = ia_css_isys_convert_stream_format_to_mipi_format(
546 stream->config.input_config.format,
547 stream->csi_rx_config.comp,
549 if (err != IA_CSS_SUCCESS)
551 sh_css_sp_program_input_circuit(fmt_type,
552 stream->config.channel_id,
553 stream->config.mode);
555 if ((binary && (binary->online || stream->config.continuous)) ||
556 pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
557 err = ia_css_ifmtr_configure(&stream->config,
559 if (err != IA_CSS_SUCCESS)
563 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
564 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
565 unsigned int hblank_cycles = 100,
570 width = (stream->config.input_config.input_res.width) / (1 + (stream->config.pixels_per_clock == 2));
571 height = stream->config.input_config.input_res.height;
572 vblank_cycles = vblank_lines * (width + hblank_cycles);
573 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
575 #if defined(IS_ISP_2400_SYSTEM)
576 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
577 /* TODO: move define to proper file in tools */
578 #define GP_ISEL_TPG_MODE 0x90058
579 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
583 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
584 "sh_css_config_input_network() leave:\n");
585 return IA_CSS_SUCCESS;
587 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
588 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
589 enum atomisp_input_format format,
590 unsigned int pixels_per_line)
595 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
597 * The frame format layout is shown below.
599 * Line 0: UYY0 UYY0 ... UYY0
600 * Line 1: VYY0 VYY0 ... VYY0
601 * Line 2: UYY0 UYY0 ... UYY0
602 * Line 3: VYY0 VYY0 ... VYY0
604 * Line (n-2): UYY0 UYY0 ... UYY0
605 * Line (n-1): VYY0 VYY0 ... VYY0
607 * In this frame format, the even-line is
608 * as wide as the odd-line.
609 * The 0 is introduced by the input system
612 rval = pixels_per_line * 2;
614 case ATOMISP_INPUT_FORMAT_YUV420_8:
615 case ATOMISP_INPUT_FORMAT_YUV420_10:
616 case ATOMISP_INPUT_FORMAT_YUV420_16:
618 * The frame format layout is shown below.
620 * Line 0: YYYY YYYY ... YYYY
621 * Line 1: UYVY UYVY ... UYVY UYVY
622 * Line 2: YYYY YYYY ... YYYY
623 * Line 3: UYVY UYVY ... UYVY UYVY
625 * Line (n-2): YYYY YYYY ... YYYY
626 * Line (n-1): UYVY UYVY ... UYVY UYVY
628 * In this frame format, the odd-line is twice
629 * wider than the even-line.
631 rval = pixels_per_line * 2;
633 case ATOMISP_INPUT_FORMAT_YUV422_8:
634 case ATOMISP_INPUT_FORMAT_YUV422_10:
635 case ATOMISP_INPUT_FORMAT_YUV422_16:
637 * The frame format layout is shown below.
639 * Line 0: UYVY UYVY ... UYVY
640 * Line 1: UYVY UYVY ... UYVY
641 * Line 2: UYVY UYVY ... UYVY
642 * Line 3: UYVY UYVY ... UYVY
644 * Line (n-2): UYVY UYVY ... UYVY
645 * Line (n-1): UYVY UYVY ... UYVY
647 * In this frame format, the even-line is
648 * as wide as the odd-line.
650 rval = pixels_per_line * 2;
652 case ATOMISP_INPUT_FORMAT_RGB_444:
653 case ATOMISP_INPUT_FORMAT_RGB_555:
654 case ATOMISP_INPUT_FORMAT_RGB_565:
655 case ATOMISP_INPUT_FORMAT_RGB_666:
656 case ATOMISP_INPUT_FORMAT_RGB_888:
658 * The frame format layout is shown below.
660 * Line 0: ABGR ABGR ... ABGR
661 * Line 1: ABGR ABGR ... ABGR
662 * Line 2: ABGR ABGR ... ABGR
663 * Line 3: ABGR ABGR ... ABGR
665 * Line (n-2): ABGR ABGR ... ABGR
666 * Line (n-1): ABGR ABGR ... ABGR
668 * In this frame format, the even-line is
669 * as wide as the odd-line.
671 rval = pixels_per_line * 4;
673 case ATOMISP_INPUT_FORMAT_RAW_6:
674 case ATOMISP_INPUT_FORMAT_RAW_7:
675 case ATOMISP_INPUT_FORMAT_RAW_8:
676 case ATOMISP_INPUT_FORMAT_RAW_10:
677 case ATOMISP_INPUT_FORMAT_RAW_12:
678 case ATOMISP_INPUT_FORMAT_RAW_14:
679 case ATOMISP_INPUT_FORMAT_RAW_16:
680 case ATOMISP_INPUT_FORMAT_BINARY_8:
681 case ATOMISP_INPUT_FORMAT_USER_DEF1:
682 case ATOMISP_INPUT_FORMAT_USER_DEF2:
683 case ATOMISP_INPUT_FORMAT_USER_DEF3:
684 case ATOMISP_INPUT_FORMAT_USER_DEF4:
685 case ATOMISP_INPUT_FORMAT_USER_DEF5:
686 case ATOMISP_INPUT_FORMAT_USER_DEF6:
687 case ATOMISP_INPUT_FORMAT_USER_DEF7:
688 case ATOMISP_INPUT_FORMAT_USER_DEF8:
690 * The frame format layout is shown below.
692 * Line 0: Pixel Pixel ... Pixel
693 * Line 1: Pixel Pixel ... Pixel
694 * Line 2: Pixel Pixel ... Pixel
695 * Line 3: Pixel Pixel ... Pixel
697 * Line (n-2): Pixel Pixel ... Pixel
698 * Line (n-1): Pixel Pixel ... Pixel
700 * In this frame format, the even-line is
701 * as wide as the odd-line.
703 rval = pixels_per_line;
713 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
714 struct ia_css_stream_config *stream_cfg,
715 ia_css_isys_descr_t *isys_stream_descr)
720 switch (stream_cfg->mode) {
721 case IA_CSS_INPUT_MODE_TPG:
723 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
724 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
725 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
726 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
727 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
728 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
732 case IA_CSS_INPUT_MODE_PRBS:
734 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
735 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
736 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
737 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
738 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
739 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
743 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
745 if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
746 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
747 } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
748 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
749 } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
750 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
762 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
763 struct ia_css_stream_config *stream_cfg,
764 ia_css_isys_descr_t *isys_stream_descr)
769 switch (stream_cfg->mode) {
770 case IA_CSS_INPUT_MODE_TPG:
772 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
775 case IA_CSS_INPUT_MODE_PRBS:
777 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
780 case IA_CSS_INPUT_MODE_SENSOR:
781 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
783 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
794 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
795 struct ia_css_stream_config *stream_cfg,
796 ia_css_isys_descr_t *isys_stream_descr,
802 switch (stream_cfg->mode) {
803 case IA_CSS_INPUT_MODE_TPG:
804 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
805 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
806 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
807 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
808 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
809 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
816 * - Make "color_cfg" as part of "ia_css_tpg_config".
818 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
819 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
820 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
821 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
822 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
823 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
825 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask = stream_cfg->source.tpg.x_mask;
826 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask = stream_cfg->source.tpg.y_mask;
827 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask = stream_cfg->source.tpg.xy_mask;
829 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta = stream_cfg->source.tpg.x_delta;
830 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta = stream_cfg->source.tpg.y_delta;
834 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
836 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
837 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
838 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
839 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
840 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;
841 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;
844 case IA_CSS_INPUT_MODE_PRBS:
846 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
847 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
851 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
853 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
854 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
855 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock = stream_cfg->pixels_per_clock;
856 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t) ~(0x0);
857 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;
858 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;
861 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
864 unsigned int fmt_type;
866 err = ia_css_isys_convert_stream_format_to_mipi_format(
867 stream_cfg->isys_config[isys_stream_idx].format,
870 if (err != IA_CSS_SUCCESS)
873 isys_stream_descr->csi_port_attr.active_lanes = stream_cfg->source.port.num_lanes;
874 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
875 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
876 #ifdef USE_INPUT_SYSTEM_VERSION_2401
877 isys_stream_descr->online = stream_cfg->online;
879 err |= ia_css_isys_convert_compressed_format(
880 &stream_cfg->source.port.compression,
882 if (err != IA_CSS_SUCCESS)
886 isys_stream_descr->metadata.enable = false;
887 if (stream_cfg->metadata_config.resolution.height > 0) {
888 err = ia_css_isys_convert_stream_format_to_mipi_format(
889 stream_cfg->metadata_config.data_type,
892 if (err != IA_CSS_SUCCESS)
894 isys_stream_descr->metadata.fmt_type = fmt_type;
895 isys_stream_descr->metadata.bits_per_pixel =
896 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
897 isys_stream_descr->metadata.pixels_per_line = stream_cfg->metadata_config.resolution.width;
898 isys_stream_descr->metadata.lines_per_frame = stream_cfg->metadata_config.resolution.height;
899 #ifdef USE_INPUT_SYSTEM_VERSION_2401
900 /* For new input system, number of str2mmio requests must be even.
901 * So we round up number of metadata lines to be even. */
902 if (isys_stream_descr->metadata.lines_per_frame > 0)
903 isys_stream_descr->metadata.lines_per_frame +=
904 (isys_stream_descr->metadata.lines_per_frame & 1);
906 isys_stream_descr->metadata.align_req_in_bytes =
907 ia_css_csi2_calculate_input_system_alignment(stream_cfg->metadata_config.data_type);
908 isys_stream_descr->metadata.enable = true;
921 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
922 struct ia_css_stream_config *stream_cfg,
923 ia_css_isys_descr_t *isys_stream_descr,
926 unsigned int bits_per_subpixel;
927 unsigned int max_subpixels_per_line;
928 unsigned int lines_per_frame;
929 unsigned int align_req_in_bytes;
930 enum atomisp_input_format fmt_type;
932 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
933 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
934 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
935 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
937 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
938 UNCOMPRESSED_BITS_PER_PIXEL_10) {
939 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
941 else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
942 UNCOMPRESSED_BITS_PER_PIXEL_12) {
943 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
950 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
951 if (bits_per_subpixel == 0)
954 max_subpixels_per_line =
955 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
956 stream_cfg->isys_config[isys_stream_idx].input_res.width);
957 if (max_subpixels_per_line == 0)
960 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
961 if (lines_per_frame == 0)
964 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
966 /* HW needs subpixel info for their settings */
967 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
968 isys_stream_descr->input_port_resolution.pixels_per_line = max_subpixels_per_line;
969 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
970 isys_stream_descr->input_port_resolution.align_req_in_bytes = align_req_in_bytes;
975 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
976 struct ia_css_stream_config *stream_cfg,
978 ia_css_isys_descr_t *isys_stream_descr,
983 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
984 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
985 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg, isys_stream_descr);
986 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg, isys_stream_descr);
987 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg, isys_stream_descr, isys_stream_idx);
988 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(stream_cfg, isys_stream_descr, isys_stream_idx);
990 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
991 isys_stream_descr->linked_isys_stream_id = (int8_t) stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
993 * Early polling is required for timestamp accuracy in certain case.
994 * The ISYS HW polling is started on
995 * ia_css_isys_stream_capture_indication() instead of
996 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
997 * capture takes longer than getting an ISYS frame
999 * Only 2401 relevant ??
1001 isys_stream_descr->polling_mode
1002 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1003 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1004 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1005 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1010 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1011 struct ia_css_binary *binary,
1012 ia_css_isys_descr_t *isys_stream_descr)
1017 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1018 isys_stream_descr->output_port_attr.max_isp_input_width = binary->info->sp.input.max_width;
1023 static enum ia_css_err
1024 sh_css_config_input_network(struct ia_css_stream *stream)
1027 ia_css_isys_descr_t isys_stream_descr;
1028 unsigned int sp_thread_id;
1029 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1030 struct ia_css_pipe *pipe = NULL;
1031 struct ia_css_binary *binary = NULL;
1033 uint32_t isys_stream_id;
1034 bool early_polling = false;
1036 assert(stream != NULL);
1037 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1038 "sh_css_config_input_network() enter 0x%p:\n", stream);
1040 if (stream->config.continuous == true) {
1041 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1042 pipe = stream->last_pipe;
1043 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1044 pipe = stream->last_pipe;
1045 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1046 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1047 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1048 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1051 pipe = stream->last_pipe;
1052 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1054 * We need to poll the ISYS HW in capture_indication itself
1055 * for "non-continuous" capture usecase for getting accurate
1056 * isys frame capture timestamps.
1057 * This is because the capturepipe propcessing takes longer
1058 * to execute than the input system frame capture.
1061 early_polling = true;
1065 assert(pipe != NULL);
1067 return IA_CSS_ERR_INTERNAL_ERROR;
1069 if (pipe->pipeline.stages != NULL)
1070 if (pipe->pipeline.stages->binary != NULL)
1071 binary = pipe->pipeline.stages->binary;
1076 /* this was being done in ifmtr in 2400.
1077 * online and cont bypass the init_in_frameinfo_memory_defaults
1078 * so need to do it here
1080 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1083 /* get the SP thread id */
1084 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1086 return IA_CSS_ERR_INTERNAL_ERROR;
1087 /* get the target input terminal */
1088 sp_pipeline_input_terminal = &(sh_css_sp_group.pipe_io[sp_thread_id].input);
1090 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
1091 /* initialization */
1092 memset((void*)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1093 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1094 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1096 if (!stream->config.isys_config[i].valid)
1099 /* translate the stream configuration to the Input System (2401) configuration */
1100 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1103 &(isys_stream_descr), i);
1105 if (stream->config.online) {
1106 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1108 &(isys_stream_descr));
1112 return IA_CSS_ERR_INTERNAL_ERROR;
1114 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1116 /* create the virtual Input System (2401) */
1117 rc = ia_css_isys_stream_create(
1118 &(isys_stream_descr),
1119 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1122 return IA_CSS_ERR_INTERNAL_ERROR;
1124 /* calculate the configuration of the virtual Input System (2401) */
1125 rc = ia_css_isys_stream_calculate_cfg(
1126 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]),
1127 &(isys_stream_descr),
1128 &(sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]));
1130 ia_css_isys_stream_destroy(&(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]));
1131 return IA_CSS_ERR_INTERNAL_ERROR;
1135 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1136 "sh_css_config_input_network() leave:\n");
1138 return IA_CSS_SUCCESS;
1141 static inline struct ia_css_pipe *stream_get_last_pipe(
1142 struct ia_css_stream *stream)
1144 struct ia_css_pipe *last_pipe = NULL;
1146 last_pipe = stream->last_pipe;
1151 static inline struct ia_css_pipe *stream_get_copy_pipe(
1152 struct ia_css_stream *stream)
1154 struct ia_css_pipe *copy_pipe = NULL;
1155 struct ia_css_pipe *last_pipe = NULL;
1156 enum ia_css_pipe_id pipe_id;
1158 last_pipe = stream_get_last_pipe(stream);
1160 if ((stream != NULL) &&
1161 (last_pipe != NULL) &&
1162 (stream->config.continuous)) {
1164 pipe_id = last_pipe->mode;
1166 case IA_CSS_PIPE_ID_PREVIEW:
1167 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1169 case IA_CSS_PIPE_ID_VIDEO:
1170 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1181 static inline struct ia_css_pipe *stream_get_target_pipe(
1182 struct ia_css_stream *stream)
1184 struct ia_css_pipe *target_pipe;
1186 /* get the pipe that consumes the stream */
1187 if (stream->config.continuous) {
1188 target_pipe = stream_get_copy_pipe(stream);
1190 target_pipe = stream_get_last_pipe(stream);
1196 static enum ia_css_err stream_csi_rx_helper(
1197 struct ia_css_stream *stream,
1198 enum ia_css_err (*func)(enum mipi_port_id, uint32_t))
1200 enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
1201 uint32_t sp_thread_id, stream_id;
1203 struct ia_css_pipe *target_pipe = NULL;
1205 if ((stream == NULL) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1208 target_pipe = stream_get_target_pipe(stream);
1210 if (target_pipe == NULL)
1213 rc = ia_css_pipeline_get_sp_thread_id(
1214 ia_css_pipe_get_pipe_num(target_pipe),
1220 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1223 if (stream->config.isys_config[stream_id].valid) {
1224 uint32_t isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1225 retval = func(stream->config.source.port.port, isys_stream_id);
1228 } while ((retval == IA_CSS_SUCCESS) &&
1229 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1235 static inline enum ia_css_err stream_register_with_csi_rx(
1236 struct ia_css_stream *stream)
1238 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1241 static inline enum ia_css_err stream_unregister_with_csi_rx(
1242 struct ia_css_stream *stream)
1244 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1248 #if WITH_PC_MONITORING
1249 static struct task_struct *my_kthread; /* Handle for the monitoring thread */
1250 static int sh_binary_running; /* Enable sampling in the thread */
1252 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1255 unsigned cnt_run = 0;
1256 unsigned cnt_stall = 0;
1261 sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1262 sh_css_print("%s PC\trun\tstall\n", core_name);
1264 for (i = 0; i < hist->length; i++) {
1265 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1267 sh_css_print("%s %d\t%d\t%d\n",
1268 core_name, i, hist->run[i], hist->stall[i]);
1269 cnt_run += hist->run[i];
1270 cnt_stall += hist->stall[i];
1273 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, "
1274 "hist->length = %d\n",
1275 core_name, cnt_run, cnt_stall, hist->length);
1278 static void print_pc_histogram(void)
1280 struct ia_css_binary_metrics *metrics;
1282 for (metrics = sh_css_metrics.binary_metrics;
1284 metrics = metrics->next) {
1285 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1286 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1287 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1292 sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1293 print_pc_histo(" ISP", &metrics->isp_histogram);
1294 print_pc_histo(" SP", &metrics->sp_histogram);
1295 sh_css_print("print_pc_histogram() done for binay->id = %d, "
1296 "done.\n", metrics->id);
1299 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1302 static int pc_monitoring(void *data)
1308 if (sh_binary_running) {
1309 sh_css_metrics_sample_pcs();
1310 #if MULTIPLE_SAMPLES
1311 for (i = 0; i < NOF_SAMPLES; i++)
1312 sh_css_metrics_sample_pcs();
1315 usleep_range(10, 50);
1320 static void spying_thread_create(void)
1322 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1323 sh_css_metrics_enable_pc_histogram(1);
1326 static void input_frame_info(struct ia_css_frame_info frame_info)
1328 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, "
1329 "frame->info.res.height = %d, format = %d\n",
1330 frame_info.res.width, frame_info.res.height, frame_info.format);
1332 #endif /* WITH_PC_MONITORING */
1335 start_binary(struct ia_css_pipe *pipe,
1336 struct ia_css_binary *binary)
1338 struct ia_css_stream *stream;
1340 assert(pipe != NULL);
1341 /* Acceleration uses firmware, the binary thus can be NULL */
1342 /* assert(binary != NULL); */
1346 #if !defined(HAS_NO_INPUT_SYSTEM)
1347 stream = pipe->stream;
1354 sh_css_metrics_start_binary(&binary->metrics);
1356 #if WITH_PC_MONITORING
1357 sh_css_print("PC_MONITORING: %s() -- binary id = %d , "
1358 "enable_dvs_envelope = %d\n",
1359 __func__, binary->info->sp.id,
1360 binary->info->sp.enable.dvs_envelope);
1361 input_frame_info(binary->in_frame_info);
1363 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1364 sh_binary_running = true;
1367 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1368 if (stream->reconfigure_css_rx) {
1369 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1370 pipe->stream->config.mode);
1371 stream->reconfigure_css_rx = false;
1376 /* start the copy function on the SP */
1377 static enum ia_css_err
1378 start_copy_on_sp(struct ia_css_pipe *pipe,
1379 struct ia_css_frame *out_frame)
1383 assert(pipe != NULL);
1384 assert(pipe->stream != NULL);
1386 if ((pipe == NULL) || (pipe->stream == NULL))
1387 return IA_CSS_ERR_INVALID_ARGUMENTS;
1389 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1390 if (pipe->stream->reconfigure_css_rx)
1391 ia_css_isys_rx_disable();
1394 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1395 return IA_CSS_ERR_INTERNAL_ERROR;
1396 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1398 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1399 if (pipe->stream->reconfigure_css_rx) {
1400 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode);
1401 pipe->stream->reconfigure_css_rx = false;
1405 return IA_CSS_SUCCESS;
1408 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1413 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++)
1415 for (i = 0; i < NUM_TNR_FRAMES; i++)
1417 args->tnr_frames[i] = NULL;
1418 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1419 args->delay_frames[i] = NULL;
1420 args->in_frame = NULL;
1421 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1422 args->out_frame[i] = NULL;
1423 args->out_vf_frame = NULL;
1424 args->copy_vf = false;
1425 args->copy_output = true;
1426 args->vf_downscale_log2 = 0;
1429 static void start_pipe(
1430 struct ia_css_pipe *me,
1431 enum sh_css_pipe_config_override copy_ovrd,
1432 enum ia_css_input_mode input_mode)
1434 #if defined(HAS_NO_INPUT_SYSTEM)
1438 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1439 me, copy_ovrd, input_mode);
1441 assert(me != NULL); /* all callers are in this file and call with non null argument */
1443 sh_css_sp_init_pipeline(&me->pipeline,
1445 (uint8_t)ia_css_pipe_get_pipe_num(me),
1446 me->config.default_capture_config.enable_xnr != 0,
1447 me->stream->config.pixels_per_clock == 2,
1448 me->stream->config.continuous,
1450 me->required_bds_factor,
1453 &me->stream->config.metadata_config,
1454 &me->stream->info.metadata_info
1455 #if !defined(HAS_NO_INPUT_SYSTEM)
1456 ,(input_mode==IA_CSS_INPUT_MODE_MEMORY) ?
1457 (enum mipi_port_id)0 :
1458 me->stream->config.source.port.port
1461 ,&me->config.internal_frame_origin_bqs_on_sctbl,
1462 me->stream->isp_params_configs
1466 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1467 struct ia_css_pipeline_stage *stage;
1468 stage = me->pipeline.stages;
1470 me->pipeline.current_stage = stage;
1471 start_binary(me, stage->binary);
1474 IA_CSS_LEAVE_PRIVATE("void");
1478 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1481 assert(stream != NULL);
1483 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1484 "sh_css_invalidate_shading_tables() enter:\n");
1486 for (i=0; i<stream->num_pipes; i++) {
1487 assert(stream->pipes[i] != NULL);
1488 sh_css_pipe_free_shading_table(stream->pipes[i]);
1491 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1492 "sh_css_invalidate_shading_tables() leave: return_void\n");
1497 enable_interrupts(enum ia_css_irq_type irq_type)
1499 #ifdef USE_INPUT_SYSTEM_VERSION_2
1500 enum mipi_port_id port;
1502 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1503 IA_CSS_ENTER_PRIVATE("");
1504 /* Enable IRQ on the SP which signals that SP goes to idle
1505 * (aka ready state) */
1506 cnd_sp_irq_enable(SP0_ID, true);
1507 /* Set the IRQ device 0 to either level or pulse */
1508 irq_enable_pulse(IRQ0_ID, enable_pulse);
1510 cnd_virq_enable_channel(virq_sp, true);
1512 /* Enable SW interrupt 0, this is used to signal ISYS events */
1513 cnd_virq_enable_channel(
1514 (virq_id_t)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1516 /* Enable SW interrupt 1, this is used to signal PSYS events */
1517 cnd_virq_enable_channel(
1518 (virq_id_t)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1520 #if !defined(HAS_IRQ_MAP_VERSION_2)
1521 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1522 cnd_virq_enable_channel(
1523 (virq_id_t)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1528 #ifdef USE_INPUT_SYSTEM_VERSION_2
1529 for (port = 0; port < N_MIPI_PORT_ID; port++)
1530 ia_css_isys_rx_enable_all_interrupts(port);
1533 IA_CSS_LEAVE_PRIVATE("");
1538 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1539 const char * program,
1540 ia_css_spctrl_cfg *spctrl_cfg)
1542 if((fw == NULL)||(spctrl_cfg == NULL))
1544 spctrl_cfg->sp_entry = 0;
1545 spctrl_cfg->program_name = (char *)(program);
1547 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1548 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1549 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1550 spctrl_cfg->data_size = fw->blob.data_size ;
1551 spctrl_cfg->bss_size = fw->blob.bss_size;
1553 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1554 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1556 spctrl_cfg->code_size = fw->blob.size;
1557 spctrl_cfg->code = fw->blob.code;
1558 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1563 ia_css_unload_firmware(void)
1565 if (sh_css_num_binaries)
1567 /* we have already loaded before so get rid of the old stuff */
1568 ia_css_binary_uninit();
1569 sh_css_unload_firmware();
1571 fw_explicitly_loaded = false;
1575 ia_css_reset_defaults(struct sh_css* css)
1577 struct sh_css default_css;
1579 /* Reset everything to zero */
1580 memset(&default_css, 0, sizeof(default_css));
1582 /* Initialize the non zero values*/
1583 default_css.check_system_idle = true;
1584 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1586 /* All should be 0: but memset does it already.
1587 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1590 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1592 /*Set the defaults to the output */
1597 ia_css_check_firmware_version(const struct ia_css_fw *fw)
1599 bool retval = false;
1602 retval = sh_css_check_firmware_version(fw->data);
1608 ia_css_load_firmware(const struct ia_css_env *env,
1609 const struct ia_css_fw *fw)
1611 enum ia_css_err err;
1614 return IA_CSS_ERR_INVALID_ARGUMENTS;
1616 return IA_CSS_ERR_INVALID_ARGUMENTS;
1618 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1620 /* make sure we initialize my_css */
1621 if (my_css.flush != env->cpu_mem_env.flush) {
1622 ia_css_reset_defaults(&my_css);
1623 my_css.flush = env->cpu_mem_env.flush;
1626 ia_css_unload_firmware(); /* in case we are called twice */
1627 err = sh_css_load_firmware(fw->data, fw->bytes);
1628 if (err == IA_CSS_SUCCESS) {
1629 err = ia_css_binary_init_infos();
1630 if (err == IA_CSS_SUCCESS)
1631 fw_explicitly_loaded = true;
1634 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave \n");
1639 ia_css_init(const struct ia_css_env *env,
1640 const struct ia_css_fw *fw,
1641 uint32_t mmu_l1_base,
1642 enum ia_css_irq_type irq_type)
1644 enum ia_css_err err;
1645 ia_css_spctrl_cfg spctrl_cfg;
1647 void (*flush_func)(struct ia_css_acc_fw *fw);
1648 hrt_data select, enable;
1651 * The C99 standard does not specify the exact object representation of structs;
1652 * the representation is compiler dependent.
1654 * The structs that are communicated between host and SP/ISP should have the
1655 * exact same object representation. The compiler that is used to compile the
1656 * firmware is hivecc.
1658 * To check if a different compiler, used to compile a host application, uses
1659 * another object representation, macros are defined specifying the size of
1660 * the structs as expected by the firmware.
1662 * A host application shall verify that a sizeof( ) of the struct is equal to
1663 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1664 * equal, functionality will break.
1666 /* Check struct sh_css_ddr_address_map */
1667 COMPILATION_ERROR_IF( sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT );
1668 /* Check struct host_sp_queues */
1669 COMPILATION_ERROR_IF( sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT );
1670 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT );
1671 COMPILATION_ERROR_IF( sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT );
1673 /* Check struct host_sp_communication */
1674 COMPILATION_ERROR_IF( sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT );
1675 COMPILATION_ERROR_IF( sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT );
1677 /* Check struct sh_css_hmm_buffer */
1678 COMPILATION_ERROR_IF( sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT );
1679 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT );
1680 COMPILATION_ERROR_IF( sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT );
1681 COMPILATION_ERROR_IF( sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT );
1683 /* Check struct ia_css_init_dmem_cfg */
1684 COMPILATION_ERROR_IF( sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT );
1686 if (fw == NULL && !fw_explicitly_loaded)
1687 return IA_CSS_ERR_INVALID_ARGUMENTS;
1689 return IA_CSS_ERR_INVALID_ARGUMENTS;
1691 sh_css_printf = env->print_env.debug_print;
1693 IA_CSS_ENTER("void");
1695 flush_func = env->cpu_mem_env.flush;
1698 ia_css_pipeline_init();
1699 ia_css_queue_map_init();
1701 ia_css_device_access_init(&env->hw_access_env);
1703 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1704 & (~GPIO_FLASH_PIN_MASK);
1705 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1706 | GPIO_FLASH_PIN_MASK;
1707 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1709 my_css_save.mmu_base = mmu_l1_base;
1711 ia_css_save_mmu_base_addr(mmu_l1_base);
1714 ia_css_reset_defaults(&my_css);
1716 my_css_save.driver_env = *env;
1717 my_css.flush = flush_func;
1719 err = ia_css_rmgr_init();
1720 if (err != IA_CSS_SUCCESS) {
1721 IA_CSS_LEAVE_ERR(err);
1726 IA_CSS_LOG("init: %d", my_css_save_initialized);
1728 ia_css_save_restore_data_init();
1732 if (!my_css_save_initialized)
1734 my_css_save_initialized = true;
1735 my_css_save.mode = sh_css_mode_working;
1736 memset(my_css_save.stream_seeds, 0, sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1737 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1743 /* In case this has been programmed already, update internal
1744 data structure ... DEPRECATED */
1745 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1748 my_css.irq_type = irq_type;
1750 my_css_save.irq_type = irq_type;
1752 ia_css_save_irq_type(irq_type);
1754 enable_interrupts(my_css.irq_type);
1756 /* configure GPIO to output mode */
1757 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1758 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1759 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1761 err = ia_css_refcount_init(REFCOUNT_SIZE);
1762 if (err != IA_CSS_SUCCESS) {
1763 IA_CSS_LEAVE_ERR(err);
1766 err = sh_css_params_init();
1767 if (err != IA_CSS_SUCCESS) {
1768 IA_CSS_LEAVE_ERR(err);
1773 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1774 err = sh_css_load_firmware(fw->data, fw->bytes);
1775 if (err != IA_CSS_SUCCESS) {
1776 IA_CSS_LEAVE_ERR(err);
1779 err = ia_css_binary_init_infos();
1780 if (err != IA_CSS_SUCCESS) {
1781 IA_CSS_LEAVE_ERR(err);
1784 fw_explicitly_loaded = false;
1786 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1789 if(!sh_css_setup_spctrl_config(&sh_css_sp_fw,SP_PROG_NAME,&spctrl_cfg))
1790 return IA_CSS_ERR_INTERNAL_ERROR;
1792 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1793 if (err != IA_CSS_SUCCESS) {
1794 IA_CSS_LEAVE_ERR(err);
1798 #if WITH_PC_MONITORING
1799 if (!thread_alive) {
1801 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1803 spying_thread_create();
1806 if (!sh_css_hrt_system_is_idle()) {
1807 IA_CSS_LEAVE_ERR(IA_CSS_ERR_SYSTEM_NOT_IDLE);
1808 return IA_CSS_ERR_SYSTEM_NOT_IDLE;
1810 /* can be called here, queuing works, but:
1811 - when sp is started later, it will wipe queued items
1812 so for now we leave it for later and make sure
1813 updates are not called to frequently.
1814 sh_css_init_buffer_queues();
1817 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1818 #if defined(USE_INPUT_SYSTEM_VERSION_2)
1819 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1820 #elif defined (USE_INPUT_SYSTEM_VERSION_2401)
1821 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1825 #if !defined(HAS_NO_INPUT_SYSTEM)
1826 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1827 ISP_DMA_MAX_BURST_LENGTH);
1829 if(ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1830 err = IA_CSS_ERR_INVALID_ARGUMENTS;
1833 sh_css_params_map_and_store_default_gdc_lut();
1835 IA_CSS_LEAVE_ERR(err);
1839 enum ia_css_err ia_css_suspend(void)
1842 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() enter\n");
1843 my_css_save.mode = sh_css_mode_suspend;
1844 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1845 if (my_css_save.stream_seeds[i].stream != NULL)
1847 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> unloading seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1848 ia_css_stream_unload(my_css_save.stream_seeds[i].stream);
1850 my_css_save.mode = sh_css_mode_working;
1853 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1854 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> after 1: seed %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
1855 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_suspend() leave\n");
1856 return IA_CSS_SUCCESS;
1863 enum ia_css_err err;
1864 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() enter: void\n");
1866 err = ia_css_init(&(my_css_save.driver_env), my_css_save.loaded_fw, my_css_save.mmu_base, my_css_save.irq_type);
1867 if (err != IA_CSS_SUCCESS)
1869 err = ia_css_start_sp();
1870 if (err != IA_CSS_SUCCESS)
1872 my_css_save.mode = sh_css_mode_resume;
1873 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
1875 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> seed stream %p\n", my_css_save.stream_seeds[i].stream);
1876 if (my_css_save.stream_seeds[i].stream != NULL)
1878 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "==*> loading seed %d\n", i);
1879 err = ia_css_stream_load(my_css_save.stream_seeds[i].stream);
1880 if (err != IA_CSS_SUCCESS)
1884 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1887 err = ia_css_stream_start(my_css_save.stream_seeds[i].stream);
1888 if (err != IA_CSS_SUCCESS)
1892 ia_css_stream_stop(my_css_save.stream_seeds[j].stream);
1893 ia_css_stream_unload(my_css_save.stream_seeds[j].stream);
1897 *my_css_save.stream_seeds[i].orig_stream = my_css_save.stream_seeds[i].stream;
1898 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
1899 *(my_css_save.stream_seeds[i].orig_pipes[j]) = my_css_save.stream_seeds[i].pipes[j];
1902 my_css_save.mode = sh_css_mode_working;
1903 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_resume() leave: return_void\n");
1904 return IA_CSS_SUCCESS;
1908 ia_css_enable_isys_event_queue(bool enable)
1910 if (sh_css_sp_is_running())
1911 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
1912 sh_css_sp_enable_isys_event_queue(enable);
1913 return IA_CSS_SUCCESS;
1916 void *sh_css_malloc(size_t size)
1918 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_malloc() enter: size=%zu\n",size);
1919 /* FIXME: This first test can probably go away */
1922 if (size > PAGE_SIZE)
1923 return vmalloc(size);
1924 return kmalloc(size, GFP_KERNEL);
1927 void *sh_css_calloc(size_t N, size_t size)
1931 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_calloc() enter: N=%zu, size=%zu\n",N,size);
1933 /* FIXME: this test can probably go away */
1935 p = sh_css_malloc(N*size);
1943 void sh_css_free(void *ptr)
1945 if (is_vmalloc_addr(ptr))
1951 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1953 sh_css_flush(struct ia_css_acc_fw *fw)
1955 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1956 if ((fw != NULL) && (my_css.flush != NULL))
1960 /* Mapping sp threads. Currently, this is done when a stream is created and
1961 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1962 * doing it from stream_create since we could run out of sp threads due to
1963 * allocation on inactive pipelines. */
1964 static enum ia_css_err
1965 map_sp_threads(struct ia_css_stream *stream, bool map)
1967 struct ia_css_pipe *main_pipe = NULL;
1968 struct ia_css_pipe *copy_pipe = NULL;
1969 struct ia_css_pipe *capture_pipe = NULL;
1970 struct ia_css_pipe *acc_pipe = NULL;
1971 enum ia_css_err err = IA_CSS_SUCCESS;
1972 enum ia_css_pipe_id pipe_id;
1974 assert(stream != NULL);
1975 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1976 stream, map ? "true" : "false");
1978 if (stream == NULL) {
1979 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1980 return IA_CSS_ERR_INVALID_ARGUMENTS;
1983 main_pipe = stream->last_pipe;
1984 pipe_id = main_pipe->mode;
1986 ia_css_pipeline_map(main_pipe->pipe_num, map);
1989 case IA_CSS_PIPE_ID_PREVIEW:
1990 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1991 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1992 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1995 case IA_CSS_PIPE_ID_VIDEO:
1996 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1997 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2000 case IA_CSS_PIPE_ID_CAPTURE:
2001 case IA_CSS_PIPE_ID_ACC:
2007 ia_css_pipeline_map(acc_pipe->pipe_num, map);
2011 ia_css_pipeline_map(capture_pipe->pipe_num, map);
2014 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
2016 ia_css_pipeline_map(copy_pipe->pipe_num, map);
2018 /* DH regular multi pipe - not continuous mode: map the next pipes too */
2019 if (!stream->config.continuous) {
2021 for (i = 1; i < stream->num_pipes; i++)
2022 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
2025 IA_CSS_LEAVE_ERR_PRIVATE(err);
2029 /* creates a host pipeline skeleton for all pipes in a stream. Called during
2031 static enum ia_css_err
2032 create_host_pipeline_structure(struct ia_css_stream *stream)
2034 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2035 struct ia_css_pipe *acc_pipe = NULL;
2036 enum ia_css_pipe_id pipe_id;
2037 struct ia_css_pipe *main_pipe = NULL;
2038 enum ia_css_err err = IA_CSS_SUCCESS;
2039 unsigned int copy_pipe_delay = 0,
2040 capture_pipe_delay = 0;
2042 assert(stream != NULL);
2043 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2045 if (stream == NULL) {
2046 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2047 return IA_CSS_ERR_INVALID_ARGUMENTS;
2050 main_pipe = stream->last_pipe;
2051 assert(main_pipe != NULL);
2052 if (main_pipe == NULL) {
2053 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2054 return IA_CSS_ERR_INVALID_ARGUMENTS;
2057 pipe_id = main_pipe->mode;
2060 case IA_CSS_PIPE_ID_PREVIEW:
2061 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2062 copy_pipe_delay = main_pipe->dvs_frame_delay;
2063 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2064 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2065 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2066 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2069 case IA_CSS_PIPE_ID_VIDEO:
2070 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2071 copy_pipe_delay = main_pipe->dvs_frame_delay;
2072 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2073 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2074 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2077 case IA_CSS_PIPE_ID_CAPTURE:
2078 capture_pipe = main_pipe;
2079 capture_pipe_delay = main_pipe->dvs_frame_delay;
2082 case IA_CSS_PIPE_ID_YUVPP:
2083 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2084 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2087 case IA_CSS_PIPE_ID_ACC:
2088 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode, main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2092 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2095 if ((IA_CSS_SUCCESS == err) && copy_pipe) {
2096 err = ia_css_pipeline_create(©_pipe->pipeline,
2098 copy_pipe->pipe_num,
2102 if ((IA_CSS_SUCCESS == err) && capture_pipe) {
2103 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2105 capture_pipe->pipe_num,
2106 capture_pipe_delay);
2109 if ((IA_CSS_SUCCESS == err) && acc_pipe) {
2110 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode, acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2113 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2114 if (!stream->config.continuous) {
2116 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2117 main_pipe = stream->pipes[i];
2118 err = ia_css_pipeline_create(&main_pipe->pipeline,
2120 main_pipe->pipe_num,
2121 main_pipe->dvs_frame_delay);
2125 IA_CSS_LEAVE_ERR_PRIVATE(err);
2129 /* creates a host pipeline for all pipes in a stream. Called during
2131 static enum ia_css_err
2132 create_host_pipeline(struct ia_css_stream *stream)
2134 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2135 struct ia_css_pipe *acc_pipe = NULL;
2136 enum ia_css_pipe_id pipe_id;
2137 struct ia_css_pipe *main_pipe = NULL;
2138 enum ia_css_err err = IA_CSS_SUCCESS;
2139 unsigned max_input_width = 0;
2141 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2142 if (stream == NULL) {
2143 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2144 return IA_CSS_ERR_INVALID_ARGUMENTS;
2147 main_pipe = stream->last_pipe;
2148 pipe_id = main_pipe->mode;
2150 /* No continuous frame allocation for capture pipe. It uses the
2151 * "main" pipe's frames. */
2152 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2153 (pipe_id == IA_CSS_PIPE_ID_VIDEO)) {
2154 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2155 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2156 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2157 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2158 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2160 if (stream->config.continuous ||
2161 (pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2162 err = alloc_continuous_frames(main_pipe, true);
2163 if (err != IA_CSS_SUCCESS)
2169 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2170 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2171 if (pipe_id != IA_CSS_PIPE_ID_ACC) {
2172 err = allocate_mipi_frames(main_pipe, &stream->info);
2173 if (err != IA_CSS_SUCCESS)
2176 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2177 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2178 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
2179 err = allocate_mipi_frames(main_pipe, &stream->info);
2180 if (err != IA_CSS_SUCCESS)
2186 case IA_CSS_PIPE_ID_PREVIEW:
2187 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2188 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2189 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2191 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2193 err = create_host_preview_pipeline(main_pipe);
2194 if (err != IA_CSS_SUCCESS)
2199 case IA_CSS_PIPE_ID_VIDEO:
2200 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2201 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2203 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2205 err = create_host_video_pipeline(main_pipe);
2206 if (err != IA_CSS_SUCCESS)
2211 case IA_CSS_PIPE_ID_CAPTURE:
2212 capture_pipe = main_pipe;
2216 case IA_CSS_PIPE_ID_YUVPP:
2217 err = create_host_yuvpp_pipeline(main_pipe);
2218 if (err != IA_CSS_SUCCESS)
2223 case IA_CSS_PIPE_ID_ACC:
2224 err = create_host_acc_pipeline(main_pipe);
2225 if (err != IA_CSS_SUCCESS)
2230 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2232 if (err != IA_CSS_SUCCESS)
2236 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2237 main_pipe->continuous_frames[0]);
2238 if (err != IA_CSS_SUCCESS)
2243 err = create_host_capture_pipeline(capture_pipe);
2244 if (err != IA_CSS_SUCCESS)
2249 err = create_host_acc_pipeline(acc_pipe);
2250 if (err != IA_CSS_SUCCESS)
2254 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2255 if (!stream->config.continuous) {
2257 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2258 switch (stream->pipes[i]->mode) {
2259 case IA_CSS_PIPE_ID_PREVIEW:
2260 err = create_host_preview_pipeline(stream->pipes[i]);
2262 case IA_CSS_PIPE_ID_VIDEO:
2263 err = create_host_video_pipeline(stream->pipes[i]);
2265 case IA_CSS_PIPE_ID_CAPTURE:
2266 err = create_host_capture_pipeline(stream->pipes[i]);
2268 case IA_CSS_PIPE_ID_YUVPP:
2269 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2271 case IA_CSS_PIPE_ID_ACC:
2272 err = create_host_acc_pipeline(stream->pipes[i]);
2275 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2277 if (err != IA_CSS_SUCCESS)
2283 IA_CSS_LEAVE_ERR_PRIVATE(err);
2287 static enum ia_css_err
2288 init_pipe_defaults(enum ia_css_pipe_mode mode,
2289 struct ia_css_pipe *pipe,
2293 IA_CSS_ERROR("NULL pipe parameter");
2294 return IA_CSS_ERR_INVALID_ARGUMENTS;
2297 /* Initialize pipe to pre-defined defaults */
2298 *pipe = IA_CSS_DEFAULT_PIPE;
2300 /* TODO: JB should not be needed, but temporary backward reference */
2302 case IA_CSS_PIPE_MODE_PREVIEW:
2303 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2304 pipe->pipe_settings.preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2306 case IA_CSS_PIPE_MODE_CAPTURE:
2308 pipe->mode = IA_CSS_PIPE_ID_COPY;
2310 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2312 pipe->pipe_settings.capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2314 case IA_CSS_PIPE_MODE_VIDEO:
2315 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2316 pipe->pipe_settings.video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2318 case IA_CSS_PIPE_MODE_ACC:
2319 pipe->mode = IA_CSS_PIPE_ID_ACC;
2321 case IA_CSS_PIPE_MODE_COPY:
2322 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2324 case IA_CSS_PIPE_MODE_YUVPP:
2325 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2326 pipe->pipe_settings.yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2329 return IA_CSS_ERR_INVALID_ARGUMENTS;
2332 return IA_CSS_SUCCESS;
2336 pipe_global_init(void)
2340 my_css.pipe_counter = 0;
2341 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2342 my_css.all_pipes[i] = NULL;
2346 static enum ia_css_err
2347 pipe_generate_pipe_num(const struct ia_css_pipe *pipe, unsigned int *pipe_number)
2349 const uint8_t INVALID_PIPE_NUM = (uint8_t)~(0);
2350 uint8_t pipe_num = INVALID_PIPE_NUM;
2354 IA_CSS_ERROR("NULL pipe parameter");
2355 return IA_CSS_ERR_INVALID_ARGUMENTS;
2358 /* Assign a new pipe_num .... search for empty place */
2359 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2360 if (my_css.all_pipes[i] == NULL) {
2361 /*position is reserved */
2362 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2367 if (pipe_num == INVALID_PIPE_NUM) {
2368 /* Max number of pipes already allocated */
2369 IA_CSS_ERROR("Max number of pipes already created");
2370 return IA_CSS_ERR_RESOURCE_EXHAUSTED;
2373 my_css.pipe_counter++;
2375 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2377 *pipe_number = pipe_num;
2378 return IA_CSS_SUCCESS;
2382 pipe_release_pipe_num(unsigned int pipe_num)
2384 my_css.all_pipes[pipe_num] = NULL;
2385 my_css.pipe_counter--;
2386 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2387 "pipe_release_pipe_num (%d)\n", pipe_num);
2390 static enum ia_css_err
2391 create_pipe(enum ia_css_pipe_mode mode,
2392 struct ia_css_pipe **pipe,
2395 enum ia_css_err err = IA_CSS_SUCCESS;
2396 struct ia_css_pipe *me;
2399 IA_CSS_ERROR("NULL pipe parameter");
2400 return IA_CSS_ERR_INVALID_ARGUMENTS;
2403 me = kmalloc(sizeof(*me), GFP_KERNEL);
2405 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
2407 err = init_pipe_defaults(mode, me, copy_pipe);
2408 if (err != IA_CSS_SUCCESS) {
2413 err = pipe_generate_pipe_num(me, &(me->pipe_num));
2414 if (err != IA_CSS_SUCCESS) {
2420 return IA_CSS_SUCCESS;
2423 struct ia_css_pipe *
2424 find_pipe_by_num(uint32_t pipe_num)
2427 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++){
2428 if (my_css.all_pipes[i] &&
2429 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2430 return my_css.all_pipes[i];
2436 static void sh_css_pipe_free_acc_binaries (
2437 struct ia_css_pipe *pipe)
2439 struct ia_css_pipeline *pipeline;
2440 struct ia_css_pipeline_stage *stage;
2442 assert(pipe != NULL);
2444 IA_CSS_ERROR("NULL input pointer");
2447 pipeline = &pipe->pipeline;
2449 /* loop through the stages and unload them */
2450 for (stage = pipeline->stages; stage; stage = stage->next) {
2451 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2454 ia_css_pipe_unload_extension(pipe, firmware);
2459 ia_css_pipe_destroy(struct ia_css_pipe *pipe)
2461 enum ia_css_err err = IA_CSS_SUCCESS;
2462 IA_CSS_ENTER("pipe = %p", pipe);
2465 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2466 return IA_CSS_ERR_INVALID_ARGUMENTS;
2469 if (pipe->stream != NULL) {
2470 IA_CSS_LOG("ia_css_stream_destroy not called!");
2471 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2472 return IA_CSS_ERR_INVALID_ARGUMENTS;
2475 switch (pipe->config.mode) {
2476 case IA_CSS_PIPE_MODE_PREVIEW:
2477 /* need to take into account that this function is also called
2478 on the internal copy pipe */
2479 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2480 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2481 pipe->continuous_frames);
2482 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2483 pipe->cont_md_buffers);
2484 if (pipe->pipe_settings.preview.copy_pipe) {
2485 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2486 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2487 "destroyed internal copy pipe err=%d\n", err);
2491 case IA_CSS_PIPE_MODE_VIDEO:
2492 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2493 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2494 pipe->continuous_frames);
2495 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2496 pipe->cont_md_buffers);
2497 if (pipe->pipe_settings.video.copy_pipe) {
2498 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2499 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_destroy(): "
2500 "destroyed internal copy pipe err=%d\n", err);
2504 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2506 ia_css_frame_free_multiple(NUM_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames);
2508 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames);
2510 case IA_CSS_PIPE_MODE_CAPTURE:
2511 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.capture.delay_frames);
2513 case IA_CSS_PIPE_MODE_ACC:
2514 sh_css_pipe_free_acc_binaries(pipe);
2516 case IA_CSS_PIPE_MODE_COPY:
2518 case IA_CSS_PIPE_MODE_YUVPP:
2522 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2523 pipe->scaler_pp_lut = mmgr_NULL;
2525 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2526 sh_css_pipe_free_shading_table(pipe);
2528 ia_css_pipeline_destroy(&pipe->pipeline);
2529 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2531 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2532 if (pipe->config.acc_extension) {
2533 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2536 IA_CSS_LEAVE("err = %d", err);
2543 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2544 #if WITH_PC_MONITORING
2545 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2546 print_pc_histogram();
2549 sh_css_params_free_default_gdc_lut();
2552 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2553 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2554 /* cleanup generic data */
2555 sh_css_params_uninit();
2556 ia_css_refcount_uninit();
2558 ia_css_rmgr_uninit();
2560 #if !defined(HAS_NO_INPUT_FORMATTER)
2561 /* needed for reprogramming the inputformatter after power cycle of css */
2562 ifmtr_set_if_blocking_mode_reset = true;
2565 if (!fw_explicitly_loaded) {
2566 ia_css_unload_firmware();
2568 ia_css_spctrl_unload_fw(SP0_ID);
2569 sh_css_sp_set_sp_running(false);
2570 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2571 /* check and free any remaining mipi frames */
2572 free_mipi_frames(NULL);
2575 sh_css_sp_reset_global_vars();
2577 #if !defined(HAS_NO_INPUT_SYSTEM)
2578 ia_css_isys_uninit();
2581 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2584 #if defined(HAS_IRQ_MAP_VERSION_2)
2585 enum ia_css_err ia_css_irq_translate(
2586 unsigned int *irq_infos)
2589 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2590 unsigned int infos = 0;
2592 /* irq_infos can be NULL, but that would make the function useless */
2593 /* assert(irq_infos != NULL); */
2594 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() enter: irq_infos=%p\n",irq_infos);
2596 while (status == hrt_isp_css_irq_status_more_irqs) {
2597 status = virq_get_channel_id(&irq);
2598 if (status == hrt_isp_css_irq_status_error)
2599 return IA_CSS_ERR_INTERNAL_ERROR;
2601 #if WITH_PC_MONITORING
2602 sh_css_print("PC_MONITORING: %s() irq = %d, "
2603 "sh_binary_running set to 0\n", __func__, irq);
2604 sh_binary_running = 0 ;
2609 /* When SP goes to idle, info is available in the
2611 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2615 #if !defined(HAS_NO_INPUT_SYSTEM)
2617 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2620 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2623 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2626 #if !defined(HAS_NO_INPUT_FORMATTER)
2628 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2632 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2635 infos |= sh_css_get_sw_interrupt_value(0);
2638 infos |= sh_css_get_sw_interrupt_value(1);
2639 /* pqiao TODO: also assumption here */
2649 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_irq_translate() "
2650 "leave: irq_infos=%u\n", infos);
2652 return IA_CSS_SUCCESS;
2655 enum ia_css_err ia_css_irq_enable(
2656 enum ia_css_irq_info info,
2659 virq_id_t irq = N_virq_id;
2660 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2663 #if !defined(HAS_NO_INPUT_FORMATTER)
2664 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2665 irq = virq_isys_sof;
2667 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2668 irq = virq_isys_eof;
2670 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2671 irq = virq_isys_csi;
2674 #if !defined(HAS_NO_INPUT_FORMATTER)
2675 case IA_CSS_IRQ_INFO_IF_ERROR:
2676 irq = virq_ifmt0_id;
2679 case IA_CSS_IRQ_INFO_DMA_ERROR:
2682 case IA_CSS_IRQ_INFO_SW_0:
2683 irq = virq_sw_pin_0;
2685 case IA_CSS_IRQ_INFO_SW_1:
2686 irq = virq_sw_pin_1;
2689 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2690 return IA_CSS_ERR_INVALID_ARGUMENTS;
2693 cnd_virq_enable_channel(irq, enable);
2695 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS);
2696 return IA_CSS_SUCCESS;
2700 #error "sh_css.c: IRQ MAP must be one of \
2701 {IRQ_MAP_VERSION_2}"
2705 sh_css_get_sw_interrupt_value(unsigned int irq)
2707 unsigned int irq_value;
2708 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() enter: irq=%d\n",irq);
2709 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2710 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n",irq_value);
2714 /* configure and load the copy binary, the next binary is used to
2715 determine whether the copy binary needs to do left padding. */
2716 static enum ia_css_err load_copy_binary(
2717 struct ia_css_pipe *pipe,
2718 struct ia_css_binary *copy_binary,
2719 struct ia_css_binary *next_binary)
2721 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2722 unsigned int left_padding;
2723 enum ia_css_err err;
2724 struct ia_css_binary_descr copy_descr;
2726 /* next_binary can be NULL */
2727 assert(pipe != NULL);
2728 assert(copy_binary != NULL);
2729 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2730 "load_copy_binary() enter:\n");
2732 if (next_binary != NULL) {
2733 copy_out_info = next_binary->in_frame_info;
2734 left_padding = next_binary->left_padding;
2736 copy_out_info = pipe->output_info[0];
2737 copy_vf_info = pipe->vf_output_info[0];
2738 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2742 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2743 ©_in_info, ©_out_info, (next_binary != NULL) ? NULL : NULL/*TODO: ©_vf_info*/);
2744 err = ia_css_binary_find(©_descr, copy_binary);
2745 if (err != IA_CSS_SUCCESS)
2747 copy_binary->left_padding = left_padding;
2748 return IA_CSS_SUCCESS;
2751 static enum ia_css_err
2752 alloc_continuous_frames(
2753 struct ia_css_pipe *pipe, bool init_time)
2755 enum ia_css_err err = IA_CSS_SUCCESS;
2756 struct ia_css_frame_info ref_info;
2757 enum ia_css_pipe_id pipe_id;
2759 unsigned int i, idx;
2760 unsigned int num_frames;
2761 struct ia_css_pipe *capture_pipe = NULL;
2763 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2765 if ((pipe == NULL) || (pipe->stream == NULL)) {
2766 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2767 return IA_CSS_ERR_INVALID_ARGUMENTS;
2770 pipe_id = pipe->mode;
2771 continuous = pipe->stream->config.continuous;
2775 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2776 pipe->stream->continuous_pipe = pipe;
2778 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2780 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2783 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2784 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2785 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2786 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2789 /* should not happen */
2790 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2791 return IA_CSS_ERR_INTERNAL_ERROR;
2794 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2795 /* For CSI2+, the continuous frame will hold the full input frame */
2796 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2797 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2799 /* Ensure padded width is aligned for 2401 */
2800 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2803 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2804 if (pipe->stream->config.pack_raw_pixels) {
2805 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2806 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2807 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2811 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2812 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2813 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2816 /* Write format back to binary */
2817 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
2818 pipe->pipe_settings.preview.preview_binary.in_frame_info.format = ref_info.format;
2819 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2820 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO) {
2821 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2822 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2824 /* should not happen */
2825 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2826 return IA_CSS_ERR_INTERNAL_ERROR;
2832 idx = pipe->stream->config.init_num_cont_raw_buf;
2834 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++) {
2835 /* free previous frame */
2836 if (pipe->continuous_frames[i]) {
2837 ia_css_frame_free(pipe->continuous_frames[i]);
2838 pipe->continuous_frames[i] = NULL;
2840 /* free previous metadata buffer */
2841 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2842 pipe->cont_md_buffers[i] = NULL;
2844 /* check if new frame needed */
2845 if (i < num_frames) {
2846 /* allocate new frame */
2847 err = ia_css_frame_allocate_from_info(
2848 &pipe->continuous_frames[i],
2850 if (err != IA_CSS_SUCCESS) {
2851 IA_CSS_LEAVE_ERR_PRIVATE(err);
2854 /* allocate metadata buffer */
2855 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2856 &pipe->stream->info.metadata_info);
2859 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
2860 return IA_CSS_SUCCESS;
2864 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream)
2867 return IA_CSS_ERR_INVALID_ARGUMENTS;
2868 return alloc_continuous_frames(stream->continuous_pipe, false);
2871 static enum ia_css_err
2872 load_preview_binaries(struct ia_css_pipe *pipe)
2874 struct ia_css_frame_info prev_in_info,
2878 struct ia_css_binary_descr preview_descr;
2880 enum ia_css_err err = IA_CSS_SUCCESS;
2881 bool continuous, need_vf_pp = false;
2882 bool need_isp_copy_binary = false;
2883 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2884 bool sensor = false;
2886 /* preview only have 1 output pin now */
2887 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2888 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2890 IA_CSS_ENTER_PRIVATE("");
2891 assert(pipe != NULL);
2892 assert(pipe->stream != NULL);
2893 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2895 online = pipe->stream->config.online;
2896 continuous = pipe->stream->config.continuous;
2897 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2898 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2901 if (mycs->preview_binary.info)
2902 return IA_CSS_SUCCESS;
2904 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2905 if (err != IA_CSS_SUCCESS)
2907 err = ia_css_frame_check_info(pipe_out_info);
2908 if (err != IA_CSS_SUCCESS)
2911 /* Note: the current selection of vf_pp binary and
2912 * parameterization of the preview binary contains a few pieces
2913 * of hardcoded knowledge. This needs to be cleaned up such that
2914 * the binary selection becomes more generic.
2915 * The vf_pp binary is needed if one or more of the following features
2917 * 1. YUV downscaling.
2919 * 3. An output format that is not supported by the preview binary.
2920 * In practice this means something other than yuv_line or nv12.
2921 * The decision if the vf_pp binary is needed for YUV downscaling is
2922 * made after the preview binary selection, since some preview binaries
2923 * can perform the requested YUV downscaling.
2925 need_vf_pp = pipe->config.enable_dz;
2926 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2927 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2928 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2929 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2931 /* Preview step 1 */
2932 if (pipe->vf_yuv_ds_input_info.res.width)
2933 prev_vf_info = pipe->vf_yuv_ds_input_info;
2935 prev_vf_info = *pipe_out_info;
2936 /* If vf_pp is needed, then preview must output yuv_line.
2937 * The exception is when vf_pp is manually disabled, that is only
2938 * used in combination with a pipeline extension that requires
2939 * yuv_line as input.
2942 ia_css_frame_info_set_format(&prev_vf_info,
2943 IA_CSS_FRAME_FORMAT_YUV_LINE);
2945 err = ia_css_pipe_get_preview_binarydesc(
2952 if (err != IA_CSS_SUCCESS)
2954 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2955 if (err != IA_CSS_SUCCESS)
2959 /* The delay latency determines the number of invalid frames after
2960 * a stream is started. */
2961 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2962 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2964 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2965 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2966 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2969 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2970 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2971 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2973 /* When vf_pp is needed, then the output format of the selected
2974 * preview binary must be yuv_line. If this is not the case,
2975 * then the preview binary selection is done again.
2978 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE)) {
2980 /* Preview step 2 */
2981 if (pipe->vf_yuv_ds_input_info.res.width)
2982 prev_vf_info = pipe->vf_yuv_ds_input_info;
2984 prev_vf_info = *pipe_out_info;
2986 ia_css_frame_info_set_format(&prev_vf_info,
2987 IA_CSS_FRAME_FORMAT_YUV_LINE);
2989 err = ia_css_pipe_get_preview_binarydesc(
2996 if (err != IA_CSS_SUCCESS)
2998 err = ia_css_binary_find(&preview_descr,
2999 &mycs->preview_binary);
3000 if (err != IA_CSS_SUCCESS)
3005 struct ia_css_binary_descr vf_pp_descr;
3007 /* Viewfinder post-processing */
3008 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
3009 &mycs->preview_binary.out_frame_info[0],
3011 err = ia_css_binary_find(&vf_pp_descr,
3012 &mycs->vf_pp_binary);
3013 if (err != IA_CSS_SUCCESS)
3017 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3018 /* When the input system is 2401, only the Direct Sensor Mode
3019 * Offline Preview uses the ISP copy binary.
3021 need_isp_copy_binary = !online && sensor;
3024 need_isp_copy_binary = !online && !continuous;
3026 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3027 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3028 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3029 * copies sensor data to DDR) does not have much use.
3031 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3036 if (need_isp_copy_binary) {
3037 err = load_copy_binary(pipe,
3039 &mycs->preview_binary);
3040 if (err != IA_CSS_SUCCESS)
3044 if (pipe->shading_table) {
3045 ia_css_shading_table_free(pipe->shading_table);
3046 pipe->shading_table = NULL;
3049 return IA_CSS_SUCCESS;
3053 ia_css_binary_unload(struct ia_css_binary *binary)
3055 ia_css_binary_destroy_isp_parameters(binary);
3058 static enum ia_css_err
3059 unload_preview_binaries(struct ia_css_pipe *pipe)
3061 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3063 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3064 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3065 return IA_CSS_ERR_INVALID_ARGUMENTS;
3067 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3068 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3069 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3071 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
3072 return IA_CSS_SUCCESS;
3075 static const struct ia_css_fw_info *last_output_firmware(
3076 const struct ia_css_fw_info *fw)
3078 const struct ia_css_fw_info *last_fw = NULL;
3079 /* fw can be NULL */
3080 IA_CSS_ENTER_LEAVE_PRIVATE("");
3082 for (; fw; fw = fw->next) {
3083 const struct ia_css_fw_info *info = fw;
3084 if (info->info.isp.sp.enable.output)
3090 static enum ia_css_err add_firmwares(
3091 struct ia_css_pipeline *me,
3092 struct ia_css_binary *binary,
3093 const struct ia_css_fw_info *fw,
3094 const struct ia_css_fw_info *last_fw,
3095 unsigned int binary_mode,
3096 struct ia_css_frame *in_frame,
3097 struct ia_css_frame *out_frame,
3098 struct ia_css_frame *vf_frame,
3099 struct ia_css_pipeline_stage **my_stage,
3100 struct ia_css_pipeline_stage **vf_stage)
3102 enum ia_css_err err = IA_CSS_SUCCESS;
3103 struct ia_css_pipeline_stage *extra_stage = NULL;
3104 struct ia_css_pipeline_stage_desc stage_desc;
3106 /* all args can be NULL ??? */
3107 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3108 "add_firmwares() enter:\n");
3110 for (; fw; fw = fw->next) {
3111 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3112 struct ia_css_frame *in = NULL;
3113 struct ia_css_frame *vf = NULL;
3114 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3117 if (fw->info.isp.sp.enable.in_frame != 0) {
3120 if (fw->info.isp.sp.enable.out_frame != 0) {
3123 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3124 out, in, vf, fw, binary_mode);
3125 err = ia_css_pipeline_create_and_add_stage(me,
3128 if (err != IA_CSS_SUCCESS)
3130 if (fw->info.isp.sp.enable.output != 0)
3131 in_frame = extra_stage->args.out_frame[0];
3132 if (my_stage && !*my_stage && extra_stage)
3133 *my_stage = extra_stage;
3134 if (vf_stage && !*vf_stage && extra_stage &&
3135 fw->info.isp.sp.enable.vf_veceven)
3136 *vf_stage = extra_stage;
3141 static enum ia_css_err add_vf_pp_stage(
3142 struct ia_css_pipe *pipe,
3143 struct ia_css_frame *in_frame,
3144 struct ia_css_frame *out_frame,
3145 struct ia_css_binary *vf_pp_binary,
3146 struct ia_css_pipeline_stage **vf_pp_stage)
3149 struct ia_css_pipeline *me = NULL;
3150 const struct ia_css_fw_info *last_fw = NULL;
3151 enum ia_css_err err = IA_CSS_SUCCESS;
3152 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3153 struct ia_css_pipeline_stage_desc stage_desc;
3155 /* out_frame can be NULL ??? */
3158 return IA_CSS_ERR_INVALID_ARGUMENTS;
3159 if (in_frame == NULL)
3160 return IA_CSS_ERR_INVALID_ARGUMENTS;
3161 if (vf_pp_binary == NULL)
3162 return IA_CSS_ERR_INVALID_ARGUMENTS;
3163 if (vf_pp_stage == NULL)
3164 return IA_CSS_ERR_INVALID_ARGUMENTS;
3166 ia_css_pipe_util_create_output_frames(out_frames);
3167 me = &pipe->pipeline;
3169 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3170 "add_vf_pp_stage() enter:\n");
3172 *vf_pp_stage = NULL;
3174 last_fw = last_output_firmware(pipe->vf_stage);
3175 if (!pipe->extra_config.disable_vf_pp) {
3177 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3178 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3179 out_frames, in_frame, NULL);
3181 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3182 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3183 out_frames, in_frame, NULL);
3185 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3186 if (err != IA_CSS_SUCCESS)
3188 in_frame = (*vf_pp_stage)->args.out_frame[0];
3190 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3191 IA_CSS_BINARY_MODE_VF_PP,
3192 in_frame, out_frame, NULL,
3197 static enum ia_css_err add_yuv_scaler_stage(
3198 struct ia_css_pipe *pipe,
3199 struct ia_css_pipeline *me,
3200 struct ia_css_frame *in_frame,
3201 struct ia_css_frame *out_frame,
3202 struct ia_css_frame *internal_out_frame,
3203 struct ia_css_binary *yuv_scaler_binary,
3204 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3206 const struct ia_css_fw_info *last_fw;
3207 enum ia_css_err err = IA_CSS_SUCCESS;
3208 struct ia_css_frame *vf_frame = NULL;
3209 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3210 struct ia_css_pipeline_stage_desc stage_desc;
3212 /* out_frame can be NULL ??? */
3213 assert(in_frame != NULL);
3214 assert(pipe != NULL);
3216 assert(yuv_scaler_binary != NULL);
3217 assert(pre_vf_pp_stage != NULL);
3218 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3219 "add_yuv_scaler_stage() enter:\n");
3221 *pre_vf_pp_stage = NULL;
3222 ia_css_pipe_util_create_output_frames(out_frames);
3224 last_fw = last_output_firmware(pipe->output_stage);
3227 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3228 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3229 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3231 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3232 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3233 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3234 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3236 err = ia_css_pipeline_create_and_add_stage(me,
3239 if (err != IA_CSS_SUCCESS)
3241 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3243 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3244 IA_CSS_BINARY_MODE_CAPTURE_PP,
3245 in_frame, out_frame, vf_frame,
3246 NULL, pre_vf_pp_stage);
3247 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3248 (*pre_vf_pp_stage)->args.vf_downscale_log2 = yuv_scaler_binary->vf_downscale_log2;
3250 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3251 "add_yuv_scaler_stage() leave:\n");
3255 static enum ia_css_err add_capture_pp_stage(
3256 struct ia_css_pipe *pipe,
3257 struct ia_css_pipeline *me,
3258 struct ia_css_frame *in_frame,
3259 struct ia_css_frame *out_frame,
3260 struct ia_css_binary *capture_pp_binary,
3261 struct ia_css_pipeline_stage **capture_pp_stage)
3263 const struct ia_css_fw_info *last_fw = NULL;
3264 enum ia_css_err err = IA_CSS_SUCCESS;
3265 struct ia_css_frame *vf_frame = NULL;
3266 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3267 struct ia_css_pipeline_stage_desc stage_desc;
3269 /* out_frame can be NULL ??? */
3270 assert(in_frame != NULL);
3271 assert(pipe != NULL);
3273 assert(capture_pp_binary != NULL);
3274 assert(capture_pp_stage != NULL);
3275 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3276 "add_capture_pp_stage() enter:\n");
3278 *capture_pp_stage = NULL;
3279 ia_css_pipe_util_create_output_frames(out_frames);
3281 last_fw = last_output_firmware(pipe->output_stage);
3282 err = ia_css_frame_allocate_from_info(&vf_frame,
3283 &capture_pp_binary->vf_frame_info);
3284 if (err != IA_CSS_SUCCESS)
3287 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3288 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3289 capture_pp_binary, out_frames, NULL, vf_frame);
3291 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3292 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3293 capture_pp_binary, out_frames, NULL, vf_frame);
3295 err = ia_css_pipeline_create_and_add_stage(me,
3298 if (err != IA_CSS_SUCCESS)
3300 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3301 IA_CSS_BINARY_MODE_CAPTURE_PP,
3302 in_frame, out_frame, vf_frame,
3303 NULL, capture_pp_stage);
3304 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3305 if (*capture_pp_stage) {
3306 (*capture_pp_stage)->args.vf_downscale_log2 =
3307 capture_pp_binary->vf_downscale_log2;
3312 static void sh_css_setup_queues(void)
3314 const struct ia_css_fw_info *fw;
3315 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3317 sh_css_hmm_buffer_record_init();
3319 sh_css_event_init_irq_mask();
3322 HIVE_ADDR_host_sp_queues_initialized =
3323 fw->info.sp.host_sp_queues_initialized;
3327 /* set "host_sp_queues_initialized" to "true" */
3328 sp_dmem_store_uint32(SP0_ID,
3329 (unsigned int)sp_address_of(host_sp_queues_initialized),
3331 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3334 static enum ia_css_err
3335 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3336 struct ia_css_frame *vf_frame, unsigned int idx)
3338 enum ia_css_err err = IA_CSS_SUCCESS;
3339 unsigned int thread_id;
3340 enum sh_css_queue_id queue_id;
3342 assert(vf_frame != NULL);
3344 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3345 vf_frame->contiguous = false;
3346 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3347 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3348 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3349 vf_frame->dynamic_queue_id = queue_id;
3350 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3352 err = ia_css_frame_init_planes(vf_frame);
3356 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3358 get_crop_lines_for_bayer_order (
3359 const struct ia_css_stream_config *config)
3361 assert(config != NULL);
3362 if ((IA_CSS_BAYER_ORDER_BGGR == config->input_config.bayer_order)
3363 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3370 get_crop_columns_for_bayer_order (
3371 const struct ia_css_stream_config *config)
3373 assert(config != NULL);
3374 if ((IA_CSS_BAYER_ORDER_RGGB == config->input_config.bayer_order)
3375 || (IA_CSS_BAYER_ORDER_GBRG == config->input_config.bayer_order))
3381 /* This function is to get the sum of all extra pixels in addition to the effective
3382 * input, it includes dvs envelop and filter run-in */
3383 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3384 unsigned int *extra_row, unsigned int *extra_column)
3386 enum ia_css_pipe_id pipe_id = pipe->mode;
3387 unsigned int left_cropping = 0, top_cropping = 0;
3389 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3391 /* The dvs envelope info may not be correctly sent down via pipe config
3392 * The check is made and the correct value is populated in the binary info
3393 * Use this value when computing crop, else excess lines may get trimmed
3396 case IA_CSS_PIPE_ID_PREVIEW:
3397 if (pipe->pipe_settings.preview.preview_binary.info) {
3398 left_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3399 top_cropping = pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3401 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3403 case IA_CSS_PIPE_ID_VIDEO:
3404 if (pipe->pipe_settings.video.video_binary.info) {
3405 left_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3406 top_cropping = pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3408 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3410 case IA_CSS_PIPE_ID_CAPTURE:
3411 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3412 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3413 left_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3414 top_cropping += pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3416 dvs_env.width += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3417 dvs_env.height += pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3424 *extra_row = top_cropping + dvs_env.height;
3425 *extra_column = left_cropping + dvs_env.width;
3429 ia_css_get_crop_offsets (
3430 struct ia_css_pipe *pipe,
3431 struct ia_css_frame_info *in_frame)
3433 unsigned int row = 0;
3434 unsigned int column = 0;
3435 struct ia_css_resolution *input_res;
3436 struct ia_css_resolution *effective_res;
3437 unsigned int extra_row = 0, extra_col = 0;
3438 unsigned int min_reqd_height, min_reqd_width;
3440 assert(pipe != NULL);
3441 assert(pipe->stream != NULL);
3442 assert(in_frame != NULL);
3444 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3445 pipe, pipe->config.input_effective_res.width,
3446 pipe->config.input_effective_res.height);
3448 input_res = &pipe->stream->config.input_config.input_res;
3450 effective_res = &pipe->stream->config.input_config.effective_res;
3452 effective_res = &pipe->config.input_effective_res;
3455 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3457 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3459 min_reqd_height = effective_res->height + extra_row;
3460 min_reqd_width = effective_res->width + extra_col;
3462 if (input_res->height > min_reqd_height) {
3463 row = (input_res->height - min_reqd_height) / 2;
3466 if (input_res->width > min_reqd_width) {
3467 column = (input_res->width - min_reqd_width) / 2;
3473 * 1. Require the special support for RAW10 packed mode.
3474 * 2. Require the special support for the online use cases.
3477 /* ISP expects GRBG bayer order, we skip one line and/or one row
3478 * to correct in case the input bayer order is different.
3480 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3481 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3483 in_frame->crop_info.start_column = column;
3484 in_frame->crop_info.start_line = row;
3486 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3492 static enum ia_css_err
3493 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3494 struct ia_css_frame *frame, enum ia_css_frame_format format)
3496 struct ia_css_frame *in_frame;
3497 enum ia_css_err err = IA_CSS_SUCCESS;
3498 unsigned int thread_id;
3499 enum sh_css_queue_id queue_id;
3501 assert(frame != NULL);
3504 in_frame->info.format = format;
3506 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3507 if (format == IA_CSS_FRAME_FORMAT_RAW)
3508 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3509 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3513 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3514 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3515 in_frame->info.raw_bit_depth =
3516 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3517 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3518 in_frame->contiguous = false;
3519 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3520 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3521 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3522 in_frame->dynamic_queue_id = queue_id;
3523 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3524 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3525 ia_css_get_crop_offsets(pipe, &in_frame->info);
3527 err = ia_css_frame_init_planes(in_frame);
3529 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3530 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3535 static enum ia_css_err
3536 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3537 struct ia_css_frame *out_frame, unsigned int idx)
3539 enum ia_css_err err = IA_CSS_SUCCESS;
3540 unsigned int thread_id;
3541 enum sh_css_queue_id queue_id;
3543 assert(out_frame != NULL);
3545 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3546 out_frame->contiguous = false;
3547 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3548 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3549 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3550 out_frame->dynamic_queue_id = queue_id;
3551 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3552 err = ia_css_frame_init_planes(out_frame);
3557 /* Create stages for video pipe */
3558 static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe)
3560 struct ia_css_pipeline_stage_desc stage_desc;
3561 struct ia_css_binary *copy_binary, *video_binary,
3562 *yuv_scaler_binary, *vf_pp_binary;
3563 struct ia_css_pipeline_stage *copy_stage = NULL;
3564 struct ia_css_pipeline_stage *video_stage = NULL;
3565 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3566 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3567 struct ia_css_pipeline *me;
3568 struct ia_css_frame *in_frame = NULL;
3569 struct ia_css_frame *out_frame;
3570 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3571 struct ia_css_frame *vf_frame = NULL;
3572 enum ia_css_err err = IA_CSS_SUCCESS;
3573 bool need_copy = false;
3574 bool need_vf_pp = false;
3575 bool need_yuv_pp = false;
3576 unsigned num_output_pins;
3577 bool need_in_frameinfo_memory = false;
3579 unsigned int i, num_yuv_scaler;
3580 bool *is_output_stage = NULL;
3582 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3583 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3584 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3585 return IA_CSS_ERR_INVALID_ARGUMENTS;
3587 ia_css_pipe_util_create_output_frames(out_frames);
3588 out_frame = &pipe->out_frame_struct;
3590 /* pipeline already created as part of create_host_pipeline_structure */
3591 me = &pipe->pipeline;
3592 ia_css_pipeline_clean(me);
3594 me->dvs_frame_delay = pipe->dvs_frame_delay;
3596 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3597 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3598 * except for the following: online or continuous
3600 need_in_frameinfo_memory = !(pipe->stream->config.online || pipe->stream->config.continuous);
3602 /* Construct in_frame info (only in case we have dynamic input */
3603 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3606 /* Construct in_frame info (only in case we have dynamic input */
3607 if (need_in_frameinfo_memory) {
3608 in_frame = &pipe->in_frame_struct;
3609 err = init_in_frameinfo_memory_defaults(pipe, in_frame, IA_CSS_FRAME_FORMAT_RAW);
3610 if (err != IA_CSS_SUCCESS)
3614 out_frame->data = 0;
3615 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3616 if (err != IA_CSS_SUCCESS)
3619 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3620 vf_frame = &pipe->vf_frame_struct;
3622 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3623 if (err != IA_CSS_SUCCESS)
3627 copy_binary = &pipe->pipe_settings.video.copy_binary;
3628 video_binary = &pipe->pipe_settings.video.video_binary;
3629 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3630 num_output_pins = video_binary->info->num_output_pins;
3632 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3633 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3634 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3636 need_copy = (copy_binary != NULL && copy_binary->info != NULL);
3637 need_vf_pp = (vf_pp_binary != NULL && vf_pp_binary->info != NULL);
3638 need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL);
3641 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3642 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3643 out_frames, NULL, NULL);
3644 err = ia_css_pipeline_create_and_add_stage(me,
3647 if (err != IA_CSS_SUCCESS)
3649 in_frame = me->stages->args.out_frame[0];
3650 } else if (pipe->stream->config.continuous) {
3651 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3652 /* When continuous is enabled, configure in_frame with the
3653 * last pipe, which is the copy pipe.
3655 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3657 in_frame = pipe->continuous_frames[0];
3661 ia_css_pipe_util_set_output_frames(out_frames, 0, need_yuv_pp ? NULL : out_frame);
3663 /* when the video binary supports a second output pin,
3664 it can directly produce the vf_frame. */
3666 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3667 out_frames, in_frame, NULL);
3669 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3670 out_frames, in_frame, vf_frame);
3672 err = ia_css_pipeline_create_and_add_stage(me,
3675 if (err != IA_CSS_SUCCESS)
3678 /* If we use copy iso video, the input must be yuv iso raw */
3680 video_stage->args.copy_vf =
3681 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3682 video_stage->args.copy_output = video_stage->args.copy_vf;
3685 /* when the video binary supports only 1 output pin, vf_pp is needed to
3686 produce the vf_frame.*/
3687 if (need_vf_pp && video_stage) {
3688 in_frame = video_stage->args.out_vf_frame;
3689 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3691 if (err != IA_CSS_SUCCESS)
3697 for (frm = 0; frm < NUM_VIDEO_TNR_FRAMES; frm++) {
3699 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3701 video_stage->args.tnr_frames[frm] =
3702 pipe->pipe_settings.video.tnr_frames[frm];
3704 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3705 video_stage->args.delay_frames[frm] =
3706 pipe->pipe_settings.video.delay_frames[frm];
3710 /* Append Extension on Video out, if enabled */
3711 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3712 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT))
3714 struct ia_css_frame *out = NULL;
3715 struct ia_css_frame *in = NULL;
3717 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3718 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3719 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3721 /* In/Out Frame mapping to support output frame extension.*/
3722 out = video_stage->args.out_frame[0];
3723 err = ia_css_frame_allocate_from_info(&in, &(pipe->output_info[0]));
3724 if (err != IA_CSS_SUCCESS)
3726 video_stage->args.out_frame[0] = in;
3729 err = add_firmwares( me, video_binary, pipe->output_stage,
3730 last_output_firmware(pipe->output_stage),
3731 IA_CSS_BINARY_MODE_VIDEO,
3732 in, out, NULL, &video_stage, NULL);
3733 if (err != IA_CSS_SUCCESS)
3737 if (need_yuv_pp && video_stage) {
3738 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3739 struct ia_css_frame *tmp_out_frame = NULL;
3741 for (i = 0; i < num_yuv_scaler; i++) {
3742 if (is_output_stage[i] == true) {
3743 tmp_out_frame = out_frame;
3745 tmp_out_frame = NULL;
3747 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3749 &yuv_scaler_binary[i],
3752 if (err != IA_CSS_SUCCESS) {
3753 IA_CSS_LEAVE_ERR_PRIVATE(err);
3756 /* we use output port 1 as internal output port */
3757 if (yuv_scaler_stage)
3758 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3762 pipe->pipeline.acquire_isp_each_stage = false;
3763 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3766 IA_CSS_LEAVE_ERR_PRIVATE(err);
3770 static enum ia_css_err
3771 create_host_acc_pipeline(struct ia_css_pipe *pipe)
3773 enum ia_css_err err = IA_CSS_SUCCESS;
3774 const struct ia_css_fw_info *fw;
3777 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3778 if ((pipe == NULL) || (pipe->stream == NULL)) {
3779 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3780 return IA_CSS_ERR_INVALID_ARGUMENTS;
3783 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3784 /* Reset pipe_qos_config to default disable all QOS extension stages */
3785 if (pipe->config.acc_extension)
3786 pipe->pipeline.pipe_qos_config = 0;
3788 fw = pipe->vf_stage;
3789 for (i = 0; fw; fw = fw->next){
3790 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3791 if (err != IA_CSS_SUCCESS)
3795 for (i=0; i<pipe->config.num_acc_stages; i++) {
3796 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3797 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3798 if (err != IA_CSS_SUCCESS)
3802 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3805 IA_CSS_LEAVE_ERR_PRIVATE(err);
3809 /* Create stages for preview */
3810 static enum ia_css_err
3811 create_host_preview_pipeline(struct ia_css_pipe *pipe)
3813 struct ia_css_pipeline_stage *copy_stage = NULL;
3814 struct ia_css_pipeline_stage *preview_stage = NULL;
3815 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3816 struct ia_css_pipeline_stage_desc stage_desc;
3817 struct ia_css_pipeline *me = NULL;
3818 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3819 struct ia_css_frame *in_frame = NULL;
3820 enum ia_css_err err = IA_CSS_SUCCESS;
3821 struct ia_css_frame *out_frame;
3822 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3823 bool need_in_frameinfo_memory = false;
3824 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3825 bool sensor = false;
3826 bool buffered_sensor = false;
3827 bool online = false;
3828 bool continuous = false;
3831 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3832 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3833 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3834 return IA_CSS_ERR_INVALID_ARGUMENTS;
3838 ia_css_pipe_util_create_output_frames(out_frames);
3839 /* pipeline already created as part of create_host_pipeline_structure */
3840 me = &pipe->pipeline;
3841 ia_css_pipeline_clean(me);
3843 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3844 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3845 * except for the following:
3846 * - Direct Sensor Mode Online Preview
3847 * - Buffered Sensor Mode Online Preview
3848 * - Direct Sensor Mode Continuous Preview
3849 * - Buffered Sensor Mode Continuous Preview
3851 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3852 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3853 online = pipe->stream->config.online;
3854 continuous = pipe->stream->config.continuous;
3855 need_in_frameinfo_memory =
3856 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3858 /* Construct in_frame info (only in case we have dynamic input */
3859 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3861 if (need_in_frameinfo_memory) {
3862 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW);
3863 if (err != IA_CSS_SUCCESS)
3866 in_frame = &me->in_frame;
3871 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3872 if (err != IA_CSS_SUCCESS)
3874 out_frame = &me->out_frame[0];
3876 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3877 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3878 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3879 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3881 if (pipe->pipe_settings.preview.copy_binary.info) {
3882 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3883 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3884 out_frames, NULL, NULL);
3885 err = ia_css_pipeline_create_and_add_stage(me,
3888 if (err != IA_CSS_SUCCESS)
3890 in_frame = me->stages->args.out_frame[0];
3894 } else if (pipe->stream->config.continuous) {
3896 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3897 /* When continuous is enabled, configure in_frame with the
3898 * last pipe, which is the copy pipe.
3900 if (continuous || !online){
3901 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3904 in_frame = pipe->continuous_frames[0];
3909 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3910 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3911 out_frames, in_frame, NULL);
3913 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3914 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3915 out_frames, in_frame, NULL);
3917 err = ia_css_pipeline_create_and_add_stage(me,
3920 if (err != IA_CSS_SUCCESS)
3922 /* If we use copy iso preview, the input must be yuv iso raw */
3923 preview_stage->args.copy_vf =
3924 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3925 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3926 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame) {
3927 /* in case of copy, use the vf frame as output frame */
3928 preview_stage->args.out_vf_frame =
3929 preview_stage->args.out_frame[0];
3932 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3933 in_frame = preview_stage->args.out_vf_frame;
3935 in_frame = preview_stage->args.out_frame[0];
3936 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3938 if (err != IA_CSS_SUCCESS)
3942 pipe->pipeline.acquire_isp_each_stage = false;
3943 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3946 IA_CSS_LEAVE_ERR_PRIVATE(err);
3950 static void send_raw_frames(struct ia_css_pipe *pipe)
3952 if (pipe->stream->config.continuous) {
3955 sh_css_update_host2sp_cont_num_raw_frames
3956 (pipe->stream->config.init_num_cont_raw_buf, true);
3957 sh_css_update_host2sp_cont_num_raw_frames
3958 (pipe->stream->config.target_num_cont_raw_buf, false);
3960 /* Hand-over all the SP-internal buffers */
3961 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3962 sh_css_update_host2sp_offline_frame(i,
3963 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3970 static enum ia_css_err
3971 preview_start(struct ia_css_pipe *pipe)
3973 struct ia_css_pipeline *me ;
3974 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3975 enum ia_css_err err = IA_CSS_SUCCESS;
3976 struct ia_css_pipe *copy_pipe, *capture_pipe;
3977 struct ia_css_pipe *acc_pipe;
3978 enum sh_css_pipe_config_override copy_ovrd;
3979 enum ia_css_input_mode preview_pipe_input_mode;
3981 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3982 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) {
3983 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3984 return IA_CSS_ERR_INVALID_ARGUMENTS;
3987 me = &pipe->pipeline;
3989 preview_pipe_input_mode = pipe->stream->config.mode;
3991 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3992 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3993 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
3995 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3996 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3997 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3998 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4000 sh_css_metrics_start_frame();
4002 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4003 /* multi stream video needs mipi buffers */
4004 err = send_mipi_frames(pipe);
4005 if (err != IA_CSS_SUCCESS)
4008 send_raw_frames(pipe);
4011 unsigned int thread_id;
4013 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4014 copy_ovrd = 1 << thread_id;
4016 if (pipe->stream->cont_capt) {
4017 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4018 copy_ovrd |= 1 << thread_id;
4022 /* Construct and load the copy pipe */
4023 if (pipe->stream->config.continuous) {
4024 sh_css_sp_init_pipeline(©_pipe->pipeline,
4025 IA_CSS_PIPE_ID_COPY,
4026 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4028 pipe->stream->config.pixels_per_clock == 2, false,
4029 false, pipe->required_bds_factor,
4031 pipe->stream->config.mode,
4032 &pipe->stream->config.metadata_config,
4034 &pipe->stream->info.metadata_info
4036 &pipe->stream->info.metadata_info,
4038 #if !defined(HAS_NO_INPUT_SYSTEM)
4040 , pipe->stream->config.source.port.port
4042 pipe->stream->config.source.port.port,
4048 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4049 pipe->stream->isp_params_configs);
4052 /* make the preview pipe start with mem mode input, copy handles
4054 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4057 /* Construct and load the capture pipe */
4058 if (pipe->stream->cont_capt) {
4059 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4060 IA_CSS_PIPE_ID_CAPTURE,
4061 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4062 capture_pipe->config.default_capture_config.enable_xnr != 0,
4063 capture_pipe->stream->config.pixels_per_clock == 2,
4064 true, /* continuous */
4065 false, /* offline */
4066 capture_pipe->required_bds_factor,
4068 IA_CSS_INPUT_MODE_MEMORY,
4069 &pipe->stream->config.metadata_config,
4071 &pipe->stream->info.metadata_info
4073 &pipe->stream->info.metadata_info,
4075 #if !defined(HAS_NO_INPUT_SYSTEM)
4077 , (enum mipi_port_id)0
4079 (enum mipi_port_id)0,
4085 &capture_pipe->config.internal_frame_origin_bqs_on_sctbl,
4086 capture_pipe->stream->isp_params_configs);
4091 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4093 (uint8_t) ia_css_pipe_get_pipe_num(acc_pipe),
4095 pipe->stream->config.pixels_per_clock == 2,
4096 false, /* continuous */
4097 false, /* offline */
4098 pipe->required_bds_factor,
4100 IA_CSS_INPUT_MODE_MEMORY,
4107 #if !defined(HAS_NO_INPUT_SYSTEM)
4109 , (enum mipi_port_id) 0
4111 (enum mipi_port_id) 0,
4117 &pipe->config.internal_frame_origin_bqs_on_sctbl,
4118 pipe->stream->isp_params_configs);
4122 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4124 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4127 IA_CSS_LEAVE_ERR_PRIVATE(err);
4132 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4133 const struct ia_css_buffer *buffer)
4135 enum ia_css_err return_err = IA_CSS_SUCCESS;
4136 unsigned int thread_id;
4137 enum sh_css_queue_id queue_id;
4138 struct ia_css_pipeline *pipeline;
4139 struct ia_css_pipeline_stage *stage;
4140 struct ia_css_rmgr_vbuf_handle p_vbuf;
4141 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4142 struct sh_css_hmm_buffer ddr_buffer;
4143 enum ia_css_buffer_type buf_type;
4144 enum ia_css_pipe_id pipe_id;
4147 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4149 if ((pipe == NULL) || (buffer == NULL)) {
4150 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4151 return IA_CSS_ERR_INVALID_ARGUMENTS;
4154 buf_type = buffer->type;
4155 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4158 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4159 bool found_pipe = false;
4160 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4161 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4162 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4169 return IA_CSS_ERR_INVALID_ARGUMENTS;
4171 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) {
4172 bool found_pipe = false;
4173 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4174 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4175 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4182 return IA_CSS_ERR_INVALID_ARGUMENTS;
4185 pipe_id = pipe->mode;
4187 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4190 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4191 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4192 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4193 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4194 (pipe_id >= IA_CSS_PIPE_ID_NUM)) {
4195 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4196 return IA_CSS_ERR_INTERNAL_ERROR;
4199 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4201 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4202 return IA_CSS_ERR_INVALID_ARGUMENTS;
4205 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4207 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4208 return IA_CSS_ERR_INVALID_ARGUMENTS;
4211 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4212 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4213 return IA_CSS_ERR_INVALID_ARGUMENTS;
4216 if (!sh_css_sp_is_running()) {
4217 IA_CSS_LOG("SP is not running!");
4218 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4219 /* SP is not running. The queues are not valid */
4220 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4224 pipeline = &pipe->pipeline;
4226 assert(pipeline != NULL ||
4227 pipe_id == IA_CSS_PIPE_ID_COPY ||
4228 pipe_id == IA_CSS_PIPE_ID_ACC);
4230 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4231 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4232 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4233 ddr_buffer.timing_data = buffer->timing_data;
4235 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS) {
4236 if (buffer->data.stats_3a == NULL) {
4237 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4238 return IA_CSS_ERR_INVALID_ARGUMENTS;
4240 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4241 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4242 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS) {
4243 if (buffer->data.stats_dvs == NULL) {
4244 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4245 return IA_CSS_ERR_INVALID_ARGUMENTS;
4247 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4248 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4249 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA) {
4250 if (buffer->data.metadata == NULL) {
4251 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4252 return IA_CSS_ERR_INVALID_ARGUMENTS;
4254 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4255 ddr_buffer.payload.metadata = *buffer->data.metadata;
4256 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4257 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4258 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4259 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4260 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)) {
4261 if (buffer->data.frame == 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.frame);
4266 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4267 ddr_buffer.payload.frame.flashed = 0;
4269 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4270 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4271 buf_type, buffer->data.frame->data);
4274 #if CONFIG_ON_FRAME_ENQUEUE()
4275 return_err = set_config_on_frame_enqueue(
4276 &buffer->data.frame->info,
4277 &ddr_buffer.payload.frame);
4278 if (IA_CSS_SUCCESS != return_err) {
4279 IA_CSS_LEAVE_ERR(return_err);
4285 /* start of test for using rmgr for acq/rel memory */
4288 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4290 /* TODO: change next to correct pool for optimization */
4291 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4293 assert(h_vbuf != NULL);
4294 assert(h_vbuf->vptr != 0x0);
4296 if ((h_vbuf == NULL) || (h_vbuf->vptr == 0x0)) {
4297 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4298 return IA_CSS_ERR_INTERNAL_ERROR;
4301 mmgr_store(h_vbuf->vptr,
4302 (void *)(&ddr_buffer),
4303 sizeof(struct sh_css_hmm_buffer));
4304 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4305 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4306 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS)) {
4307 if (pipeline == NULL) {
4308 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4309 IA_CSS_LOG("pipeline is empty!");
4310 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4311 return IA_CSS_ERR_INTERNAL_ERROR;
4314 for (stage = pipeline->stages; stage; stage = stage->next) {
4315 /* The SP will read the params
4316 after it got empty 3a and dis */
4317 if (STATS_ENABLED(stage)) {
4318 /* there is a stage that needs it */
4319 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4321 (uint32_t)h_vbuf->vptr);
4324 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4325 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4326 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4327 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4328 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4329 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA)) {
4331 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4333 (uint32_t)h_vbuf->vptr);
4334 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4335 if ((return_err == IA_CSS_SUCCESS) && (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type)) {
4336 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4337 ddr_buffer.payload.frame.frame_data,
4338 queue_id, thread_id);
4344 if (return_err == IA_CSS_SUCCESS) {
4345 if (sh_css_hmm_buffer_record_acquire(
4347 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4348 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4350 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4351 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4356 * Tell the SP which queues are not empty,
4357 * by sending the software event.
4359 if (return_err == IA_CSS_SUCCESS) {
4360 if (!sh_css_sp_is_running()) {
4361 /* SP is not running. The queues are not valid */
4362 IA_CSS_LOG("SP is not running!");
4363 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4364 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4366 return_err = ia_css_bufq_enqueue_psys_event(
4367 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4372 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4373 IA_CSS_ERROR("buffer not enqueued");
4376 IA_CSS_LEAVE("return value = %d", return_err);
4382 * TODO: Free up the hmm memory space.
4385 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4386 struct ia_css_buffer *buffer)
4388 enum ia_css_err return_err;
4389 enum sh_css_queue_id queue_id;
4390 hrt_vaddress ddr_buffer_addr = (hrt_vaddress)0;
4391 struct sh_css_hmm_buffer ddr_buffer;
4392 enum ia_css_buffer_type buf_type;
4393 enum ia_css_pipe_id pipe_id;
4394 unsigned int thread_id;
4395 hrt_address kernel_ptr = 0;
4398 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4400 if ((pipe == NULL) || (buffer == NULL)) {
4401 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4402 return IA_CSS_ERR_INVALID_ARGUMENTS;
4405 pipe_id = pipe->mode;
4407 buf_type = buffer->type;
4409 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4411 ddr_buffer.kernel_ptr = 0;
4413 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4415 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4416 return IA_CSS_ERR_INVALID_ARGUMENTS;
4419 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4421 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4422 return IA_CSS_ERR_INVALID_ARGUMENTS;
4425 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES)) {
4426 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4427 return IA_CSS_ERR_INVALID_ARGUMENTS;
4430 if (!sh_css_sp_is_running()) {
4431 IA_CSS_LOG("SP is not running!");
4432 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4433 /* SP is not running. The queues are not valid */
4434 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4437 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4438 (uint32_t *)&ddr_buffer_addr);
4440 if (return_err == IA_CSS_SUCCESS) {
4441 struct ia_css_frame *frame;
4442 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4444 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4446 /* Validate the ddr_buffer_addr and buf_type */
4447 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4448 ddr_buffer_addr, buf_type);
4449 if (hmm_buffer_record != NULL) {
4450 /* valid hmm_buffer_record found. Save the kernel_ptr
4451 * for validation after performing mmgr_load. The
4452 * vbuf handle and buffer_record can be released.
4454 kernel_ptr = hmm_buffer_record->kernel_ptr;
4455 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4456 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4458 IA_CSS_ERROR("hmm_buffer_record not found (0x%u) buf_type(%d)",
4459 ddr_buffer_addr, buf_type);
4460 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4461 return IA_CSS_ERR_INTERNAL_ERROR;
4464 mmgr_load(ddr_buffer_addr,
4466 sizeof(struct sh_css_hmm_buffer));
4468 /* if the kernel_ptr is 0 or an invalid, return an error.
4469 * do not access the buffer via the kernal_ptr.
4471 if ((ddr_buffer.kernel_ptr == 0) ||
4472 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4473 IA_CSS_ERROR("kernel_ptr invalid");
4474 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4475 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4476 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4477 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4478 return IA_CSS_ERR_INTERNAL_ERROR;
4481 if (ddr_buffer.kernel_ptr != 0) {
4482 /* buffer->exp_id : all instances to be removed later once the driver change
4483 * is completed. See patch #5758 for reference */
4485 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4486 buffer->timing_data = ddr_buffer.timing_data;
4488 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4489 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4490 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4494 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4495 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4496 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4497 if ((pipe) && (pipe->stop_requested == true))
4500 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4501 /* free mipi frames only for old input system
4502 * for 2401 it is done in ia_css_stream_destroy call
4504 return_err = free_mipi_frames(pipe);
4505 if (return_err != IA_CSS_SUCCESS) {
4506 IA_CSS_LOG("free_mipi_frames() failed");
4507 IA_CSS_LEAVE_ERR(return_err);
4511 pipe->stop_requested = false;
4513 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4514 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4515 frame = (struct ia_css_frame*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4516 buffer->data.frame = frame;
4517 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4518 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4519 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4520 if (ddr_buffer.payload.frame.flashed == 1)
4521 frame->flash_state =
4522 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4523 if (ddr_buffer.payload.frame.flashed == 2)
4524 frame->flash_state =
4525 IA_CSS_FRAME_FLASH_STATE_FULL;
4526 frame->valid = pipe->num_invalid_frames == 0;
4528 pipe->num_invalid_frames--;
4530 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4531 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4532 frame->planes.binary.size = frame->data_bytes;
4534 frame->planes.binary.size =
4535 sh_css_sp_get_binary_copy_size();
4538 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4539 if (IA_CSS_BUFFER_TYPE_OUTPUT_FRAME == buf_type) {
4540 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4541 frame->data, frame->isp_config_id, thread_id);
4545 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4546 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4547 buf_type, buffer->data.frame->data);
4550 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4551 buffer->data.stats_3a =
4552 (struct ia_css_isp_3a_statistics*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4553 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4554 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4555 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4557 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4558 buffer->data.stats_dvs =
4559 (struct ia_css_isp_dvs_statistics*)
4560 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4561 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4562 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4564 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4566 case IA_CSS_BUFFER_TYPE_METADATA:
4567 buffer->data.metadata =
4568 (struct ia_css_metadata*)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4569 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4570 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4573 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4580 * Tell the SP which queues are not full,
4581 * by sending the software event.
4583 if (return_err == IA_CSS_SUCCESS){
4584 if (!sh_css_sp_is_running()) {
4585 IA_CSS_LOG("SP is not running!");
4586 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4587 /* SP is not running. The queues are not valid */
4588 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4590 ia_css_bufq_enqueue_psys_event(
4591 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4596 IA_CSS_LEAVE("buffer=%p", buffer);
4602 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4603 * TODO: modify and move it if possible.
4605 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4606 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4607 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4608 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4609 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4611 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4612 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */
4613 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */
4614 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */
4615 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */
4616 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */
4617 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */
4618 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */
4619 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */
4620 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */
4621 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */
4622 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */
4623 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */
4624 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */
4625 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */
4626 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */
4627 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */
4628 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4632 ia_css_dequeue_event(struct ia_css_event *event)
4634 return ia_css_dequeue_psys_event(event);
4638 ia_css_dequeue_psys_event(struct ia_css_event *event)
4640 enum ia_css_pipe_id pipe_id = 0;
4641 uint8_t payload[4] = {0,0,0,0};
4642 enum ia_css_err ret_err;
4645 * a) use generic decoding function , same as the one used by sp.
4646 * b) group decode and dequeue into eventQueue module
4648 * We skip the IA_CSS_ENTER logging call
4649 * to avoid flooding the logs when the host application
4652 return IA_CSS_ERR_INVALID_ARGUMENTS;
4654 if (!sh_css_sp_is_running()) {
4655 /* SP is not running. The queues are not valid */
4656 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4659 /* dequeue the event (if any) from the psys event queue */
4660 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4661 if (ret_err != IA_CSS_SUCCESS)
4664 IA_CSS_LOG("event dequeued from psys event queue");
4666 /* Tell the SP that we dequeued an event from the event queue. */
4667 ia_css_bufq_enqueue_psys_event(
4668 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4670 /* Events are decoded into 4 bytes of payload, the first byte
4671 * contains the sp event type. This is converted to a host enum.
4672 * TODO: can this enum conversion be eliminated */
4673 event->type = convert_event_sp_to_host_domain[payload[0]];
4674 /* Some sane default values since not all events use all fields. */
4676 event->port = MIPI_PORT0_ID;
4678 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4679 event->fw_handle = 0;
4680 event->timer_data = 0;
4681 event->timer_code = 0;
4682 event->timer_subcode = 0;
4684 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4685 /* timer event ??? get the 2nd event and decode the data into the event struct */
4687 /* 1st event: LSB 16-bit timer data and code */
4688 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4689 event->timer_code = payload[2];
4690 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4691 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4692 if (ret_err != IA_CSS_SUCCESS) {
4693 /* no 2nd event ??? an error */
4694 /* Putting IA_CSS_ERROR is resulting in failures in
4695 * Merrifield smoke testing */
4696 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4699 ia_css_bufq_enqueue_psys_event(
4700 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4701 event->type = convert_event_sp_to_host_domain[payload[0]];
4703 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4704 /* 2nd event data: MSB 16-bit timer and subcode */
4705 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4706 event->timer_data |= (tmp_data << 16);
4707 event->timer_subcode = payload[2];
4709 /* It's a non timer event. So clear first half of the timer event data.
4710 * If the second part of the TIMER event is not received, we discard
4711 * the first half of the timer data and process the non timer event without
4712 * affecting the flow. So the non timer event falls through
4715 event->timer_data = 0;
4716 event->timer_code = 0;
4717 event->timer_subcode = 0;
4718 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4721 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF) {
4722 event->port = (enum mipi_port_id)payload[1];
4723 event->exp_id = payload[3];
4724 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4725 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4726 /* exp_id is only available in these warning types */
4727 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4728 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4729 event->exp_id = payload[3];
4730 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT) {
4731 event->fw_assert_module_id = payload[1]; /* module */
4732 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4733 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4734 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER) {
4735 /* pipe related events.
4736 * payload[1] contains the pipe_num,
4737 * payload[2] contains the pipe_id. These are different. */
4738 event->pipe = find_pipe_by_num(payload[1]);
4739 pipe_id = (enum ia_css_pipe_id)payload[2];
4740 /* Check to see if pipe still exists */
4742 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4744 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4745 /* find the capture pipe that goes with this */
4747 n = event->pipe->stream->num_pipes;
4748 for (i = 0; i < n; i++) {
4749 struct ia_css_pipe *p =
4750 event->pipe->stream->pipes[i];
4751 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4756 event->exp_id = payload[3];
4758 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4759 /* payload[3] contains the acc fw handle. */
4760 uint32_t stage_num = (uint32_t)payload[3];
4761 ret_err = ia_css_pipeline_get_fw_from_stage(
4762 &(event->pipe->pipeline),
4764 &(event->fw_handle));
4765 if (ret_err != IA_CSS_SUCCESS) {
4766 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4774 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4776 IA_CSS_LEAVE("event_id=%d", event->type);
4778 return IA_CSS_SUCCESS;
4782 ia_css_dequeue_isys_event(struct ia_css_event *event)
4784 uint8_t payload[4] = {0, 0, 0, 0};
4785 enum ia_css_err err = IA_CSS_SUCCESS;
4787 /* We skip the IA_CSS_ENTER logging call
4788 * to avoid flooding the logs when the host application
4791 return IA_CSS_ERR_INVALID_ARGUMENTS;
4793 if (!sh_css_sp_is_running()) {
4794 /* SP is not running. The queues are not valid */
4795 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4798 err = ia_css_bufq_dequeue_isys_event(payload);
4799 if (err != IA_CSS_SUCCESS)
4802 IA_CSS_LOG("event dequeued from isys event queue");
4804 /* Update SP state to indicate that element was dequeued. */
4805 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4807 /* Fill return struct with appropriate info */
4808 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4809 /* EOF events are associated with a CSI port, not with a pipe */
4811 event->port = payload[1];
4812 event->exp_id = payload[3];
4814 IA_CSS_LEAVE_ERR(err);
4819 acc_start(struct ia_css_pipe *pipe)
4821 assert(pipe != NULL);
4822 assert(pipe->stream != NULL);
4824 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4825 pipe->stream->config.mode);
4828 static enum ia_css_err
4829 sh_css_pipe_start(struct ia_css_stream *stream)
4831 enum ia_css_err err = IA_CSS_SUCCESS;
4833 struct ia_css_pipe *pipe;
4834 enum ia_css_pipe_id pipe_id;
4835 unsigned int thread_id;
4837 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4839 if (stream == NULL) {
4840 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4841 return IA_CSS_ERR_INVALID_ARGUMENTS;
4843 pipe = stream->last_pipe;
4845 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4846 return IA_CSS_ERR_INVALID_ARGUMENTS;
4849 pipe_id = pipe->mode;
4851 if(stream->started == true) {
4852 IA_CSS_WARNING("Cannot start stream that is already started");
4853 IA_CSS_LEAVE_ERR(err);
4857 pipe->stop_requested = false;
4860 case IA_CSS_PIPE_ID_PREVIEW:
4861 err = preview_start(pipe);
4863 case IA_CSS_PIPE_ID_VIDEO:
4864 err = video_start(pipe);
4866 case IA_CSS_PIPE_ID_CAPTURE:
4867 err = capture_start(pipe);
4869 case IA_CSS_PIPE_ID_YUVPP:
4870 err = yuvpp_start(pipe);
4872 case IA_CSS_PIPE_ID_ACC:
4876 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4878 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4879 if (!stream->config.continuous) {
4881 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) {
4882 switch (stream->pipes[i]->mode) {
4883 case IA_CSS_PIPE_ID_PREVIEW:
4884 stream->pipes[i]->stop_requested = false;
4885 err = preview_start(stream->pipes[i]);
4887 case IA_CSS_PIPE_ID_VIDEO:
4888 stream->pipes[i]->stop_requested = false;
4889 err = video_start(stream->pipes[i]);
4891 case IA_CSS_PIPE_ID_CAPTURE:
4892 stream->pipes[i]->stop_requested = false;
4893 err = capture_start(stream->pipes[i]);
4895 case IA_CSS_PIPE_ID_YUVPP:
4896 stream->pipes[i]->stop_requested = false;
4897 err = yuvpp_start(stream->pipes[i]);
4899 case IA_CSS_PIPE_ID_ACC:
4900 stream->pipes[i]->stop_requested = false;
4901 acc_start(stream->pipes[i]);
4904 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4908 if (err != IA_CSS_SUCCESS) {
4909 IA_CSS_LEAVE_ERR_PRIVATE(err);
4913 /* Force ISP parameter calculation after a mode change
4914 * Acceleration API examples pass NULL for stream but they
4915 * don't use ISP parameters anyway. So this should be okay.
4916 * The SP binary (jpeg) copy does not use any parameters.
4918 if (!copy_on_sp(pipe)) {
4919 sh_css_invalidate_params(stream);
4920 err = sh_css_param_update_isp_params(pipe,
4921 stream->isp_params_configs, true, NULL);
4922 if (err != IA_CSS_SUCCESS) {
4923 IA_CSS_LEAVE_ERR_PRIVATE(err);
4928 ia_css_debug_pipe_graph_dump_epilogue();
4930 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4932 if (!sh_css_sp_is_running()) {
4933 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4934 /* SP is not running. The queues are not valid */
4935 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4937 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4938 (uint8_t)thread_id, 0, 0);
4940 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4941 if (!stream->config.continuous) {
4943 for (i = 1; i < stream->num_pipes; i++) {
4944 ia_css_pipeline_get_sp_thread_id(
4945 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4947 ia_css_bufq_enqueue_psys_event(
4948 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4949 (uint8_t)thread_id, 0, 0);
4953 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4954 if (pipe->stream->config.continuous) {
4955 struct ia_css_pipe *copy_pipe = NULL;
4957 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4958 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4959 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4960 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4962 if (copy_pipe == NULL) {
4963 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4964 return IA_CSS_ERR_INTERNAL_ERROR;
4966 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe), &thread_id);
4967 /* by the time we reach here q is initialized and handle is available.*/
4968 ia_css_bufq_enqueue_psys_event(
4969 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4970 (uint8_t)thread_id, 0, 0);
4972 if (pipe->stream->cont_capt) {
4973 struct ia_css_pipe *capture_pipe = NULL;
4974 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4975 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4976 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4977 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4979 if (capture_pipe == NULL) {
4980 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4981 return IA_CSS_ERR_INTERNAL_ERROR;
4983 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
4984 /* by the time we reach here q is initialized and handle is available.*/
4985 ia_css_bufq_enqueue_psys_event(
4986 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4987 (uint8_t)thread_id, 0, 0);
4990 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
4991 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) {
4992 struct ia_css_pipe *acc_pipe = NULL;
4993 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4996 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe), &thread_id);
4997 /* by the time we reach here q is initialized and handle is available.*/
4998 ia_css_bufq_enqueue_psys_event(
4999 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5000 (uint8_t) thread_id, 0, 0);
5004 stream->started = true;
5006 IA_CSS_LEAVE_ERR_PRIVATE(err);
5012 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5014 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5015 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5016 //my_css.cont_capt = enable;
5017 my_css.stop_copy_preview = stop_copy_preview;
5021 sh_css_continuous_is_enabled(uint8_t pipe_num)
5024 * @brief Stop all "ia_css_pipe" instances in the target
5025 * "ia_css_stream" instance.
5027 * Refer to "Local prototypes" for more info.
5029 static enum ia_css_err
5030 sh_css_pipes_stop(struct ia_css_stream *stream)
5034 struct ia_css_pipe *pipe;
5037 enum ia_css_err err = IA_CSS_SUCCESS;
5038 struct ia_css_pipe *main_pipe;
5039 enum ia_css_pipe_id main_pipe_id;
5044 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5046 assert(stream != NULL);
5047 if (stream == NULL) {
5048 IA_CSS_LOG("stream does NOT exist!");
5049 err = IA_CSS_ERR_INTERNAL_ERROR;
5055 pipe = find_pipe_by_num(pipe_num);
5056 continuous = pipe && pipe->stream->config.continuous;
5057 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5058 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5063 main_pipe = stream->last_pipe;
5064 assert(main_pipe != NULL);
5065 if (main_pipe == NULL) {
5066 IA_CSS_LOG("main_pipe does NOT exist!");
5067 err = IA_CSS_ERR_INTERNAL_ERROR;
5074 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5076 if (buffer_depth == NULL)
5077 return IA_CSS_ERR_INVALID_ARGUMENTS;
5078 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5080 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5081 return IA_CSS_SUCCESS;
5084 main_pipe_id = main_pipe->mode;
5085 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5090 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5092 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5094 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5095 return IA_CSS_ERR_INVALID_ARGUMENTS;
5096 /* ok, value allowed */
5097 stream->config.target_num_cont_raw_buf = buffer_depth;
5098 /* TODO: check what to regarding initialization */
5099 return IA_CSS_SUCCESS;
5103 * Stop all "ia_css_pipe" instances in this target
5104 * "ia_css_stream" instance.
5106 for (i = 0; i < stream->num_pipes; i++) {
5107 /* send the "stop" request to the "ia_css_pipe" instance */
5108 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5109 stream->pipes[i]->pipeline.pipe_id);
5110 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5115 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5117 if (buffer_depth == NULL)
5118 return IA_CSS_ERR_INVALID_ARGUMENTS;
5119 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5122 * Exit this loop if "ia_css_pipeline_request_stop()"
5123 * returns the error code.
5125 * The error code would be generated in the following
5127 * (1) The Scalar Processor has already been stopped.
5128 * (2) The "Host->SP" event queue is full.
5130 * As the convention of using CSS API 2.0/2.1, such CSS
5131 * error code would be propogated from the CSS-internal
5132 * API returned value to the CSS API returned value. Then
5133 * the CSS driver should capture these error code and
5134 * handle it in the driver exception handling mechanism.
5136 if (err != IA_CSS_SUCCESS) {
5142 * In the CSS firmware use scenario "Continuous Preview"
5143 * as well as "Continuous Video", the "ia_css_pipe" instance
5144 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5145 * the CSS firmware so that it is not listed in the target
5146 * "ia_css_stream" instance.
5148 * We need to stop this "Copy Pipe", as well.
5150 if (main_pipe->stream->config.continuous) {
5151 struct ia_css_pipe *copy_pipe = NULL;
5153 /* get the reference to "Copy Pipe" */
5154 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5155 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5156 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5157 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5159 /* return the error code if "Copy Pipe" does NOT exist */
5160 assert(copy_pipe != NULL);
5161 if (copy_pipe == NULL) {
5162 IA_CSS_LOG("Copy Pipe does NOT exist!");
5163 err = IA_CSS_ERR_INTERNAL_ERROR;
5167 /* send the "stop" request to "Copy Pipe" */
5168 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5169 copy_pipe->pipeline.pipe_id);
5170 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
5174 IA_CSS_LEAVE_ERR_PRIVATE(err);
5179 * @brief Check if all "ia_css_pipe" instances in the target
5180 * "ia_css_stream" instance have stopped.
5182 * Refer to "Local prototypes" for more info.
5185 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5189 struct ia_css_pipe *main_pipe;
5190 enum ia_css_pipe_id main_pipe_id;
5194 assert(stream != NULL);
5195 if (stream == NULL) {
5196 IA_CSS_LOG("stream does NOT exist!");
5201 main_pipe = stream->last_pipe;
5202 assert(main_pipe != NULL);
5204 if (main_pipe == NULL) {
5205 IA_CSS_LOG("main_pipe does NOT exist!");
5210 main_pipe_id = main_pipe->mode;
5211 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5214 * Check if every "ia_css_pipe" instance in this target
5215 * "ia_css_stream" instance has stopped.
5217 for (i = 0; i < stream->num_pipes; i++) {
5218 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5219 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5220 stream->pipes[i]->pipeline.pipe_id,
5225 * In the CSS firmware use scenario "Continuous Preview"
5226 * as well as "Continuous Video", the "ia_css_pipe" instance
5227 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5228 * the CSS firmware so that it is not listed in the target
5229 * "ia_css_stream" instance.
5231 * We need to check if this "Copy Pipe" has stopped, as well.
5233 if (main_pipe->stream->config.continuous) {
5234 struct ia_css_pipe *copy_pipe = NULL;
5236 /* get the reference to "Copy Pipe" */
5237 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5238 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5239 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5240 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5242 /* return if "Copy Pipe" does NOT exist */
5243 assert(copy_pipe != NULL);
5244 if (copy_pipe == NULL) {
5245 IA_CSS_LOG("Copy Pipe does NOT exist!");
5251 /* check if "Copy Pipe" has stopped or not */
5252 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5253 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5254 copy_pipe->pipeline.pipe_id,
5259 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5264 sh_css_continuous_is_enabled(uint8_t pipe_num)
5266 struct ia_css_pipe *pipe;
5269 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5271 pipe = find_pipe_by_num(pipe_num);
5272 continuous = pipe && pipe->stream->config.continuous;
5273 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5274 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5280 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5282 if (buffer_depth == NULL)
5283 return IA_CSS_ERR_INVALID_ARGUMENTS;
5284 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5286 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5287 return IA_CSS_SUCCESS;
5291 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth)
5293 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n",buffer_depth);
5295 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5296 return IA_CSS_ERR_INVALID_ARGUMENTS;
5297 /* ok, value allowed */
5298 stream->config.target_num_cont_raw_buf = buffer_depth;
5299 /* TODO: check what to regarding initialization */
5300 return IA_CSS_SUCCESS;
5304 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream, int *buffer_depth)
5306 if (buffer_depth == NULL)
5307 return IA_CSS_ERR_INVALID_ARGUMENTS;
5308 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5311 *buffer_depth = stream->config.target_num_cont_raw_buf;
5312 return IA_CSS_SUCCESS;
5315 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5317 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5319 OP___assert(port < N_CSI_PORTS);
5320 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5321 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5322 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5323 return my_css.mipi_sizes_for_check[port][idx];
5327 static enum ia_css_err sh_css_pipe_configure_output(
5328 struct ia_css_pipe *pipe,
5330 unsigned int height,
5331 unsigned int padded_width,
5332 enum ia_css_frame_format format,
5335 enum ia_css_err err = IA_CSS_SUCCESS;
5337 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, paddaed width = %d, format = %d, idx = %d",
5338 pipe, width, height, padded_width, format, idx);
5340 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5341 return IA_CSS_ERR_INVALID_ARGUMENTS;
5344 err = ia_css_util_check_res(width, height);
5345 if (err != IA_CSS_SUCCESS) {
5346 IA_CSS_LEAVE_ERR_PRIVATE(err);
5349 if (pipe->output_info[idx].res.width != width ||
5350 pipe->output_info[idx].res.height != height ||
5351 pipe->output_info[idx].format != format)
5353 ia_css_frame_info_init(
5354 &pipe->output_info[idx],
5360 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5361 return IA_CSS_SUCCESS;
5364 static enum ia_css_err
5365 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5367 struct ia_css_shading_info *info)
5369 struct ia_css_shading_info *shading_info,
5370 struct ia_css_pipe_config *pipe_config)
5373 enum ia_css_err err = IA_CSS_SUCCESS;
5374 struct ia_css_binary *binary = NULL;
5376 assert(pipe != NULL);
5378 assert(info != NULL);
5380 assert(shading_info != NULL);
5381 assert(pipe_config != NULL);
5383 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5384 "sh_css_pipe_get_shading_info() enter:\n");
5386 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5389 err = ia_css_binary_get_shading_info(binary,
5390 IA_CSS_SHADING_CORRECTION_TYPE_1,
5391 pipe->required_bds_factor,
5392 (const struct ia_css_stream_config *)&pipe->stream->config,
5396 shading_info, pipe_config);
5398 /* Other function calls can be added here when other shading correction types will be added
5402 /* When the pipe does not have a binary which has the shading
5403 * correction, this function does not need to fill the shading
5404 * information. It is not a error case, and then
5405 * this function should return IA_CSS_SUCCESS.
5408 memset(info, 0, sizeof(*info));
5410 memset(shading_info, 0, sizeof(*shading_info));
5416 static enum ia_css_err
5417 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5418 struct ia_css_grid_info *info)
5420 enum ia_css_err err = IA_CSS_SUCCESS;
5421 struct ia_css_binary *binary = NULL;
5423 assert(pipe != NULL);
5424 assert(info != NULL);
5426 IA_CSS_ENTER_PRIVATE("");
5428 binary = ia_css_pipe_get_s3a_binary(pipe);
5431 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5432 if (err != IA_CSS_SUCCESS)
5435 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5437 binary = ia_css_pipe_get_sdis_binary(pipe);
5440 ia_css_binary_dvs_grid_info(binary, info, pipe);
5441 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5443 memset(&info->dvs_grid.dvs_grid_info, 0,
5444 sizeof(info->dvs_grid.dvs_grid_info));
5445 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5446 sizeof(info->dvs_grid.dvs_stat_grid_info));
5449 if (binary != NULL) {
5450 /* copy pipe does not have ISP binary*/
5451 info->isp_in_width = binary->internal_frame_info.res.width;
5452 info->isp_in_height = binary->internal_frame_info.res.height;
5455 #if defined(HAS_VAMEM_VERSION_2)
5456 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5457 #elif defined(HAS_VAMEM_VERSION_1)
5458 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5460 #error "Unknown VAMEM version"
5464 IA_CSS_LEAVE_ERR_PRIVATE(err);
5470 * @brief Check if a format is supported by the pipe.
5473 static enum ia_css_err
5474 ia_css_pipe_check_format(struct ia_css_pipe *pipe, enum ia_css_frame_format format)
5476 const enum ia_css_frame_format *supported_formats;
5477 int number_of_formats;
5481 IA_CSS_ENTER_PRIVATE("");
5483 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info) {
5484 IA_CSS_ERROR("Pipe or binary info is not set");
5485 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5486 return IA_CSS_ERR_INVALID_ARGUMENTS;
5489 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5490 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats)/sizeof(enum ia_css_frame_format);
5492 for (i = 0; i < number_of_formats && !found; i++) {
5493 if (supported_formats[i] == format) {
5499 IA_CSS_ERROR("Requested format is not supported by binary");
5500 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5501 return IA_CSS_ERR_INVALID_ARGUMENTS;
5503 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5504 return IA_CSS_SUCCESS;
5509 static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe)
5511 struct ia_css_frame_info video_in_info, tnr_info,
5512 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5514 enum ia_css_err err = IA_CSS_SUCCESS;
5515 bool continuous = pipe->stream->config.continuous;
5517 unsigned num_output_pins;
5518 struct ia_css_frame_info video_bin_out_info;
5519 bool need_scaler = false;
5520 bool vf_res_different_than_output = false;
5521 bool need_vf_pp = false;
5523 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5525 IA_CSS_ENTER_PRIVATE("");
5526 assert(pipe != NULL);
5527 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5528 /* we only test the video_binary because offline video doesn't need a
5529 * vf_pp binary and online does not (always use) the copy_binary.
5530 * All are always reset at the same time anyway.
5532 if (mycs->video_binary.info)
5533 return IA_CSS_SUCCESS;
5535 online = pipe->stream->config.online;
5536 pipe_out_info = &pipe->output_info[0];
5537 pipe_vf_out_info = &pipe->vf_output_info[0];
5539 assert(pipe_out_info != NULL);
5542 * There is no explicit input format requirement for raw or yuv
5543 * What matters is that there is a binary that supports the stream format.
5544 * This is checked in the binary_find(), so no need to check it here
5546 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5547 if (err != IA_CSS_SUCCESS)
5549 /* cannot have online video and input_mode memory */
5550 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5551 return IA_CSS_ERR_INVALID_ARGUMENTS;
5552 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5553 err = ia_css_util_check_vf_out_info(pipe_out_info,
5555 if (err != IA_CSS_SUCCESS)
5558 err = ia_css_frame_check_info(pipe_out_info);
5559 if (err != IA_CSS_SUCCESS)
5563 if (pipe->out_yuv_ds_input_info.res.width)
5564 video_bin_out_info = pipe->out_yuv_ds_input_info;
5566 video_bin_out_info = *pipe_out_info;
5569 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]){
5570 video_vf_info = pipe_vf_out_info;
5571 vf_res_different_than_output = (video_vf_info->res.width != video_bin_out_info.res.width) ||
5572 (video_vf_info->res.height != video_bin_out_info.res.height);
5575 video_vf_info = NULL;
5578 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5580 /* we build up the pipeline starting at the end */
5581 /* YUV post-processing if needed */
5583 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5585 /* NV12 is the common format that is supported by both */
5586 /* yuv_scaler and the video_xx_isp2_min binaries. */
5587 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5589 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5590 &video_bin_out_info,
5594 if (err != IA_CSS_SUCCESS)
5596 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5597 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5598 sizeof(struct ia_css_binary), GFP_KERNEL);
5599 if (!mycs->yuv_scaler_binary) {
5600 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5603 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5604 * sizeof(bool), GFP_KERNEL);
5605 if (!mycs->is_output_stage) {
5606 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5609 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5610 struct ia_css_binary_descr yuv_scaler_descr;
5611 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5612 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5613 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5614 &cas_scaler_descr.out_info[i],
5615 &cas_scaler_descr.internal_out_info[i],
5616 &cas_scaler_descr.vf_info[i]);
5617 err = ia_css_binary_find(&yuv_scaler_descr,
5618 &mycs->yuv_scaler_binary[i]);
5619 if (err != IA_CSS_SUCCESS) {
5620 kfree(mycs->is_output_stage);
5621 mycs->is_output_stage = NULL;
5625 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5630 struct ia_css_binary_descr video_descr;
5631 enum ia_css_frame_format vf_info_format;
5633 err = ia_css_pipe_get_video_binarydesc(pipe,
5634 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info, video_vf_info,
5635 pipe->stream->config.left_padding);
5636 if (err != IA_CSS_SUCCESS)
5639 /* In the case where video_vf_info is not NULL, this allows
5640 * us to find a potential video library with desired vf format.
5641 * If success, no vf_pp binary is needed.
5642 * If failed, we will look up video binary with YUV_LINE vf format
5644 err = ia_css_binary_find(&video_descr,
5645 &mycs->video_binary);
5647 if (err != IA_CSS_SUCCESS) {
5648 if (video_vf_info) {
5649 /* This will do another video binary lookup later for YUV_LINE format*/
5653 } else if (video_vf_info) {
5654 /* The first video binary lookup is successful, but we may
5655 * still need vf_pp binary based on additiona check */
5656 num_output_pins = mycs->video_binary.info->num_output_pins;
5657 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5659 /* If the binary has dual output pins, we need vf_pp if the resolution
5661 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5663 /* If the binary has single output pin, we need vf_pp if additional
5664 * scaling is needed for vf */
5665 need_vf_pp |= ((num_output_pins == 1) &&
5666 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5667 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5671 /* save the current vf_info format for restoration later */
5672 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5673 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5675 vf_info_format = video_vf_info->format;
5677 if (!pipe->config.enable_vfpp_bci)
5678 ia_css_frame_info_set_format(video_vf_info,
5679 IA_CSS_FRAME_FORMAT_YUV_LINE);
5681 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5683 err = ia_css_binary_find(&video_descr,
5684 &mycs->video_binary);
5686 /* restore original vf_info format */
5687 ia_css_frame_info_set_format(video_vf_info,
5689 if (err != IA_CSS_SUCCESS)
5694 /* If a video binary does not use a ref_frame, we set the frame delay
5695 * to 0. This is the case for the 1-stage low-power video binary. */
5696 if (!mycs->video_binary.info->sp.enable.ref_frame)
5697 pipe->dvs_frame_delay = 0;
5699 /* The delay latency determines the number of invalid frames after
5700 * a stream is started. */
5701 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5702 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5704 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5705 * outputs a viewfinder output, then we need double the number of
5708 pipe->num_invalid_frames *= 2;
5710 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5711 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5712 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5714 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5715 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5717 if (!online && !continuous) {
5718 /* TODO: what exactly needs doing, prepend the copy binary to
5719 * video base this only on !online?
5721 err = load_copy_binary(pipe,
5723 &mycs->video_binary);
5724 if (err != IA_CSS_SUCCESS)
5731 #if !defined(HAS_OUTPUT_SYSTEM)
5732 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5733 struct ia_css_binary_descr vf_pp_descr;
5735 if (mycs->video_binary.vf_frame_info.format
5736 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5737 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5738 &mycs->video_binary.vf_frame_info,
5741 /* output from main binary is not yuv line. currently this is
5742 * possible only when bci is enabled on vfpp output */
5743 assert(pipe->config.enable_vfpp_bci == true);
5744 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5745 &mycs->video_binary.vf_frame_info,
5746 pipe_vf_out_info, NULL, NULL);
5749 err = ia_css_binary_find(&vf_pp_descr,
5750 &mycs->vf_pp_binary);
5751 if (err != IA_CSS_SUCCESS)
5756 err = allocate_delay_frames(pipe);
5758 if (err != IA_CSS_SUCCESS)
5761 if (mycs->video_binary.info->sp.enable.block_output) {
5763 unsigned int tnr_width;
5764 unsigned int tnr_height;
5766 tnr_info = mycs->video_binary.out_frame_info[0];
5769 /* Select resolution for TNR. If
5770 * output_system_in_resolution(GDC_out_resolution) is
5771 * being used, then select that as it will also be in resolution for
5772 * TNR. At present, it only make sense for Skycam */
5773 if (pipe->config.output_system_in_res.width && pipe->config.output_system_in_res.height) {
5774 tnr_width = pipe->config.output_system_in_res.width;
5775 tnr_height = pipe->config.output_system_in_res.height;
5777 tnr_width = tnr_info.res.width;
5778 tnr_height = tnr_info.res.height;
5781 /* Make tnr reference buffers output block width(in pix) align */
5782 tnr_info.res.width =
5784 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5785 tnr_info.padded_width = tnr_info.res.width;
5788 /* Make tnr reference buffers output block height align */
5790 tnr_info.res.height =
5791 CEIL_MUL(tnr_info.res.height,
5792 mycs->video_binary.info->sp.block.output_block_height);
5794 tnr_info.res.height =
5795 CEIL_MUL(tnr_height,
5796 mycs->video_binary.info->sp.block.output_block_height);
5799 tnr_info = mycs->video_binary.internal_frame_info;
5801 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5802 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5805 for (i = 0; i < NUM_VIDEO_TNR_FRAMES; i++) {
5807 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5809 if (mycs->tnr_frames[i]) {
5810 ia_css_frame_free(mycs->tnr_frames[i]);
5811 mycs->tnr_frames[i] = NULL;
5813 err = ia_css_frame_allocate_from_info(
5814 &mycs->tnr_frames[i],
5816 if (err != IA_CSS_SUCCESS)
5819 IA_CSS_LEAVE_PRIVATE("");
5820 return IA_CSS_SUCCESS;
5823 static enum ia_css_err
5824 unload_video_binaries(struct ia_css_pipe *pipe)
5827 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5829 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5830 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5831 return IA_CSS_ERR_INVALID_ARGUMENTS;
5833 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5834 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5835 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5837 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5840 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5841 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5843 kfree(pipe->pipe_settings.video.is_output_stage);
5844 pipe->pipe_settings.video.is_output_stage = NULL;
5845 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5846 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5848 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5849 return IA_CSS_SUCCESS;
5852 static enum ia_css_err video_start(struct ia_css_pipe *pipe)
5854 struct ia_css_binary *copy_binary;
5855 enum ia_css_err err = IA_CSS_SUCCESS;
5856 struct ia_css_pipe *copy_pipe, *capture_pipe;
5857 enum sh_css_pipe_config_override copy_ovrd;
5858 enum ia_css_input_mode video_pipe_input_mode;
5861 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5862 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5863 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5864 return IA_CSS_ERR_INVALID_ARGUMENTS;
5867 video_pipe_input_mode = pipe->stream->config.mode;
5869 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5870 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5872 copy_binary = &pipe->pipe_settings.video.copy_binary;
5874 sh_css_metrics_start_frame();
5876 /* multi stream video needs mipi buffers */
5878 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5879 err = send_mipi_frames(pipe);
5880 if (err != IA_CSS_SUCCESS)
5884 send_raw_frames(pipe);
5886 unsigned int thread_id;
5888 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5889 copy_ovrd = 1 << thread_id;
5891 if (pipe->stream->cont_capt) {
5892 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe), &thread_id);
5893 copy_ovrd |= 1 << thread_id;
5897 /* Construct and load the copy pipe */
5898 if (pipe->stream->config.continuous) {
5899 sh_css_sp_init_pipeline(©_pipe->pipeline,
5900 IA_CSS_PIPE_ID_COPY,
5901 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5903 pipe->stream->config.pixels_per_clock == 2, false,
5904 false, pipe->required_bds_factor,
5906 pipe->stream->config.mode,
5907 &pipe->stream->config.metadata_config,
5909 &pipe->stream->info.metadata_info
5911 &pipe->stream->info.metadata_info,
5913 #if !defined(HAS_NO_INPUT_SYSTEM)
5915 , pipe->stream->config.source.port.port
5917 pipe->stream->config.source.port.port,
5923 ©_pipe->config.internal_frame_origin_bqs_on_sctbl,
5924 copy_pipe->stream->isp_params_configs);
5927 /* make the video pipe start with mem mode input, copy handles
5929 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5932 /* Construct and load the capture pipe */
5933 if (pipe->stream->cont_capt) {
5934 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5935 IA_CSS_PIPE_ID_CAPTURE,
5936 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5937 capture_pipe->config.default_capture_config.enable_xnr != 0,
5938 capture_pipe->stream->config.pixels_per_clock == 2,
5939 true, /* continuous */
5940 false, /* offline */
5941 capture_pipe->required_bds_factor,
5943 IA_CSS_INPUT_MODE_MEMORY,
5944 &pipe->stream->config.metadata_config,
5946 &pipe->stream->info.metadata_info
5948 &pipe->stream->info.metadata_info,
5950 #if !defined(HAS_NO_INPUT_SYSTEM)
5952 , (enum mipi_port_id)0
5954 (enum mipi_port_id)0,
5960 &capture_pipe->config.internal_frame_origin_bqs_on_sctbl,
5961 capture_pipe->stream->isp_params_configs);
5965 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5967 IA_CSS_LEAVE_ERR_PRIVATE(err);
5972 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
5973 struct ia_css_pipe *pipe,
5974 struct ia_css_frame_info *info,
5977 assert(pipe != NULL);
5978 assert(info != NULL);
5980 /* We could print the pointer as input arg, and the values as output */
5981 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5983 if ( pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5984 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5985 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5986 return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER;
5987 /* offline video does not generate viewfinder output */
5988 *info = pipe->vf_output_info[idx];
5990 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5991 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5992 info.res.width=%d, info.res.height=%d, \
5993 info.padded_width=%d, info.format=%d, \
5994 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5995 info->res.width,info->res.height,
5996 info->padded_width,info->format,
5997 info->raw_bit_depth,info->raw_bayer_order);
5999 return IA_CSS_SUCCESS;
6002 static enum ia_css_err
6003 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
6004 unsigned int height, unsigned int min_width,
6005 enum ia_css_frame_format format,
6008 enum ia_css_err err = IA_CSS_SUCCESS;
6010 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
6011 pipe, width, height, min_width, format, idx);
6014 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6015 return IA_CSS_ERR_INVALID_ARGUMENTS;
6019 err = ia_css_util_check_res(width, height);
6020 if (err != IA_CSS_SUCCESS) {
6021 IA_CSS_LEAVE_ERR_PRIVATE(err);
6024 if (pipe->vf_output_info[idx].res.width != width ||
6025 pipe->vf_output_info[idx].res.height != height ||
6026 pipe->vf_output_info[idx].format != format) {
6027 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
6030 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6031 return IA_CSS_SUCCESS;
6034 static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe)
6036 enum ia_css_err err = IA_CSS_SUCCESS;
6038 assert(pipe != NULL);
6039 IA_CSS_ENTER_PRIVATE("");
6041 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6042 if (pipe->pipe_settings.capture.copy_binary.info)
6043 return IA_CSS_SUCCESS;
6045 err = ia_css_frame_check_info(&pipe->output_info[0]);
6046 if (err != IA_CSS_SUCCESS)
6049 err = verify_copy_out_frame_format(pipe);
6050 if (err != IA_CSS_SUCCESS)
6053 err = load_copy_binary(pipe,
6054 &pipe->pipe_settings.capture.copy_binary,
6058 IA_CSS_LEAVE_ERR_PRIVATE(err);
6062 static bool need_capture_pp(
6063 const struct ia_css_pipe *pipe)
6065 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6066 IA_CSS_ENTER_LEAVE_PRIVATE("");
6067 assert(pipe != NULL);
6068 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6071 /* ldc and capture_pp are not supported in the same pipeline */
6072 if (need_capt_ldc(pipe) == true)
6075 /* determine whether we need to use the capture_pp binary.
6076 * This is needed for:
6078 * 2. Digital Zoom or
6079 * 3. YUV downscaling
6081 if (pipe->out_yuv_ds_input_info.res.width &&
6082 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6083 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6086 if (pipe->config.default_capture_config.enable_xnr != 0)
6089 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6090 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6091 pipe->config.enable_dz)
6097 static bool need_capt_ldc(
6098 const struct ia_css_pipe *pipe)
6100 IA_CSS_ENTER_LEAVE_PRIVATE("");
6101 assert(pipe != NULL);
6102 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6103 return (pipe->extra_config.enable_dvs_6axis) ? true:false;
6106 static enum ia_css_err set_num_primary_stages(unsigned int *num, enum ia_css_pipe_version version)
6108 enum ia_css_err err = IA_CSS_SUCCESS;
6111 return IA_CSS_ERR_INVALID_ARGUMENTS;
6114 case IA_CSS_PIPE_VERSION_2_6_1:
6115 *num = NUM_PRIMARY_HQ_STAGES;
6117 case IA_CSS_PIPE_VERSION_2_2:
6118 case IA_CSS_PIPE_VERSION_1:
6119 *num = NUM_PRIMARY_STAGES;
6122 err = IA_CSS_ERR_INVALID_ARGUMENTS;
6129 static enum ia_css_err load_primary_binaries(
6130 struct ia_css_pipe *pipe)
6132 bool online = false;
6133 bool memory = false;
6134 bool continuous = false;
6135 bool need_pp = false;
6136 bool need_isp_copy_binary = false;
6137 bool need_ldc = false;
6138 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6139 bool sensor = false;
6141 struct ia_css_frame_info prim_in_info,
6143 capt_pp_out_info, vf_info,
6144 *vf_pp_in_info, *pipe_out_info,
6146 *pipe_vf_out_info, *capt_pp_in_info,
6151 enum ia_css_err err = IA_CSS_SUCCESS;
6152 struct ia_css_capture_settings *mycs;
6154 bool need_extra_yuv_scaler = false;
6156 IA_CSS_ENTER_PRIVATE("");
6157 assert(pipe != NULL);
6158 assert(pipe->stream != NULL);
6159 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6161 online = pipe->stream->config.online;
6162 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6163 continuous = pipe->stream->config.continuous;
6164 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6165 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6168 mycs = &pipe->pipe_settings.capture;
6169 pipe_out_info = &pipe->output_info[0];
6170 pipe_vf_out_info = &pipe->vf_output_info[0];
6172 if (mycs->primary_binary[0].info)
6173 return IA_CSS_SUCCESS;
6175 err = set_num_primary_stages(&mycs->num_primary_stage, pipe->config.isp_pipe_version);
6176 if (err != IA_CSS_SUCCESS) {
6177 IA_CSS_LEAVE_ERR_PRIVATE(err);
6181 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6182 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6183 if (err != IA_CSS_SUCCESS) {
6184 IA_CSS_LEAVE_ERR_PRIVATE(err);
6189 err = ia_css_frame_check_info(pipe_out_info);
6190 if (err != IA_CSS_SUCCESS) {
6191 IA_CSS_LEAVE_ERR_PRIVATE(err);
6195 need_pp = need_capture_pp(pipe);
6197 /* we use the vf output info to get the primary/capture_pp binary
6198 configured for vf_veceven. It will select the closest downscaling
6200 vf_info = *pipe_vf_out_info;
6203 * WARNING: The #if def flag has been added below as a
6204 * temporary solution to solve the problem of enabling the
6205 * view finder in a single binary in a capture flow. The
6206 * vf-pp stage has been removed for Skycam in the solution
6207 * provided. The vf-pp stage should be re-introduced when
6208 * required. This should not be considered as a clean solution.
6209 * Proper investigation should be done to come up with the clean
6212 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6214 /* TODO: All this yuv_scaler and capturepp calculation logic
6215 * can be shared later. Capture_pp is also a yuv_scale binary
6216 * with extra XNR funcionality. Therefore, it can be made as the
6217 * first step of the cascade. */
6218 capt_pp_out_info = pipe->out_yuv_ds_input_info;
6219 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6220 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
6221 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6222 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6225 * WARNING: The #if def flag has been added below as a
6226 * temporary solution to solve the problem of enabling the
6227 * view finder in a single binary in a capture flow. The
6228 * vf-pp stage has been removed for Skycam in the solution
6229 * provided. The vf-pp stage should be re-introduced when
6230 * required. This should not be considered as a clean solution.
6231 * Proper investigation should be done to come up with the clean
6234 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6235 pipe_out_info->res);
6237 if (need_extra_yuv_scaler) {
6238 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6240 err = ia_css_pipe_create_cas_scaler_desc_single_output(
6245 if (err != IA_CSS_SUCCESS) {
6246 IA_CSS_LEAVE_ERR_PRIVATE(err);
6249 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6250 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6251 sizeof(struct ia_css_binary), GFP_KERNEL);
6252 if (!mycs->yuv_scaler_binary) {
6253 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6254 IA_CSS_LEAVE_ERR_PRIVATE(err);
6257 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6258 sizeof(bool), GFP_KERNEL);
6259 if (!mycs->is_output_stage) {
6260 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6261 IA_CSS_LEAVE_ERR_PRIVATE(err);
6264 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6265 struct ia_css_binary_descr yuv_scaler_descr;
6266 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6267 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6268 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6269 &cas_scaler_descr.out_info[i],
6270 &cas_scaler_descr.internal_out_info[i],
6271 &cas_scaler_descr.vf_info[i]);
6272 err = ia_css_binary_find(&yuv_scaler_descr,
6273 &mycs->yuv_scaler_binary[i]);
6274 if (err != IA_CSS_SUCCESS) {
6275 IA_CSS_LEAVE_ERR_PRIVATE(err);
6279 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6282 capt_pp_out_info = pipe->output_info[0];
6285 /* TODO Do we disable ldc for skycam */
6286 need_ldc = need_capt_ldc(pipe);
6288 /* ldc and capt_pp are not supported in the same pipeline */
6290 struct ia_css_binary_descr capt_ldc_descr;
6291 ia_css_pipe_get_ldc_binarydesc(pipe,
6292 &capt_ldc_descr, &prim_out_info,
6297 err = ia_css_binary_find(&capt_ldc_descr,
6298 &mycs->capture_ldc_binary);
6299 if (err != IA_CSS_SUCCESS) {
6300 IA_CSS_LEAVE_ERR_PRIVATE(err);
6303 } else if (need_pp) {
6305 /* we build up the pipeline starting at the end */
6306 /* Capture post-processing */
6310 struct ia_css_binary_descr capture_pp_descr;
6312 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6315 ia_css_pipe_get_capturepp_binarydesc(pipe,
6317 &capture_pp_descr, capt_pp_in_info,
6319 &capture_pp_descr, &prim_out_info,
6321 &capt_pp_out_info, &vf_info);
6322 err = ia_css_binary_find(&capture_pp_descr,
6323 &mycs->capture_pp_binary);
6324 if (err != IA_CSS_SUCCESS) {
6325 IA_CSS_LEAVE_ERR_PRIVATE(err);
6331 struct ia_css_binary_descr capt_ldc_descr;
6332 ia_css_pipe_get_ldc_binarydesc(pipe,
6333 &capt_ldc_descr, &prim_out_info,
6334 &capt_ldc_out_info);
6336 err = ia_css_binary_find(&capt_ldc_descr,
6337 &mycs->capture_ldc_binary);
6338 if (err != IA_CSS_SUCCESS) {
6339 IA_CSS_LEAVE_ERR_PRIVATE(err);
6345 prim_out_info = *pipe_out_info;
6350 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6352 for (i = 0; i < mycs->num_primary_stage; i++) {
6353 struct ia_css_frame_info *local_vf_info = NULL;
6354 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && (i == mycs->num_primary_stage - 1))
6355 local_vf_info = &vf_info;
6356 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info, &prim_out_info, local_vf_info, i);
6357 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6358 if (err != IA_CSS_SUCCESS) {
6359 IA_CSS_LEAVE_ERR_PRIVATE(err);
6365 /* Viewfinder post-processing */
6368 &mycs->capture_pp_binary.vf_frame_info;
6371 &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6375 * WARNING: The #if def flag has been added below as a
6376 * temporary solution to solve the problem of enabling the
6377 * view finder in a single binary in a capture flow. The
6378 * vf-pp stage has been removed for Skycam in the solution
6379 * provided. The vf-pp stage should be re-introduced when
6380 * required. Thisshould not be considered as a clean solution.
6381 * Proper * investigation should be done to come up with the clean
6384 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
6386 struct ia_css_binary_descr vf_pp_descr;
6388 ia_css_pipe_get_vfpp_binarydesc(pipe,
6389 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6390 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6391 if (err != IA_CSS_SUCCESS) {
6392 IA_CSS_LEAVE_ERR_PRIVATE(err);
6396 err = allocate_delay_frames(pipe);
6398 if (err != IA_CSS_SUCCESS)
6401 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6402 /* When the input system is 2401, only the Direct Sensor Mode
6403 * Offline Capture uses the ISP copy binary.
6405 need_isp_copy_binary = !online && sensor;
6407 need_isp_copy_binary = !online && !continuous && !memory;
6411 if (need_isp_copy_binary) {
6412 err = load_copy_binary(pipe,
6414 &mycs->primary_binary[0]);
6415 if (err != IA_CSS_SUCCESS) {
6416 IA_CSS_LEAVE_ERR_PRIVATE(err);
6421 return IA_CSS_SUCCESS;
6424 static enum ia_css_err
6425 allocate_delay_frames(struct ia_css_pipe *pipe)
6427 unsigned int num_delay_frames = 0, i = 0;
6428 unsigned int dvs_frame_delay = 0;
6429 struct ia_css_frame_info ref_info;
6430 enum ia_css_err err = IA_CSS_SUCCESS;
6431 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6432 struct ia_css_frame **delay_frames = NULL;
6434 IA_CSS_ENTER_PRIVATE("");
6437 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6438 return IA_CSS_ERR_INVALID_ARGUMENTS;
6442 dvs_frame_delay = pipe->dvs_frame_delay;
6444 if (dvs_frame_delay > 0)
6445 num_delay_frames = dvs_frame_delay + 1;
6448 case IA_CSS_PIPE_ID_CAPTURE:
6450 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6455 case IA_CSS_PIPE_ID_VIDEO:
6457 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6458 ref_info = mycs_video->video_binary.internal_frame_info;
6459 /*The ref frame expects
6461 * 2. UV plane with line interleaving, like below
6462 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6464 * This format is not YUV420(which has Y, U and V planes).
6465 * Its closer to NV12, except that the UV plane has UV
6466 * interleaving, like UVUVUVUVUVUVUVUVU...
6468 * TODO: make this ref_frame format as a separate frame format
6470 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6471 delay_frames = mycs_video->delay_frames;
6474 case IA_CSS_PIPE_ID_PREVIEW:
6476 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6477 ref_info = mycs_preview->preview_binary.internal_frame_info;
6478 /*The ref frame expects
6480 * 2. UV plane with line interleaving, like below
6481 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6483 * This format is not YUV420(which has Y, U and V planes).
6484 * Its closer to NV12, except that the UV plane has UV
6485 * interleaving, like UVUVUVUVUVUVUVUVU...
6487 * TODO: make this ref_frame format as a separate frame format
6489 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6490 delay_frames = mycs_preview->delay_frames;
6494 return IA_CSS_ERR_INVALID_ARGUMENTS;
6498 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6500 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6501 for (i = 0; i < num_delay_frames; i++) {
6502 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6503 if (err != IA_CSS_SUCCESS)
6506 IA_CSS_LEAVE_PRIVATE("");
6507 return IA_CSS_SUCCESS;
6510 static enum ia_css_err load_advanced_binaries(
6511 struct ia_css_pipe *pipe)
6513 struct ia_css_frame_info pre_in_info, gdc_in_info,
6514 post_in_info, post_out_info,
6515 vf_info, *vf_pp_in_info, *pipe_out_info,
6518 bool need_isp_copy = true;
6519 enum ia_css_err err = IA_CSS_SUCCESS;
6521 IA_CSS_ENTER_PRIVATE("");
6523 assert(pipe != NULL);
6524 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6525 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6526 return IA_CSS_SUCCESS;
6527 pipe_out_info = &pipe->output_info[0];
6528 pipe_vf_out_info = &pipe->vf_output_info[0];
6530 vf_info = *pipe_vf_out_info;
6531 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6532 if (err != IA_CSS_SUCCESS)
6534 need_pp = need_capture_pp(pipe);
6536 ia_css_frame_info_set_format(&vf_info,
6537 IA_CSS_FRAME_FORMAT_YUV_LINE);
6539 /* we build up the pipeline starting at the end */
6540 /* Capture post-processing */
6542 struct ia_css_binary_descr capture_pp_descr;
6544 ia_css_pipe_get_capturepp_binarydesc(pipe,
6545 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6546 err = ia_css_binary_find(&capture_pp_descr,
6547 &pipe->pipe_settings.capture.capture_pp_binary);
6548 if (err != IA_CSS_SUCCESS)
6551 post_out_info = *pipe_out_info;
6556 struct ia_css_binary_descr post_gdc_descr;
6558 ia_css_pipe_get_post_gdc_binarydesc(pipe,
6559 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6560 err = ia_css_binary_find(&post_gdc_descr,
6561 &pipe->pipe_settings.capture.post_isp_binary);
6562 if (err != IA_CSS_SUCCESS)
6568 struct ia_css_binary_descr gdc_descr;
6570 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6571 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6572 err = ia_css_binary_find(&gdc_descr,
6573 &pipe->pipe_settings.capture.anr_gdc_binary);
6574 if (err != IA_CSS_SUCCESS)
6577 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6578 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6582 struct ia_css_binary_descr pre_gdc_descr;
6584 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6585 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6586 err = ia_css_binary_find(&pre_gdc_descr,
6587 &pipe->pipe_settings.capture.pre_isp_binary);
6588 if (err != IA_CSS_SUCCESS)
6591 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6592 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6594 /* Viewfinder post-processing */
6597 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6600 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6604 struct ia_css_binary_descr vf_pp_descr;
6606 ia_css_pipe_get_vfpp_binarydesc(pipe,
6607 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6608 err = ia_css_binary_find(&vf_pp_descr,
6609 &pipe->pipe_settings.capture.vf_pp_binary);
6610 if (err != IA_CSS_SUCCESS)
6615 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6616 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6617 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6620 load_copy_binary(pipe,
6621 &pipe->pipe_settings.capture.copy_binary,
6622 &pipe->pipe_settings.capture.pre_isp_binary);
6627 static enum ia_css_err load_bayer_isp_binaries(
6628 struct ia_css_pipe *pipe)
6630 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6631 enum ia_css_err err = IA_CSS_SUCCESS;
6632 struct ia_css_binary_descr pre_de_descr;
6634 IA_CSS_ENTER_PRIVATE("");
6635 assert(pipe != NULL);
6636 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6637 pipe_out_info = &pipe->output_info[0];
6639 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6640 return IA_CSS_SUCCESS;
6642 err = ia_css_frame_check_info(pipe_out_info);
6643 if (err != IA_CSS_SUCCESS)
6646 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6650 err = ia_css_binary_find(&pre_de_descr,
6651 &pipe->pipe_settings.capture.pre_isp_binary);
6656 static enum ia_css_err load_low_light_binaries(
6657 struct ia_css_pipe *pipe)
6659 struct ia_css_frame_info pre_in_info, anr_in_info,
6660 post_in_info, post_out_info,
6661 vf_info, *pipe_vf_out_info, *pipe_out_info,
6664 bool need_isp_copy = true;
6665 enum ia_css_err err = IA_CSS_SUCCESS;
6667 IA_CSS_ENTER_PRIVATE("");
6668 assert(pipe != NULL);
6669 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6671 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6672 return IA_CSS_SUCCESS;
6673 pipe_vf_out_info = &pipe->vf_output_info[0];
6674 pipe_out_info = &pipe->output_info[0];
6676 vf_info = *pipe_vf_out_info;
6677 err = ia_css_util_check_vf_out_info(pipe_out_info,
6679 if (err != IA_CSS_SUCCESS)
6681 need_pp = need_capture_pp(pipe);
6683 ia_css_frame_info_set_format(&vf_info,
6684 IA_CSS_FRAME_FORMAT_YUV_LINE);
6686 /* we build up the pipeline starting at the end */
6687 /* Capture post-processing */
6689 struct ia_css_binary_descr capture_pp_descr;
6691 ia_css_pipe_get_capturepp_binarydesc(pipe,
6692 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6693 err = ia_css_binary_find(&capture_pp_descr,
6694 &pipe->pipe_settings.capture.capture_pp_binary);
6695 if (err != IA_CSS_SUCCESS)
6698 post_out_info = *pipe_out_info;
6703 struct ia_css_binary_descr post_anr_descr;
6705 ia_css_pipe_get_post_anr_binarydesc(pipe,
6706 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6707 err = ia_css_binary_find(&post_anr_descr,
6708 &pipe->pipe_settings.capture.post_isp_binary);
6709 if (err != IA_CSS_SUCCESS)
6715 struct ia_css_binary_descr anr_descr;
6717 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6718 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6719 err = ia_css_binary_find(&anr_descr,
6720 &pipe->pipe_settings.capture.anr_gdc_binary);
6721 if (err != IA_CSS_SUCCESS)
6724 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6725 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6729 struct ia_css_binary_descr pre_anr_descr;
6731 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6732 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6733 err = ia_css_binary_find(&pre_anr_descr,
6734 &pipe->pipe_settings.capture.pre_isp_binary);
6735 if (err != IA_CSS_SUCCESS)
6738 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6739 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6741 /* Viewfinder post-processing */
6744 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6747 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6751 struct ia_css_binary_descr vf_pp_descr;
6753 ia_css_pipe_get_vfpp_binarydesc(pipe,
6754 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6755 err = ia_css_binary_find(&vf_pp_descr,
6756 &pipe->pipe_settings.capture.vf_pp_binary);
6757 if (err != IA_CSS_SUCCESS)
6762 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6763 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6764 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6767 err = load_copy_binary(pipe,
6768 &pipe->pipe_settings.capture.copy_binary,
6769 &pipe->pipe_settings.capture.pre_isp_binary);
6774 static bool copy_on_sp(struct ia_css_pipe *pipe)
6778 assert(pipe != NULL);
6779 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6783 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6785 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6787 rval &= ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) ||
6788 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6793 static enum ia_css_err load_capture_binaries(
6794 struct ia_css_pipe *pipe)
6796 enum ia_css_err err = IA_CSS_SUCCESS;
6799 IA_CSS_ENTER_PRIVATE("");
6800 assert(pipe != NULL);
6801 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
6803 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6804 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6805 return IA_CSS_SUCCESS;
6808 /* in primary, advanced,low light or bayer,
6809 the input format must be raw */
6811 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6812 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6813 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6814 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6815 if (err != IA_CSS_SUCCESS) {
6816 IA_CSS_LEAVE_ERR_PRIVATE(err);
6819 if (copy_on_sp(pipe) &&
6820 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6821 ia_css_frame_info_init(
6822 &pipe->output_info[0],
6825 IA_CSS_FRAME_FORMAT_BINARY_8,
6827 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6828 return IA_CSS_SUCCESS;
6831 switch (pipe->config.default_capture_config.mode) {
6832 case IA_CSS_CAPTURE_MODE_RAW:
6833 err = load_copy_binaries(pipe);
6834 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6835 if (err == IA_CSS_SUCCESS)
6836 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6839 case IA_CSS_CAPTURE_MODE_BAYER:
6840 err = load_bayer_isp_binaries(pipe);
6842 case IA_CSS_CAPTURE_MODE_PRIMARY:
6843 err = load_primary_binaries(pipe);
6845 case IA_CSS_CAPTURE_MODE_ADVANCED:
6846 err = load_advanced_binaries(pipe);
6848 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6849 err = load_low_light_binaries(pipe);
6852 if (err != IA_CSS_SUCCESS) {
6853 IA_CSS_LEAVE_ERR_PRIVATE(err);
6857 IA_CSS_LEAVE_ERR_PRIVATE(err);
6861 static enum ia_css_err
6862 unload_capture_binaries(struct ia_css_pipe *pipe)
6865 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6867 if ((pipe == NULL) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY))) {
6868 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6869 return IA_CSS_ERR_INVALID_ARGUMENTS;
6871 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6872 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6873 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6874 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6875 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6876 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6877 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6878 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6879 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6881 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6882 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6884 kfree(pipe->pipe_settings.capture.is_output_stage);
6885 pipe->pipe_settings.capture.is_output_stage = NULL;
6886 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6887 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6889 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6890 return IA_CSS_SUCCESS;
6894 need_downscaling(const struct ia_css_resolution in_res,
6895 const struct ia_css_resolution out_res)
6898 if (in_res.width > out_res.width || in_res.height > out_res.height)
6905 need_yuv_scaler_stage(const struct ia_css_pipe *pipe)
6908 struct ia_css_resolution in_res, out_res;
6910 bool need_format_conversion = false;
6912 IA_CSS_ENTER_PRIVATE("");
6913 assert(pipe != NULL);
6914 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6916 /* TODO: make generic function */
6917 need_format_conversion =
6918 ((pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6919 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6921 in_res = pipe->config.input_effective_res;
6923 if (pipe->config.enable_dz)
6926 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6929 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6930 out_res = pipe->output_info[i].res;
6932 /* A non-zero width means it is a valid output port */
6933 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6940 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6941 /* which has some hard-coded knowledge which prevents reuse of the function. */
6942 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6943 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
6944 struct ia_css_frame_info *cas_scaler_in_info,
6945 struct ia_css_frame_info *cas_scaler_out_info,
6946 struct ia_css_frame_info *cas_scaler_vf_info,
6947 struct ia_css_cas_binary_descr *descr)
6950 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6951 enum ia_css_err err = IA_CSS_SUCCESS;
6952 struct ia_css_frame_info tmp_in_info;
6954 unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6956 assert(cas_scaler_in_info != NULL);
6957 assert(cas_scaler_out_info != NULL);
6959 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6961 /* We assume that this function is used only for single output port case. */
6962 descr->num_output_stage = 1;
6964 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width , cas_scaler_out_info->res.width);
6965 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height, cas_scaler_out_info->res.height);
6966 /* use the same horizontal and vertical downscaling factor for simplicity */
6967 assert(hor_ds_factor == ver_ds_factor);
6970 while (i < hor_ds_factor) {
6972 i *= max_scale_factor_per_stage;
6975 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
6976 if (!descr->in_info) {
6977 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6980 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
6981 if (!descr->internal_out_info) {
6982 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6985 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
6986 if (!descr->out_info) {
6987 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6990 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
6991 if (!descr->vf_info) {
6992 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6995 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
6996 if (!descr->is_output_stage) {
6997 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7001 tmp_in_info = *cas_scaler_in_info;
7002 for (i = 0; i < descr->num_stage; i++) {
7004 descr->in_info[i] = tmp_in_info;
7005 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= cas_scaler_out_info->res.width) {
7006 descr->is_output_stage[i] = true;
7007 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7008 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
7009 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
7010 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
7011 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7013 assert(i == (descr->num_stage - 1));
7014 descr->internal_out_info[i].res.width = 0;
7015 descr->internal_out_info[i].res.height = 0;
7017 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
7018 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
7019 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
7020 descr->out_info[i].format = cas_scaler_out_info->format;
7021 if (cas_scaler_vf_info != NULL) {
7022 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
7023 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
7024 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
7025 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7027 descr->vf_info[i].res.width = 0;
7028 descr->vf_info[i].res.height = 0;
7029 descr->vf_info[i].padded_width = 0;
7032 descr->is_output_stage[i] = false;
7033 descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage;
7034 descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage;
7035 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7036 ia_css_frame_info_init(&descr->internal_out_info[i],
7037 tmp_in_info.res.width / max_scale_factor_per_stage,
7038 tmp_in_info.res.height / max_scale_factor_per_stage,
7039 IA_CSS_FRAME_FORMAT_YUV420, 0);
7040 descr->out_info[i].res.width = 0;
7041 descr->out_info[i].res.height = 0;
7042 descr->vf_info[i].res.width = 0;
7043 descr->vf_info[i].res.height = 0;
7045 tmp_in_info = descr->internal_out_info[i];
7048 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7053 /* FIXME: merge most of this and single output version */
7054 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc(struct ia_css_pipe *pipe,
7055 struct ia_css_cas_binary_descr *descr)
7057 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7058 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7059 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7060 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
7062 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7063 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
7065 unsigned int num_stages = 0;
7066 enum ia_css_err err = IA_CSS_SUCCESS;
7068 unsigned max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
7070 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7072 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7074 vf_out_info[i] = NULL;
7075 hor_scale_factor[i] = 0;
7076 ver_scale_factor[i] = 0;
7079 in_info.res = pipe->config.input_effective_res;
7080 in_info.padded_width = in_info.res.width;
7081 descr->num_output_stage = 0;
7082 /* Find out how much scaling we need for each output */
7083 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7084 if (pipe->output_info[i].res.width != 0) {
7085 out_info[i] = &pipe->output_info[i];
7086 if (pipe->vf_output_info[i].res.width != 0)
7087 vf_out_info[i] = &pipe->vf_output_info[i];
7088 descr->num_output_stage += 1;
7091 if (out_info[i] != NULL) {
7092 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7093 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7094 /* use the same horizontal and vertical scaling factor for simplicity */
7095 assert(hor_scale_factor[i] == ver_scale_factor[i]);
7099 scale_factor *= max_scale_factor_per_stage;
7100 } while (scale_factor < hor_scale_factor[i]);
7102 in_info.res = out_info[i]->res;
7106 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7109 descr->num_stage = num_stages;
7111 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
7112 if (!descr->in_info) {
7113 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7116 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
7117 if (!descr->internal_out_info) {
7118 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7121 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
7122 if (!descr->out_info) {
7123 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7126 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info), GFP_KERNEL);
7127 if (!descr->vf_info) {
7128 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7131 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7132 if (descr->is_output_stage == NULL) {
7133 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7137 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7140 assert((out_info[i-1]->res.width >= out_info[i]->res.width) &&
7141 (out_info[i-1]->res.height >= out_info[i]->res.height));
7146 tmp_in_info.res = pipe->config.input_effective_res;
7147 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7148 for (i = 0, j = 0; i < descr->num_stage; i++) {
7150 assert(out_info[j] != NULL);
7152 descr->in_info[i] = tmp_in_info;
7153 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <= out_info[j]->res.width) {
7154 descr->is_output_stage[i] = true;
7155 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7156 descr->internal_out_info[i].res.width = out_info[j]->res.width;
7157 descr->internal_out_info[i].res.height = out_info[j]->res.height;
7158 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7159 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7161 assert(i == (descr->num_stage - 1));
7162 descr->internal_out_info[i].res.width = 0;
7163 descr->internal_out_info[i].res.height = 0;
7165 descr->out_info[i].res.width = out_info[j]->res.width;
7166 descr->out_info[i].res.height = out_info[j]->res.height;
7167 descr->out_info[i].padded_width = out_info[j]->padded_width;
7168 descr->out_info[i].format = out_info[j]->format;
7169 if (vf_out_info[j] != NULL) {
7170 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7171 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7172 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7173 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7175 descr->vf_info[i].res.width = 0;
7176 descr->vf_info[i].res.height = 0;
7177 descr->vf_info[i].padded_width = 0;
7181 descr->is_output_stage[i] = false;
7182 descr->internal_out_info[i].res.width = tmp_in_info.res.width / max_scale_factor_per_stage;
7183 descr->internal_out_info[i].res.height = tmp_in_info.res.height / max_scale_factor_per_stage;
7184 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7185 ia_css_frame_info_init(&descr->internal_out_info[i],
7186 tmp_in_info.res.width / max_scale_factor_per_stage,
7187 tmp_in_info.res.height / max_scale_factor_per_stage,
7188 IA_CSS_FRAME_FORMAT_YUV420, 0);
7189 descr->out_info[i].res.width = 0;
7190 descr->out_info[i].res.height = 0;
7191 descr->vf_info[i].res.width = 0;
7192 descr->vf_info[i].res.height = 0;
7194 tmp_in_info = descr->internal_out_info[i];
7197 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7202 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr *descr)
7204 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7205 kfree(descr->in_info);
7206 descr->in_info = NULL;
7207 kfree(descr->internal_out_info);
7208 descr->internal_out_info = NULL;
7209 kfree(descr->out_info);
7210 descr->out_info = NULL;
7211 kfree(descr->vf_info);
7212 descr->vf_info = NULL;
7213 kfree(descr->is_output_stage);
7214 descr->is_output_stage = NULL;
7215 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7218 static enum ia_css_err
7219 load_yuvpp_binaries(struct ia_css_pipe *pipe)
7221 enum ia_css_err err = IA_CSS_SUCCESS;
7222 bool need_scaler = false;
7223 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7224 struct ia_css_yuvpp_settings *mycs;
7225 struct ia_css_binary *next_binary;
7226 struct ia_css_cas_binary_descr cas_scaler_descr = { };
7228 bool need_isp_copy_binary = false;
7230 IA_CSS_ENTER_PRIVATE("");
7231 assert(pipe != NULL);
7232 assert(pipe->stream != NULL);
7233 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7235 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7238 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7239 err = ia_css_util_check_input(&pipe->stream->config, false, false);
7240 if (err != IA_CSS_SUCCESS)
7243 mycs = &pipe->pipe_settings.yuvpp;
7245 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7246 if (pipe->vf_output_info[i].res.width != 0) {
7247 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7248 &pipe->vf_output_info[i]);
7249 if (err != IA_CSS_SUCCESS)
7252 vf_pp_in_info[i] = NULL;
7255 need_scaler = need_yuv_scaler_stage(pipe);
7257 /* we build up the pipeline starting at the end */
7258 /* Capture post-processing */
7260 struct ia_css_binary_descr yuv_scaler_descr;
7262 err = ia_css_pipe_create_cas_scaler_desc(pipe,
7264 if (err != IA_CSS_SUCCESS)
7266 mycs->num_output = cas_scaler_descr.num_output_stage;
7267 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
7268 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7269 sizeof(struct ia_css_binary), GFP_KERNEL);
7270 if (!mycs->yuv_scaler_binary) {
7271 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7274 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7275 sizeof(bool), GFP_KERNEL);
7276 if (!mycs->is_output_stage) {
7277 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7280 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7281 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7282 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7283 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7284 &cas_scaler_descr.out_info[i],
7285 &cas_scaler_descr.internal_out_info[i],
7286 &cas_scaler_descr.vf_info[i]);
7287 err = ia_css_binary_find(&yuv_scaler_descr,
7288 &mycs->yuv_scaler_binary[i]);
7289 if (err != IA_CSS_SUCCESS)
7292 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7294 mycs->num_output = 1;
7298 next_binary = &mycs->yuv_scaler_binary[0];
7303 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7306 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7307 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
7309 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7310 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7311 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7313 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7314 * _scale_binary". It would translate the input-frame to the frame formats that
7315 * are supported by the "yuv_scale_binary".
7317 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7318 * pp_defs.h" for the list of input-frame formats that are supported by the
7319 * "yuv_scale_binary".
7321 need_isp_copy_binary =
7322 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7323 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7324 need_isp_copy_binary = true;
7325 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7327 if (need_isp_copy_binary) {
7328 err = load_copy_binary(pipe,
7332 if (err != IA_CSS_SUCCESS)
7337 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7339 * In some use cases, the first stage in the "yuvpp" pipe is the
7340 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7341 * the input from either the system DDR or from the IPU internal VMEM.
7342 * So it provides the flag "online" to specify where its input is from,
7345 * (1) "online <= true", the input is from the IPU internal VMEM.
7346 * (2) "online <= false", the input is from the system DDR.
7348 * In other use cases, the first stage in the "yuvpp" pipe is the
7349 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7350 * input ONLY from the system DDR. So it does not provide the flag "online"
7351 * to specify where its input is from.
7353 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7356 /* Viewfinder post-processing */
7358 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7359 if (mycs->is_output_stage[i]) {
7362 &mycs->yuv_scaler_binary[i].vf_frame_info;
7366 mycs->num_vf_pp = j;
7369 &mycs->copy_binary.vf_frame_info;
7370 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7371 vf_pp_in_info[i] = NULL;
7373 mycs->num_vf_pp = 1;
7375 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7377 if (!mycs->vf_pp_binary) {
7378 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7383 struct ia_css_binary_descr vf_pp_descr;
7385 for (i = 0; i < mycs->num_vf_pp; i++) {
7386 if (pipe->vf_output_info[i].res.width != 0) {
7387 ia_css_pipe_get_vfpp_binarydesc(pipe,
7388 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7389 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7390 if (err != IA_CSS_SUCCESS)
7396 if (err != IA_CSS_SUCCESS)
7401 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7403 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7408 static enum ia_css_err
7409 unload_yuvpp_binaries(struct ia_css_pipe *pipe)
7412 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7414 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7415 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7416 return IA_CSS_ERR_INVALID_ARGUMENTS;
7418 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7419 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++) {
7420 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7422 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++) {
7423 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7425 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7426 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7427 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7428 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7429 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7430 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7432 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7433 return IA_CSS_SUCCESS;
7436 static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe)
7438 struct ia_css_binary *copy_binary;
7439 enum ia_css_err err = IA_CSS_SUCCESS;
7440 enum sh_css_pipe_config_override copy_ovrd;
7441 enum ia_css_input_mode yuvpp_pipe_input_mode;
7443 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7444 if ((pipe == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7445 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7446 return IA_CSS_ERR_INVALID_ARGUMENTS;
7449 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7451 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7453 sh_css_metrics_start_frame();
7455 /* multi stream video needs mipi buffers */
7457 #if !defined(HAS_NO_INPUT_SYSTEM) && ( defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) )
7458 err = send_mipi_frames(pipe);
7459 if (err != IA_CSS_SUCCESS) {
7460 IA_CSS_LEAVE_ERR_PRIVATE(err);
7466 unsigned int thread_id;
7468 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7469 copy_ovrd = 1 << thread_id;
7472 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7474 IA_CSS_LEAVE_ERR_PRIVATE(err);
7478 static enum ia_css_err
7479 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe)
7481 enum ia_css_err err = IA_CSS_SUCCESS;
7482 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7485 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7486 return IA_CSS_ERR_INVALID_ARGUMENTS;
7488 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7489 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY) {
7490 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7491 return IA_CSS_SUCCESS;
7494 switch (pipe->mode) {
7495 case IA_CSS_PIPE_ID_PREVIEW:
7496 err = unload_preview_binaries(pipe);
7498 case IA_CSS_PIPE_ID_VIDEO:
7499 err = unload_video_binaries(pipe);
7501 case IA_CSS_PIPE_ID_CAPTURE:
7502 err = unload_capture_binaries(pipe);
7504 case IA_CSS_PIPE_ID_YUVPP:
7505 err = unload_yuvpp_binaries(pipe);
7510 IA_CSS_LEAVE_ERR_PRIVATE(err);
7514 static enum ia_css_err
7515 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe)
7517 enum ia_css_err err = IA_CSS_SUCCESS;
7519 assert(pipe != NULL);
7520 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7522 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7523 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7526 switch (pipe->mode) {
7527 case IA_CSS_PIPE_ID_PREVIEW:
7528 err = load_preview_binaries(pipe);
7530 case IA_CSS_PIPE_ID_VIDEO:
7531 err = load_video_binaries(pipe);
7533 case IA_CSS_PIPE_ID_CAPTURE:
7534 err = load_capture_binaries(pipe);
7536 case IA_CSS_PIPE_ID_YUVPP:
7537 err = load_yuvpp_binaries(pipe);
7539 case IA_CSS_PIPE_ID_ACC:
7542 err = IA_CSS_ERR_INTERNAL_ERROR;
7545 if (err != IA_CSS_SUCCESS) {
7546 if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) {
7547 /* currently css does not support multiple error returns in a single function,
7548 * using IA_CSS_ERR_INTERNAL_ERROR in this case */
7549 err = IA_CSS_ERR_INTERNAL_ERROR;
7555 static enum ia_css_err
7556 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe)
7558 struct ia_css_pipeline *me;
7559 enum ia_css_err err = IA_CSS_SUCCESS;
7560 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7562 *yuv_scaler_stage = NULL;
7563 struct ia_css_binary *copy_binary,
7566 bool need_scaler = false;
7567 unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7570 struct ia_css_frame *in_frame = NULL;
7571 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7572 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7573 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7574 struct ia_css_pipeline_stage_desc stage_desc;
7575 bool need_in_frameinfo_memory = false;
7576 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7577 bool sensor = false;
7578 bool buffered_sensor = false;
7579 bool online = false;
7580 bool continuous = false;
7583 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7584 if ((pipe == NULL) || (pipe->stream == NULL) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7585 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7586 return IA_CSS_ERR_INVALID_ARGUMENTS;
7588 me = &pipe->pipeline;
7589 ia_css_pipeline_clean(me);
7590 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7591 out_frame[i] = NULL;
7594 ia_css_pipe_util_create_output_frames(bin_out_frame);
7595 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7596 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp;
7597 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7599 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7600 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7601 * except for the following:
7602 * - Direct Sensor Mode Online Capture
7603 * - Direct Sensor Mode Continuous Capture
7604 * - Buffered Sensor Mode Continuous Capture
7606 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7607 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7608 online = pipe->stream->config.online;
7609 continuous = pipe->stream->config.continuous;
7610 need_in_frameinfo_memory =
7611 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7613 /* Construct in_frame info (only in case we have dynamic input */
7614 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7616 /* the input frame can come from:
7617 * a) memory: connect yuvscaler to me->in_frame
7618 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7619 if (need_in_frameinfo_memory) {
7620 /* TODO: improve for different input formats. */
7623 * "pipe->stream->config.input_config.format" represents the sensor output
7624 * frame format, e.g. YUV422 8-bit.
7626 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7629 int in_frame_format;
7630 if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7631 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7632 } else if (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8) {
7634 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
7635 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7638 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7639 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7641 * By now, the "isp_copy_var" binary does NOT provide a separated
7642 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7643 * the YUV422-8 pixels in the frame-line buffer which is designed to
7644 * store the Bayer-Quad RAW pixels.
7646 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7647 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7650 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7652 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7655 err = init_in_frameinfo_memory_defaults(pipe,
7659 if (err != IA_CSS_SUCCESS) {
7660 IA_CSS_LEAVE_ERR_PRIVATE(err);
7664 in_frame = &me->in_frame;
7669 for (i = 0; i < num_output_stage; i++) {
7670 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7671 if (pipe->output_info[i].res.width != 0) {
7672 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7673 if (err != IA_CSS_SUCCESS) {
7674 IA_CSS_LEAVE_ERR_PRIVATE(err);
7677 out_frame[i] = &me->out_frame[i];
7680 /* Construct vf_frame info (only in case we have VF) */
7681 if (pipe->vf_output_info[i].res.width != 0) {
7682 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7683 if (err != IA_CSS_SUCCESS) {
7684 IA_CSS_LEAVE_ERR_PRIVATE(err);
7687 vf_frame[i] = &me->vf_frame[i];
7691 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7692 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7693 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7694 need_scaler = need_yuv_scaler_stage(pipe);
7696 if (pipe->pipe_settings.yuvpp.copy_binary.info) {
7698 struct ia_css_frame *in_frame_local = NULL;
7700 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7701 /* After isp copy is enabled in_frame needs to be passed. */
7703 in_frame_local = in_frame;
7707 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7708 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7709 bin_out_frame, in_frame_local, NULL);
7711 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7712 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7713 bin_out_frame, in_frame_local, NULL);
7716 err = ia_css_pipeline_create_and_add_stage(me,
7720 if (err != IA_CSS_SUCCESS) {
7721 IA_CSS_LEAVE_ERR_PRIVATE(err);
7726 /* if we use yuv scaler binary, vf output should be from there */
7727 copy_stage->args.copy_vf = !need_scaler;
7728 /* for yuvpp pipe, it should always be enabled */
7729 copy_stage->args.copy_output = true;
7730 /* connect output of copy binary to input of yuv scaler */
7731 in_frame = copy_stage->args.out_frame[0];
7736 struct ia_css_frame *tmp_out_frame = NULL;
7737 struct ia_css_frame *tmp_vf_frame = NULL;
7738 struct ia_css_frame *tmp_in_frame = in_frame;
7740 for (i = 0, j = 0; i < num_stage; i++) {
7741 assert(j < num_output_stage);
7742 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7743 tmp_out_frame = out_frame[j];
7744 tmp_vf_frame = vf_frame[j];
7746 tmp_out_frame = NULL;
7747 tmp_vf_frame = NULL;
7750 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7752 &yuv_scaler_binary[i],
7755 if (err != IA_CSS_SUCCESS) {
7756 IA_CSS_LEAVE_ERR_PRIVATE(err);
7759 /* we use output port 1 as internal output port */
7760 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7761 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7762 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7763 in_frame = yuv_scaler_stage->args.out_vf_frame;
7764 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7767 if (err != IA_CSS_SUCCESS) {
7768 IA_CSS_LEAVE_ERR_PRIVATE(err);
7775 } else if (copy_stage != NULL) {
7776 if (vf_frame[0] != NULL && vf_frame[0]->info.res.width != 0) {
7777 in_frame = copy_stage->args.out_vf_frame;
7778 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7781 if (err != IA_CSS_SUCCESS) {
7782 IA_CSS_LEAVE_ERR_PRIVATE(err);
7787 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7789 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7791 return IA_CSS_SUCCESS;
7794 static enum ia_css_err
7795 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7796 unsigned max_input_width,
7797 struct ia_css_frame *out_frame)
7799 struct ia_css_pipeline *me;
7800 enum ia_css_err err = IA_CSS_SUCCESS;
7801 struct ia_css_pipeline_stage_desc stage_desc;
7803 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7804 "create_host_copy_pipeline() enter:\n");
7806 /* pipeline already created as part of create_host_pipeline_structure */
7807 me = &pipe->pipeline;
7808 ia_css_pipeline_clean(me);
7810 /* Construct out_frame info */
7811 out_frame->contiguous = false;
7812 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7814 if (copy_on_sp(pipe) &&
7815 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
7816 ia_css_frame_info_init(
7820 IA_CSS_FRAME_FORMAT_BINARY_8,
7822 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW) {
7823 out_frame->info.raw_bit_depth =
7824 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7828 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7829 pipe->mode = IA_CSS_PIPE_ID_COPY;
7831 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7832 IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7833 err = ia_css_pipeline_create_and_add_stage(me,
7837 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7839 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7840 "create_host_copy_pipeline() leave:\n");
7845 static enum ia_css_err
7846 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe)
7848 struct ia_css_pipeline *me = &pipe->pipeline;
7849 enum ia_css_err err = IA_CSS_SUCCESS;
7850 struct ia_css_pipeline_stage_desc stage_desc;
7851 struct ia_css_frame *out_frame = &me->out_frame[0];
7852 struct ia_css_pipeline_stage *out_stage = NULL;
7853 unsigned int thread_id;
7854 enum sh_css_queue_id queue_id;
7855 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7857 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7858 "create_host_isyscopy_capture_pipeline() enter:\n");
7859 ia_css_pipeline_clean(me);
7861 /* Construct out_frame info */
7862 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7863 if (err != IA_CSS_SUCCESS)
7865 out_frame->contiguous = false;
7866 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7867 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7868 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7869 out_frame->dynamic_queue_id = queue_id;
7870 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7873 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7874 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7875 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7876 IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7877 err = ia_css_pipeline_create_and_add_stage(me,
7878 &stage_desc, &out_stage);
7879 if(err != IA_CSS_SUCCESS)
7882 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7884 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7885 "create_host_isyscopy_capture_pipeline() leave:\n");
7890 static enum ia_css_err
7891 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe)
7893 struct ia_css_pipeline *me;
7894 enum ia_css_err err = IA_CSS_SUCCESS;
7895 enum ia_css_capture_mode mode;
7896 struct ia_css_pipeline_stage *current_stage = NULL;
7897 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7898 struct ia_css_binary *copy_binary,
7899 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7906 *capture_ldc_binary;
7907 bool need_pp = false;
7910 struct ia_css_frame *in_frame;
7911 struct ia_css_frame *out_frame;
7912 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7913 struct ia_css_frame *vf_frame;
7914 struct ia_css_pipeline_stage_desc stage_desc;
7915 bool need_in_frameinfo_memory = false;
7916 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7917 bool sensor = false;
7918 bool buffered_sensor = false;
7919 bool online = false;
7920 bool continuous = false;
7922 unsigned int i, num_yuv_scaler, num_primary_stage;
7923 bool need_yuv_pp = false;
7924 bool *is_output_stage = NULL;
7925 bool need_ldc = false;
7927 IA_CSS_ENTER_PRIVATE("");
7928 assert(pipe != NULL);
7929 assert(pipe->stream != NULL);
7930 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7932 me = &pipe->pipeline;
7933 mode = pipe->config.default_capture_config.mode;
7934 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7935 ia_css_pipeline_clean(me);
7936 ia_css_pipe_util_create_output_frames(out_frames);
7938 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7939 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7940 * except for the following:
7941 * - Direct Sensor Mode Online Capture
7942 * - Direct Sensor Mode Online Capture
7943 * - Direct Sensor Mode Continuous Capture
7944 * - Buffered Sensor Mode Continuous Capture
7946 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7947 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7948 online = pipe->stream->config.online;
7949 continuous = pipe->stream->config.continuous;
7950 need_in_frameinfo_memory =
7951 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7953 /* Construct in_frame info (only in case we have dynamic input */
7954 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7956 if (need_in_frameinfo_memory) {
7957 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW);
7958 if (err != IA_CSS_SUCCESS) {
7959 IA_CSS_LEAVE_ERR_PRIVATE(err);
7963 in_frame = &me->in_frame;
7968 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7969 if (err != IA_CSS_SUCCESS) {
7970 IA_CSS_LEAVE_ERR_PRIVATE(err);
7973 out_frame = &me->out_frame[0];
7975 /* Construct vf_frame info (only in case we have VF) */
7976 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
7977 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7978 /* These modes don't support viewfinder output */
7981 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7982 vf_frame = &me->vf_frame[0];
7988 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7989 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7990 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY)) {
7991 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
7992 return IA_CSS_ERR_INTERNAL_ERROR;
7994 for (i = 0; i < num_primary_stage; i++) {
7995 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7997 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7998 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7999 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
8000 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
8001 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
8002 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
8003 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
8004 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
8005 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
8007 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
8008 mode != IA_CSS_CAPTURE_MODE_RAW &&
8009 mode != IA_CSS_CAPTURE_MODE_BAYER;
8010 need_yuv_pp = (yuv_scaler_binary != NULL && yuv_scaler_binary->info != NULL);
8011 need_ldc = (capture_ldc_binary != NULL && capture_ldc_binary->info != NULL);
8013 if (pipe->pipe_settings.capture.copy_binary.info) {
8015 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8016 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
8018 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8019 out_frames, in_frame, NULL);
8021 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8022 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8023 out_frames, in_frame, NULL);
8026 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8027 out_frames, NULL, NULL);
8030 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
8031 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8032 out_frames, NULL, NULL);
8035 err = ia_css_pipeline_create_and_add_stage(me,
8038 if (err != IA_CSS_SUCCESS) {
8039 IA_CSS_LEAVE_ERR_PRIVATE(err);
8042 } else if (pipe->stream->config.continuous) {
8043 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8046 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
8047 struct ia_css_frame *local_in_frame = NULL;
8048 struct ia_css_frame *local_out_frame = NULL;
8050 for (i = 0; i < num_primary_stage; i++) {
8052 local_in_frame = in_frame;
8054 local_in_frame = NULL;
8056 if (!need_pp && (i == num_primary_stage - 1))
8058 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8060 local_out_frame = out_frame;
8062 local_out_frame = NULL;
8063 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8065 * WARNING: The #if def flag has been added below as a
8066 * temporary solution to solve the problem of enabling the
8067 * view finder in a single binary in a capture flow. The
8068 * vf-pp stage has been removed from Skycam in the solution
8069 * provided. The vf-pp stage should be re-introduced when
8070 * required. This * should not be considered as a clean solution.
8071 * Proper investigation should be done to come up with the clean
8074 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8075 out_frames, local_in_frame, NULL);
8076 err = ia_css_pipeline_create_and_add_stage(me,
8079 if (err != IA_CSS_SUCCESS) {
8080 IA_CSS_LEAVE_ERR_PRIVATE(err);
8084 /* If we use copy iso primary,
8085 the input must be yuv iso raw */
8086 current_stage->args.copy_vf =
8087 primary_binary[0]->info->sp.pipeline.mode ==
8088 IA_CSS_BINARY_MODE_COPY;
8089 current_stage->args.copy_output = current_stage->args.copy_vf;
8090 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8091 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
8092 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8093 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8094 out_frames, in_frame, NULL);
8095 err = ia_css_pipeline_create_and_add_stage(me,
8097 if (err != IA_CSS_SUCCESS) {
8098 IA_CSS_LEAVE_ERR_PRIVATE(err);
8101 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8102 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8103 out_frames, NULL, NULL);
8104 err = ia_css_pipeline_create_and_add_stage(me,
8106 if (err != IA_CSS_SUCCESS) {
8107 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, post_isp_binary,
8114 out_frames, NULL, NULL);
8116 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8117 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8118 out_frames, NULL, NULL);
8121 err = ia_css_pipeline_create_and_add_stage(me,
8122 &stage_desc, ¤t_stage);
8123 if (err != IA_CSS_SUCCESS) {
8124 IA_CSS_LEAVE_ERR_PRIVATE(err);
8127 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER) {
8128 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8129 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8130 out_frames, in_frame, NULL);
8131 err = ia_css_pipeline_create_and_add_stage(me,
8134 if (err != IA_CSS_SUCCESS) {
8135 IA_CSS_LEAVE_ERR_PRIVATE(err);
8141 if (need_pp && current_stage) {
8142 struct ia_css_frame *local_in_frame = NULL;
8143 local_in_frame = current_stage->args.out_frame[0];
8146 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8147 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8148 out_frames, local_in_frame, NULL);
8149 err = ia_css_pipeline_create_and_add_stage(me,
8152 local_in_frame = current_stage->args.out_frame[0];
8154 err = add_capture_pp_stage(pipe, me, local_in_frame, need_yuv_pp ? NULL : out_frame,
8156 /* ldc and capture_pp not supported in same pipeline */
8157 if (need_ldc && current_stage) {
8158 in_frame = current_stage->args.out_frame[0];
8159 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8160 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8161 out_frames, in_frame, NULL);
8162 err = ia_css_pipeline_create_and_add_stage(me,
8165 } else if (need_pp && current_stage) {
8166 in_frame = current_stage->args.out_frame[0];
8167 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8171 if (err != IA_CSS_SUCCESS) {
8172 IA_CSS_LEAVE_ERR_PRIVATE(err);
8177 if (need_yuv_pp && current_stage) {
8178 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8179 struct ia_css_frame *tmp_out_frame = NULL;
8181 for (i = 0; i < num_yuv_scaler; i++) {
8182 if (is_output_stage[i] == true)
8183 tmp_out_frame = out_frame;
8185 tmp_out_frame = NULL;
8187 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8189 &yuv_scaler_binary[i],
8191 if (err != IA_CSS_SUCCESS) {
8192 IA_CSS_LEAVE_ERR_PRIVATE(err);
8195 /* we use output port 1 as internal output port */
8196 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8201 * WARNING: The #if def flag has been added below as a
8202 * temporary solution to solve the problem of enabling the
8203 * view finder in a single binary in a capture flow. The vf-pp
8204 * stage has been removed from Skycam in the solution provided.
8205 * The vf-pp stage should be re-introduced when required. This
8206 * should not be considered as a clean solution. Proper
8207 * investigation should be done to come up with the clean solution.
8209 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame) {
8210 in_frame = current_stage->args.out_vf_frame;
8211 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8213 if (err != IA_CSS_SUCCESS) {
8214 IA_CSS_LEAVE_ERR_PRIVATE(err);
8218 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8220 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8221 "create_host_regular_capture_pipeline() leave:\n");
8223 return IA_CSS_SUCCESS;
8226 static enum ia_css_err
8227 create_host_capture_pipeline(struct ia_css_pipe *pipe)
8229 enum ia_css_err err = IA_CSS_SUCCESS;
8231 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8233 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8234 err = create_host_isyscopy_capture_pipeline(pipe);
8236 err = create_host_regular_capture_pipeline(pipe);
8237 if (err != IA_CSS_SUCCESS) {
8238 IA_CSS_LEAVE_ERR_PRIVATE(err);
8242 IA_CSS_LEAVE_ERR_PRIVATE(err);
8247 static enum ia_css_err capture_start(
8248 struct ia_css_pipe *pipe)
8250 struct ia_css_pipeline *me;
8252 enum ia_css_err err = IA_CSS_SUCCESS;
8253 enum sh_css_pipe_config_override copy_ovrd;
8255 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8257 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8258 return IA_CSS_ERR_INVALID_ARGUMENTS;
8261 me = &pipe->pipeline;
8263 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8264 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ) &&
8265 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8266 if (copy_on_sp(pipe)) {
8267 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8268 IA_CSS_LEAVE_ERR_PRIVATE(err);
8273 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8274 /* old isys: need to send_mipi_frames() in all pipe modes */
8275 err = send_mipi_frames(pipe);
8276 if (err != IA_CSS_SUCCESS) {
8277 IA_CSS_LEAVE_ERR_PRIVATE(err);
8280 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8281 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8282 err = send_mipi_frames(pipe);
8283 if (err != IA_CSS_SUCCESS) {
8284 IA_CSS_LEAVE_ERR_PRIVATE(err);
8292 unsigned int thread_id;
8294 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8295 copy_ovrd = 1 << thread_id;
8298 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8300 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8302 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8303 * which is currently done in start_binary(); but COPY pipe contains no binary,
8304 * and does not call start_binary(); so we need to configure the rx here.
8306 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY && pipe->stream->reconfigure_css_rx) {
8307 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config, pipe->stream->config.mode);
8308 pipe->stream->reconfigure_css_rx = false;
8312 IA_CSS_LEAVE_ERR_PRIVATE(err);
8317 static enum ia_css_err
8318 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8319 struct ia_css_frame_info *info,
8322 assert(pipe != NULL);
8323 assert(info != NULL);
8325 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8326 "sh_css_pipe_get_output_frame_info() enter:\n");
8328 *info = pipe->output_info[idx];
8329 if (copy_on_sp(pipe) &&
8330 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
8331 ia_css_frame_info_init(
8335 IA_CSS_FRAME_FORMAT_BINARY_8,
8337 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8338 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) {
8339 info->raw_bit_depth =
8340 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8344 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8345 "sh_css_pipe_get_output_frame_info() leave:\n");
8346 return IA_CSS_SUCCESS;
8349 #if !defined(HAS_NO_INPUT_SYSTEM)
8351 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8352 const unsigned short *data,
8354 unsigned int height)
8356 assert(stream != NULL);
8358 ia_css_inputfifo_send_input_frame(
8359 data, width, height,
8360 stream->config.channel_id,
8361 stream->config.input_config.format,
8362 stream->config.pixels_per_clock == 2);
8366 ia_css_stream_start_input_frame(const struct ia_css_stream *stream)
8368 assert(stream != NULL);
8370 ia_css_inputfifo_start_frame(
8371 stream->config.channel_id,
8372 stream->config.input_config.format,
8373 stream->config.pixels_per_clock == 2);
8377 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8378 const unsigned short *data,
8380 const unsigned short *data2,
8381 unsigned int width2)
8383 assert(stream != NULL);
8385 ia_css_inputfifo_send_line(stream->config.channel_id,
8386 data, width, data2, width2);
8390 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8391 enum atomisp_input_format format,
8392 const unsigned short *data,
8395 assert(stream != NULL);
8396 if (data == NULL || width == 0)
8398 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8399 format, data, width);
8403 ia_css_stream_end_input_frame(const struct ia_css_stream *stream)
8405 assert(stream != NULL);
8407 ia_css_inputfifo_end_frame(stream->config.channel_id);
8412 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8414 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l , firmware);
8416 IA_CSS_ERROR("NULL fw_info");
8417 IA_CSS_LEAVE_PRIVATE("");
8423 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8424 IA_CSS_LEAVE_PRIVATE("");
8428 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware)
8434 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8436 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8437 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8440 static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware)
8442 hrt_vaddress binary;
8444 if (firmware == NULL) {
8445 IA_CSS_ERROR("NULL input parameter");
8446 return IA_CSS_ERR_INVALID_ARGUMENTS;
8448 binary = firmware->info.isp.xmem_addr;
8451 unsigned size = firmware->blob.size;
8452 const unsigned char *blob;
8453 const unsigned char *binary_name;
8455 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8457 blob = binary_name +
8458 strlen((const char *)binary_name) +
8460 binary = sh_css_load_blob(blob, size);
8461 firmware->info.isp.xmem_addr = binary;
8465 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
8466 return IA_CSS_SUCCESS;
8469 static enum ia_css_err
8470 acc_load_extension(struct ia_css_fw_info *firmware)
8472 enum ia_css_err err;
8473 struct ia_css_fw_info *hd = firmware;
8475 err = upload_isp_code(hd);
8476 if (err != IA_CSS_SUCCESS)
8481 if (firmware == NULL)
8482 return IA_CSS_ERR_INVALID_ARGUMENTS;
8483 firmware->loaded = true;
8484 return IA_CSS_SUCCESS;
8488 acc_unload_extension(struct ia_css_fw_info *firmware)
8490 struct ia_css_fw_info *hd = firmware;
8491 struct ia_css_fw_info *hdn = NULL;
8493 if (firmware == NULL) /* should not happen */
8495 /* unload and remove multiple firmwares */
8497 hdn = (hd->next) ? &(*hd->next) : NULL;
8498 if (hd->info.isp.xmem_addr) {
8499 hmm_free(hd->info.isp.xmem_addr);
8500 hd->info.isp.xmem_addr = mmgr_NULL;
8502 hd->isp_code = NULL;
8507 firmware->loaded = false;
8509 /* Load firmware for extension */
8510 static enum ia_css_err
8511 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8512 struct ia_css_fw_info *firmware)
8514 enum ia_css_err err = IA_CSS_SUCCESS;
8516 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8518 if ((firmware == NULL) || (pipe == NULL)) {
8519 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8520 return IA_CSS_ERR_INVALID_ARGUMENTS;
8523 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT) {
8524 if (&pipe->output_stage != NULL)
8525 append_firmware(&pipe->output_stage, firmware);
8527 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8528 return IA_CSS_ERR_INTERNAL_ERROR;
8531 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER) {
8532 if (&pipe->vf_stage != NULL)
8533 append_firmware(&pipe->vf_stage, firmware);
8535 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
8536 return IA_CSS_ERR_INTERNAL_ERROR;
8539 err = acc_load_extension(firmware);
8541 IA_CSS_LEAVE_ERR_PRIVATE(err);
8545 /* Unload firmware for extension */
8547 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8548 struct ia_css_fw_info *firmware)
8550 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8552 if ((firmware == NULL) || (pipe == NULL)) {
8553 IA_CSS_ERROR("NULL input parameters");
8554 IA_CSS_LEAVE_PRIVATE("");
8558 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8559 remove_firmware(&pipe->output_stage, firmware);
8560 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8561 remove_firmware(&pipe->vf_stage, firmware);
8562 acc_unload_extension(firmware);
8564 IA_CSS_LEAVE_PRIVATE("");
8568 ia_css_pipeline_uses_params(struct ia_css_pipeline *me)
8570 struct ia_css_pipeline_stage *stage;
8574 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8575 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8577 for (stage = me->stages; stage; stage = stage->next)
8578 if (stage->binary_info && stage->binary_info->enable.params) {
8579 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8580 "ia_css_pipeline_uses_params() leave: "
8581 "return_bool=true\n");
8584 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8585 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8589 static enum ia_css_err
8590 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8593 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8594 /* In QoS case, load_extension already called, so skipping */
8595 enum ia_css_err err = IA_CSS_SUCCESS;
8596 if (fw->loaded == false)
8597 err = acc_load_extension(fw);
8599 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8600 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p,"
8601 " acc_fw=%p\n", pipeline, acc_fw);
8603 if (err == IA_CSS_SUCCESS) {
8604 struct ia_css_pipeline_stage_desc stage_desc;
8605 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8606 err = ia_css_pipeline_create_and_add_stage(pipeline,
8611 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8612 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n",err);
8617 * @brief Tag a specific frame in continuous capture.
8618 * Refer to "sh_css_internal.h" for details.
8620 enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream,
8621 unsigned int exp_id)
8623 struct sh_css_tag_descr tag_descr;
8624 uint32_t encoded_tag_descr;
8625 enum ia_css_err err;
8627 assert(stream != NULL);
8628 IA_CSS_ENTER("exp_id=%d", exp_id);
8630 /* Only continuous streams have a tagger */
8631 if (exp_id == 0 || !stream->config.continuous) {
8632 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
8633 return IA_CSS_ERR_INVALID_ARGUMENTS;
8636 if (!sh_css_sp_is_running()) {
8637 /* SP is not running. The queues are not valid */
8638 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
8639 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8642 /* Create the tag descriptor from the parameters */
8643 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8644 /* Encode the tag descriptor into a 32-bit value */
8645 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8646 /* Enqueue the encoded tag to the host2sp queue.
8647 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8648 * on both host and the SP side.
8649 * It is mainly because it is enough to have only one tag_cmd queue */
8650 err= ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8652 IA_CSS_LEAVE_ERR(err);
8657 * @brief Configure the continuous capture.
8658 * Refer to "sh_css_internal.h" for details.
8660 enum ia_css_err ia_css_stream_capture(
8661 struct ia_css_stream *stream,
8666 struct sh_css_tag_descr tag_descr;
8667 unsigned int encoded_tag_descr;
8668 enum ia_css_err return_err;
8671 return IA_CSS_ERR_INVALID_ARGUMENTS;
8673 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8674 "ia_css_stream_capture() enter: num_captures=%d,"
8675 " skip=%d, offset=%d\n", num_captures, skip,offset);
8677 /* Check if the tag descriptor is valid */
8678 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8679 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8680 "ia_css_stream_capture() leave: return_err=%d\n",
8681 IA_CSS_ERR_INVALID_ARGUMENTS);
8682 return IA_CSS_ERR_INVALID_ARGUMENTS;
8685 /* Create the tag descriptor from the parameters */
8686 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8689 /* Encode the tag descriptor into a 32-bit value */
8690 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8692 if (!sh_css_sp_is_running()) {
8693 /* SP is not running. The queues are not valid */
8694 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8695 "ia_css_stream_capture() leaving:"
8696 "queues unavailable\n");
8697 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8700 /* Enqueue the encoded tag to the host2sp queue.
8701 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8702 * on both host and the SP side.
8703 * It is mainly because it is enough to have only one tag_cmd queue */
8704 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8706 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8707 "ia_css_stream_capture() leave: return_err=%d\n",
8713 void ia_css_stream_request_flash(struct ia_css_stream *stream)
8717 assert(stream != NULL);
8718 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_request_flash() enter: void\n");
8721 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8723 if (sh_css_sp_is_running()) {
8724 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8725 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8726 ia_css_debug_dump_sp_sw_debug_info();
8727 ia_css_debug_dump_debug_info(NULL);
8730 IA_CSS_LOG("SP is not running!");
8733 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8734 "ia_css_stream_request_flash() leave: return_void\n");
8738 sh_css_init_host_sp_control_vars(void)
8740 const struct ia_css_fw_info *fw;
8741 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8743 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8744 unsigned int HIVE_ADDR_sp_sleep_mode;
8745 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8747 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8749 unsigned int HIVE_ADDR_host_sp_com;
8750 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8753 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8757 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8758 "sh_css_init_host_sp_control_vars() enter: void\n");
8761 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8763 HIVE_ADDR_host_sp_queues_initialized =
8764 fw->info.sp.host_sp_queues_initialized;
8765 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8766 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8768 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8770 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8772 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8774 (void)HIVE_ADDR_sp_sleep_mode;
8775 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8777 (void)HIVE_ADDR_sp_stop_copy_preview;
8779 (void)HIVE_ADDR_host_sp_com;
8781 sp_dmem_store_uint32(SP0_ID,
8782 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8785 sp_dmem_store_uint32(SP0_ID,
8786 (unsigned int)sp_address_of(host_sp_queues_initialized),
8788 sp_dmem_store_uint32(SP0_ID,
8789 (unsigned int)sp_address_of(sp_sleep_mode),
8791 sp_dmem_store_uint32(SP0_ID,
8792 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8795 sp_dmem_store_uint32(SP0_ID,
8796 (unsigned int)sp_address_of(sp_stop_copy_preview),
8797 my_css.stop_copy_preview?(uint32_t)(1):(uint32_t)(0));
8799 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8801 #if !defined(HAS_NO_INPUT_SYSTEM)
8802 for (i = 0; i < N_CSI_PORTS; i++) {
8803 sh_css_update_host2sp_num_mipi_frames
8804 (my_css.num_mipi_frames[i]);
8808 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8809 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8813 * create the internal structures and fill in the configuration data
8815 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8817 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8818 *pipe_config = DEFAULT_PIPE_CONFIG;
8822 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config *extra_config)
8824 if (extra_config == NULL) {
8825 IA_CSS_ERROR("NULL input parameter");
8829 extra_config->enable_raw_binning = false;
8830 extra_config->enable_yuv_ds = false;
8831 extra_config->enable_high_speed = false;
8832 extra_config->enable_dvs_6axis = false;
8833 extra_config->enable_reduced_pipe = false;
8834 extra_config->disable_vf_pp = false;
8835 extra_config->enable_fractional_ds = false;
8838 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8840 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8841 assert(stream_config != NULL);
8842 memset(stream_config, 0, sizeof(*stream_config));
8843 stream_config->online = true;
8844 stream_config->left_padding = -1;
8845 stream_config->pixels_per_clock = 1;
8846 /* temporary default value for backwards compatibility.
8847 * This field used to be hardcoded within CSS but this has now
8848 * been moved to the stream_config struct. */
8849 stream_config->source.port.rxcount = 0x04040404;
8852 static enum ia_css_err
8853 ia_css_acc_pipe_create(struct ia_css_pipe *pipe)
8855 enum ia_css_err err = IA_CSS_SUCCESS;
8858 IA_CSS_ERROR("NULL input parameter");
8859 return IA_CSS_ERR_INVALID_ARGUMENTS;
8862 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8863 if (pipe->config.acc_num_execs == 0)
8864 pipe->config.acc_num_execs = 1;
8866 if (pipe->config.acc_extension) {
8867 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8874 ia_css_pipe_create(const struct ia_css_pipe_config *config,
8875 struct ia_css_pipe **pipe)
8880 enum ia_css_err err = IA_CSS_SUCCESS;
8881 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8883 if (config == NULL) {
8884 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8886 return IA_CSS_ERR_INVALID_ARGUMENTS;
8892 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8894 return IA_CSS_ERR_INVALID_ARGUMENTS;
8896 return ia_css_pipe_create_extra(config, NULL, pipe);
8900 err = ia_css_pipe_create_extra(config, NULL, pipe);
8902 if(err == IA_CSS_SUCCESS) {
8903 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8906 IA_CSS_LEAVE_ERR_PRIVATE(err);
8913 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8914 const struct ia_css_pipe_extra_config *extra_config,
8915 struct ia_css_pipe **pipe)
8917 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
8918 struct ia_css_pipe *internal_pipe = NULL;
8921 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8923 /* do not allow to create more than the maximum limit */
8924 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX) {
8925 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED);
8926 return IA_CSS_ERR_INVALID_ARGUMENTS;
8929 if ((pipe == NULL) || (config == NULL)) {
8930 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8931 return IA_CSS_ERR_INVALID_ARGUMENTS;
8934 ia_css_debug_dump_pipe_config(config);
8935 ia_css_debug_dump_pipe_extra_config(extra_config);
8937 err = create_pipe(config->mode, &internal_pipe, false);
8938 if (err != IA_CSS_SUCCESS) {
8939 IA_CSS_LEAVE_ERR_PRIVATE(err);
8943 /* now we have a pipe structure to fill */
8944 internal_pipe->config = *config;
8946 internal_pipe->extra_config = *extra_config;
8948 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8950 if (config->mode == IA_CSS_PIPE_MODE_ACC) {
8951 /* Temporary hack to migrate acceleration to CSS 2.0.
8952 * In the future the code for all pipe types should be
8954 *pipe = internal_pipe;
8955 if (!internal_pipe->config.acc_extension &&
8956 internal_pipe->config.num_acc_stages == 0){ /* if no acc binary and no standalone stage */
8958 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
8959 return IA_CSS_SUCCESS;
8961 return ia_css_acc_pipe_create(internal_pipe);
8964 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8965 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8966 internal_pipe->dvs_frame_delay = 2;
8968 internal_pipe->dvs_frame_delay = 1;
8971 /* we still keep enable_raw_binning for backward compatibility, for any new
8972 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8973 specified, bayer_ds_out_res will take precedence.if none is specified, we
8974 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8975 sensor output) or use default decimation factor 1. */
8976 if (internal_pipe->extra_config.enable_raw_binning &&
8977 internal_pipe->config.bayer_ds_out_res.width) {
8978 /* fill some code here, if no code is needed, please remove it during integration */
8981 /* YUV downscaling */
8982 if ((internal_pipe->config.vf_pp_in_res.width ||
8983 internal_pipe->config.capt_pp_in_res.width)) {
8984 enum ia_css_frame_format format;
8985 if (internal_pipe->config.vf_pp_in_res.width) {
8986 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8987 ia_css_frame_info_init(
8988 &internal_pipe->vf_yuv_ds_input_info,
8989 internal_pipe->config.vf_pp_in_res.width,
8990 internal_pipe->config.vf_pp_in_res.height,
8993 if (internal_pipe->config.capt_pp_in_res.width) {
8994 format = IA_CSS_FRAME_FORMAT_YUV420;
8995 ia_css_frame_info_init(
8996 &internal_pipe->out_yuv_ds_input_info,
8997 internal_pipe->config.capt_pp_in_res.width,
8998 internal_pipe->config.capt_pp_in_res.height,
9002 if (internal_pipe->config.vf_pp_in_res.width &&
9003 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
9004 ia_css_frame_info_init(
9005 &internal_pipe->vf_yuv_ds_input_info,
9006 internal_pipe->config.vf_pp_in_res.width,
9007 internal_pipe->config.vf_pp_in_res.height,
9008 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
9010 /* handle bayer downscaling output info */
9011 if (internal_pipe->config.bayer_ds_out_res.width) {
9012 ia_css_frame_info_init(
9013 &internal_pipe->bds_output_info,
9014 internal_pipe->config.bayer_ds_out_res.width,
9015 internal_pipe->config.bayer_ds_out_res.height,
9016 IA_CSS_FRAME_FORMAT_RAW, 0);
9019 /* handle output info, assume always needed */
9020 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
9021 if (internal_pipe->config.output_info[i].res.width) {
9022 err = sh_css_pipe_configure_output(
9024 internal_pipe->config.output_info[i].res.width,
9025 internal_pipe->config.output_info[i].res.height,
9026 internal_pipe->config.output_info[i].padded_width,
9027 internal_pipe->config.output_info[i].format,
9029 if (err != IA_CSS_SUCCESS) {
9030 IA_CSS_LEAVE_ERR_PRIVATE(err);
9031 sh_css_free(internal_pipe);
9032 internal_pipe = NULL;
9037 /* handle vf output info, when configured */
9038 internal_pipe->enable_viewfinder[i] = (internal_pipe->config.vf_output_info[i].res.width != 0);
9039 if (internal_pipe->config.vf_output_info[i].res.width) {
9040 err = sh_css_pipe_configure_viewfinder(
9042 internal_pipe->config.vf_output_info[i].res.width,
9043 internal_pipe->config.vf_output_info[i].res.height,
9044 internal_pipe->config.vf_output_info[i].padded_width,
9045 internal_pipe->config.vf_output_info[i].format,
9047 if (err != IA_CSS_SUCCESS) {
9048 IA_CSS_LEAVE_ERR_PRIVATE(err);
9049 sh_css_free(internal_pipe);
9050 internal_pipe = NULL;
9055 if (internal_pipe->config.acc_extension) {
9056 err = ia_css_pipe_load_extension(internal_pipe,
9057 internal_pipe->config.acc_extension);
9058 if (err != IA_CSS_SUCCESS) {
9059 IA_CSS_LEAVE_ERR_PRIVATE(err);
9060 sh_css_free(internal_pipe);
9064 /* set all info to zeroes first */
9065 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9067 /* all went well, return the pipe */
9068 *pipe = internal_pipe;
9069 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9070 return IA_CSS_SUCCESS;
9075 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9076 struct ia_css_pipe_info *pipe_info)
9078 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9079 "ia_css_pipe_get_info()\n");
9080 assert(pipe_info != NULL);
9081 if (pipe_info == NULL) {
9082 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9083 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9084 return IA_CSS_ERR_INVALID_ARGUMENTS;
9086 if (pipe == NULL || pipe->stream == NULL) {
9087 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9088 "ia_css_pipe_get_info: ia_css_stream_create needs to"
9089 " be called before ia_css_[stream/pipe]_get_info\n");
9090 return IA_CSS_ERR_INVALID_ARGUMENTS;
9092 /* we succeeded return the info */
9093 *pipe_info = pipe->info;
9094 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9095 return IA_CSS_SUCCESS;
9098 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
9102 if (pipe_info != NULL) {
9103 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9104 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9114 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9116 enum ia_css_frame_format new_format)
9118 enum ia_css_err err = IA_CSS_SUCCESS;
9120 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9123 IA_CSS_ERROR("pipe is not set");
9124 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9125 IA_CSS_LEAVE_ERR_PRIVATE(err);
9128 if (0 != pin_index && 1 != pin_index) {
9129 IA_CSS_ERROR("pin index is not valid");
9130 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9131 IA_CSS_LEAVE_ERR_PRIVATE(err);
9134 if (IA_CSS_FRAME_FORMAT_NV12_TILEY != new_format) {
9135 IA_CSS_ERROR("new format is not valid");
9136 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9137 IA_CSS_LEAVE_ERR_PRIVATE(err);
9140 err = ia_css_pipe_check_format(pipe, new_format);
9141 if (IA_CSS_SUCCESS == err) {
9142 if (pin_index == 0) {
9143 pipe->output_info[0].format = new_format;
9145 pipe->vf_output_info[0].format = new_format;
9149 IA_CSS_LEAVE_ERR_PRIVATE(err);
9154 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9155 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9156 static enum ia_css_err
9157 ia_css_stream_configure_rx(struct ia_css_stream *stream)
9159 struct ia_css_input_port *config;
9160 assert(stream != NULL);
9162 config = &stream->config.source.port;
9163 /* AM: this code is not reliable, especially for 2400 */
9164 if (config->num_lanes == 1)
9165 stream->csi_rx_config.mode = MONO_1L_1L_0L;
9166 else if (config->num_lanes == 2)
9167 stream->csi_rx_config.mode = MONO_2L_1L_0L;
9168 else if (config->num_lanes == 3)
9169 stream->csi_rx_config.mode = MONO_3L_1L_0L;
9170 else if (config->num_lanes == 4)
9171 stream->csi_rx_config.mode = MONO_4L_1L_0L;
9172 else if (config->num_lanes != 0)
9173 return IA_CSS_ERR_INVALID_ARGUMENTS;
9175 if (config->port > MIPI_PORT2_ID)
9176 return IA_CSS_ERR_INVALID_ARGUMENTS;
9177 stream->csi_rx_config.port =
9178 ia_css_isys_port_to_mipi_port(config->port);
9179 stream->csi_rx_config.timeout = config->timeout;
9180 stream->csi_rx_config.initcount = 0;
9181 stream->csi_rx_config.synccount = 0x28282828;
9182 stream->csi_rx_config.rxcount = config->rxcount;
9183 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9184 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9186 /* not implemented yet, requires extension of the rx_cfg_t
9188 return IA_CSS_ERR_INVALID_ARGUMENTS;
9190 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9191 stream->reconfigure_css_rx = true;
9192 return IA_CSS_SUCCESS;
9196 static struct ia_css_pipe *
9197 find_pipe(struct ia_css_pipe *pipes[],
9198 unsigned int num_pipes,
9199 enum ia_css_pipe_mode mode,
9203 assert(pipes != NULL);
9204 for (i = 0; i < num_pipes; i++) {
9205 assert(pipes[i] != NULL);
9206 if (pipes[i]->config.mode != mode)
9208 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9215 static enum ia_css_err
9216 ia_css_acc_stream_create(struct ia_css_stream *stream)
9219 enum ia_css_err err = IA_CSS_SUCCESS;
9221 assert(stream != NULL);
9222 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9224 if (stream == NULL) {
9225 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9226 return IA_CSS_ERR_INVALID_ARGUMENTS;
9229 for (i = 0; i < stream->num_pipes; i++) {
9230 struct ia_css_pipe *pipe = stream->pipes[i];
9231 assert(pipe != NULL);
9233 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9234 return IA_CSS_ERR_INVALID_ARGUMENTS;
9237 pipe->stream = stream;
9240 /* Map SP threads before doing anything. */
9241 err = map_sp_threads(stream, true);
9242 if (err != IA_CSS_SUCCESS) {
9243 IA_CSS_LEAVE_ERR_PRIVATE(err);
9247 for (i = 0; i < stream->num_pipes; i++) {
9248 struct ia_css_pipe *pipe = stream->pipes[i];
9249 assert(pipe != NULL);
9250 ia_css_pipe_map_queue(pipe, true);
9253 err = create_host_pipeline_structure(stream);
9254 if (err != IA_CSS_SUCCESS) {
9255 IA_CSS_LEAVE_ERR_PRIVATE(err);
9259 stream->started = false;
9262 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9264 return IA_CSS_SUCCESS;
9267 static enum ia_css_err
9268 metadata_info_init(const struct ia_css_metadata_config *mdc,
9269 struct ia_css_metadata_info *md)
9271 /* Either both width and height should be set or neither */
9272 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9273 return IA_CSS_ERR_INVALID_ARGUMENTS;
9275 md->resolution = mdc->resolution;
9276 /* We round up the stride to a multiple of the width
9277 * of the port going to DDR, this is a HW requirements (DMA). */
9278 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9279 md->size = mdc->resolution.height * md->stride;
9280 return IA_CSS_SUCCESS;
9284 static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe)
9286 enum ia_css_err err = IA_CSS_SUCCESS;
9288 IA_CSS_ENTER_PRIVATE("");
9290 if (!pipe || !pipe->stream) {
9291 IA_CSS_ERROR("null arguments");
9292 err = IA_CSS_ERR_INTERNAL_ERROR;
9296 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9297 pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) {
9298 IA_CSS_ERROR("effective resolution not supported");
9299 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9302 if (!ia_css_util_resolution_is_zero(pipe->stream->config.input_config.input_res)) {
9303 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9304 pipe->stream->config.input_config.input_res)) {
9305 IA_CSS_ERROR("effective resolution is larger than input resolution");
9306 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9310 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9311 IA_CSS_ERROR("output resolution must be even");
9312 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9315 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9316 IA_CSS_ERROR("VF resolution must be even");
9317 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9321 IA_CSS_LEAVE_ERR_PRIVATE(err);
9328 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9330 struct ia_css_pipe *pipes[],
9331 struct ia_css_stream **stream)
9333 struct ia_css_pipe *curr_pipe;
9334 struct ia_css_stream *curr_stream = NULL;
9336 bool sensor_binning_changed;
9338 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
9339 struct ia_css_metadata_info md_info;
9341 struct ia_css_resolution effective_res;
9343 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9344 bool aspect_ratio_crop_enabled = false;
9348 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9349 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9352 if (num_pipes == 0 ||
9355 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9356 IA_CSS_LEAVE_ERR(err);
9360 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9361 /* We don't support metadata for JPEG stream, since they both use str2mem */
9362 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9363 stream_config->metadata_config.resolution.height > 0) {
9364 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9365 IA_CSS_LEAVE_ERR(err);
9370 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9371 if (stream_config->online && stream_config->pack_raw_pixels) {
9372 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9373 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9374 IA_CSS_LEAVE_ERR(err);
9379 #if !defined(HAS_NO_INPUT_SYSTEM)
9380 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9382 /* check if mipi size specified */
9383 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9384 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9385 if (!stream_config->online)
9388 unsigned int port = (unsigned int) stream_config->source.port.port;
9389 if (port >= N_MIPI_PORT_ID) {
9390 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9391 IA_CSS_LEAVE_ERR(err);
9395 if (my_css.size_mem_words != 0){
9396 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9397 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9398 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9400 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9401 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9402 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9403 err = IA_CSS_ERR_INTERNAL_ERROR;
9404 IA_CSS_LEAVE_ERR(err);
9408 if (my_css.size_mem_words != 0) {
9409 my_css.num_mipi_frames[port] = 2; /* Temp change: Default for backwards compatibility. */
9410 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9411 my_css.num_mipi_frames[port] = stream_config->mipi_buffer_config.nof_mipi_buffers;
9413 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9414 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9415 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9416 err = IA_CSS_ERR_INTERNAL_ERROR;
9417 IA_CSS_LEAVE_ERR(err);
9424 /* Currently we only supported metadata up to a certain size. */
9425 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9426 if (err != IA_CSS_SUCCESS) {
9427 IA_CSS_LEAVE_ERR(err);
9431 /* allocate the stream instance */
9432 curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9434 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9435 IA_CSS_LEAVE_ERR(err);
9438 /* default all to 0 */
9439 memset(curr_stream, 0, sizeof(struct ia_css_stream));
9440 curr_stream->info.metadata_info = md_info;
9442 /* allocate pipes */
9443 curr_stream->num_pipes = num_pipes;
9444 curr_stream->pipes = kzalloc(num_pipes * sizeof(struct ia_css_pipe *), GFP_KERNEL);
9445 if (!curr_stream->pipes) {
9446 curr_stream->num_pipes = 0;
9449 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9450 IA_CSS_LEAVE_ERR(err);
9454 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9455 for (i = 0; i < num_pipes; i++)
9456 curr_stream->pipes [i] = pipes[i];
9457 curr_stream->last_pipe = curr_stream->pipes[0];
9458 /* take over stream config */
9459 curr_stream->config = *stream_config;
9461 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9462 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9463 stream_config->online)
9464 curr_stream->config.online = false;
9467 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9468 if (curr_stream->config.online) {
9469 curr_stream->config.source.port.num_lanes = stream_config->source.port.num_lanes;
9470 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9473 /* in case driver doesn't configure init number of raw buffers, configure it here */
9474 if (curr_stream->config.target_num_cont_raw_buf == 0)
9475 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9476 if (curr_stream->config.init_num_cont_raw_buf == 0)
9477 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9479 /* Enable locking & unlocking of buffers in RAW buffer pool */
9480 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9481 sh_css_sp_configure_enable_raw_pool_locking(
9482 curr_stream->config.lock_all);
9484 /* copy mode specific stuff */
9485 switch (curr_stream->config.mode) {
9486 case IA_CSS_INPUT_MODE_SENSOR:
9487 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9488 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9489 ia_css_stream_configure_rx(curr_stream);
9492 case IA_CSS_INPUT_MODE_TPG:
9493 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9494 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9495 curr_stream->config.source.tpg.x_mask,
9496 curr_stream->config.source.tpg.y_mask,
9497 curr_stream->config.source.tpg.x_delta,
9498 curr_stream->config.source.tpg.y_delta,
9499 curr_stream->config.source.tpg.xy_mask);
9501 sh_css_sp_configure_tpg(
9502 curr_stream->config.source.tpg.x_mask,
9503 curr_stream->config.source.tpg.y_mask,
9504 curr_stream->config.source.tpg.x_delta,
9505 curr_stream->config.source.tpg.y_delta,
9506 curr_stream->config.source.tpg.xy_mask);
9509 case IA_CSS_INPUT_MODE_PRBS:
9510 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9511 IA_CSS_LOG("mode prbs");
9512 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9515 case IA_CSS_INPUT_MODE_MEMORY:
9516 IA_CSS_LOG("mode memory");
9517 curr_stream->reconfigure_css_rx = false;
9520 IA_CSS_LOG("mode sensor/default");
9524 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9525 err = aspect_ratio_crop_init(curr_stream,
9527 &aspect_ratio_crop_enabled);
9528 if (err != IA_CSS_SUCCESS) {
9529 IA_CSS_LEAVE_ERR(err);
9535 for (i = 0; i < num_pipes; i++) {
9537 struct ia_css_resolution effective_res;
9539 curr_pipe = pipes[i];
9540 /* set current stream */
9541 curr_pipe->stream = curr_stream;
9542 /* take over effective info */
9544 effective_res = curr_pipe->config.input_effective_res;
9545 if (effective_res.height == 0 || effective_res.width == 0) {
9546 effective_res = curr_pipe->stream->config.input_config.effective_res;
9549 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9550 /* The aspect ratio cropping is currently only
9551 * supported on the new input system. */
9552 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9554 struct ia_css_resolution crop_res;
9556 err = aspect_ratio_crop(curr_pipe, &crop_res);
9557 if (err == IA_CSS_SUCCESS) {
9558 effective_res = crop_res;
9560 /* in case of error fallback to default
9561 * effective resolution from driver. */
9562 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9567 curr_pipe->config.input_effective_res = effective_res;
9569 IA_CSS_LOG("effective_res=%dx%d",
9570 effective_res.width,
9571 effective_res.height);
9575 for (i = 0; i < num_pipes; i++) {
9576 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9577 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9578 err = check_pipe_resolutions(pipes[i]);
9579 if (err != IA_CSS_SUCCESS) {
9586 err = ia_css_stream_isp_parameters_init(curr_stream);
9587 if (err != IA_CSS_SUCCESS)
9589 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9591 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC) {
9592 *stream = curr_stream;
9593 err = ia_css_acc_stream_create(curr_stream);
9596 /* sensor binning */
9598 sensor_binning_changed =
9599 sh_css_params_set_binning_factor(curr_stream, curr_stream->config.sensor_binning_factor);
9601 sensor_binning_changed = false;
9604 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9605 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9606 /* loop over pipes */
9607 IA_CSS_LOG("num_pipes=%d", num_pipes);
9608 curr_stream->cont_capt = false;
9609 /* Temporary hack: we give the preview pipe a reference to the capture
9610 * pipe in continuous capture mode. */
9611 if (curr_stream->config.continuous) {
9612 /* Search for the preview pipe and create the copy pipe */
9613 struct ia_css_pipe *preview_pipe;
9614 struct ia_css_pipe *video_pipe;
9615 struct ia_css_pipe *acc_pipe;
9616 struct ia_css_pipe *capture_pipe = NULL;
9617 struct ia_css_pipe *copy_pipe = NULL;
9619 if (num_pipes >= 2) {
9620 curr_stream->cont_capt = true;
9621 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9623 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9627 /* Create copy pipe here, since it may not be exposed to the driver */
9628 preview_pipe = find_pipe(pipes, num_pipes,
9629 IA_CSS_PIPE_MODE_PREVIEW, false);
9630 video_pipe = find_pipe(pipes, num_pipes,
9631 IA_CSS_PIPE_MODE_VIDEO, false);
9632 acc_pipe = find_pipe(pipes, num_pipes,
9633 IA_CSS_PIPE_MODE_ACC, false);
9634 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9635 curr_stream->cont_capt = false; /* preview + QoS case will not need cont_capt switch */
9636 if (curr_stream->cont_capt == true) {
9637 capture_pipe = find_pipe(pipes, num_pipes,
9638 IA_CSS_PIPE_MODE_CAPTURE, false);
9639 if (capture_pipe == NULL) {
9640 err = IA_CSS_ERR_INTERNAL_ERROR;
9644 /* We do not support preview and video pipe at the same time */
9645 if (preview_pipe && video_pipe) {
9646 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9650 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9651 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9652 if (err != IA_CSS_SUCCESS)
9654 ia_css_pipe_config_defaults(©_pipe->config);
9655 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9656 copy_pipe->stream = curr_stream;
9658 if (preview_pipe && (curr_stream->cont_capt == true)) {
9659 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9661 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9662 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9663 if (err != IA_CSS_SUCCESS)
9665 ia_css_pipe_config_defaults(©_pipe->config);
9666 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9667 copy_pipe->stream = curr_stream;
9669 if (video_pipe && (curr_stream->cont_capt == true)) {
9670 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9672 if (preview_pipe && acc_pipe) {
9673 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9676 for (i = 0; i < num_pipes; i++) {
9677 curr_pipe = pipes[i];
9678 /* set current stream */
9679 curr_pipe->stream = curr_stream;
9681 /* take over effective info */
9683 effective_res = curr_pipe->config.input_effective_res;
9684 err = ia_css_util_check_res(
9685 effective_res.width,
9686 effective_res.height);
9687 if (err != IA_CSS_SUCCESS)
9690 /* sensor binning per pipe */
9691 if (sensor_binning_changed)
9692 sh_css_pipe_free_shading_table(curr_pipe);
9695 /* now pipes have been configured, info should be available */
9696 for (i = 0; i < num_pipes; i++) {
9697 struct ia_css_pipe_info *pipe_info = NULL;
9698 curr_pipe = pipes[i];
9700 err = sh_css_pipe_load_binaries(curr_pipe);
9701 if (err != IA_CSS_SUCCESS)
9704 /* handle each pipe */
9705 pipe_info = &curr_pipe->info;
9706 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9707 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9708 &pipe_info->output_info[j], j);
9709 if (err != IA_CSS_SUCCESS)
9713 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9716 err = sh_css_pipe_get_shading_info(curr_pipe,
9718 &pipe_info->shading_info);
9720 &pipe_info->shading_info, &curr_pipe->config);
9722 if (err != IA_CSS_SUCCESS)
9724 err = sh_css_pipe_get_grid_info(curr_pipe,
9725 &pipe_info->grid_info);
9726 if (err != IA_CSS_SUCCESS)
9728 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9729 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9730 &pipe_info->vf_output_info[j], j);
9731 if (err != IA_CSS_SUCCESS)
9736 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9739 curr_stream->started = false;
9741 /* Map SP threads before doing anything. */
9742 err = map_sp_threads(curr_stream, true);
9743 if (err != IA_CSS_SUCCESS) {
9744 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9748 for (i = 0; i < num_pipes; i++) {
9749 curr_pipe = pipes[i];
9750 ia_css_pipe_map_queue(curr_pipe, true);
9753 /* Create host side pipeline objects without stages */
9754 err = create_host_pipeline_structure(curr_stream);
9755 if (err != IA_CSS_SUCCESS) {
9756 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9760 /* assign curr_stream */
9761 *stream = curr_stream;
9765 if (err == IA_CSS_SUCCESS)
9767 /* working mode: enter into the seed list */
9768 if (my_css_save.mode == sh_css_mode_working) {
9769 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9770 if (!my_css_save.stream_seeds[i].stream) {
9771 IA_CSS_LOG("entered stream into loc=%d", i);
9772 my_css_save.stream_seeds[i].orig_stream = stream;
9773 my_css_save.stream_seeds[i].stream = curr_stream;
9774 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9775 my_css_save.stream_seeds[i].stream_config = *stream_config;
9776 for (j = 0; j < num_pipes; j++) {
9777 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9778 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9779 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9785 if (err == IA_CSS_SUCCESS) {
9786 err = ia_css_save_stream(curr_stream);
9789 ia_css_stream_destroy(curr_stream);
9792 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9794 IA_CSS_LEAVE("return_err=%d", err);
9800 ia_css_stream_destroy(struct ia_css_stream *stream)
9803 enum ia_css_err err = IA_CSS_SUCCESS;
9805 enum ia_css_err err1 = IA_CSS_SUCCESS;
9806 enum ia_css_err err2 = IA_CSS_SUCCESS;
9809 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9810 if (stream == NULL) {
9811 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9812 IA_CSS_LEAVE_ERR_PRIVATE(err);
9816 ia_css_stream_isp_parameters_uninit(stream);
9818 if ((stream->last_pipe != NULL) &&
9819 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num)) {
9820 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9821 for (i = 0; i < stream->num_pipes; i++) {
9822 struct ia_css_pipe *entry = stream->pipes[i];
9823 unsigned int sp_thread_id;
9824 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9826 assert(entry != NULL);
9827 if (entry != NULL) {
9828 /* get the SP thread id */
9829 if (ia_css_pipeline_get_sp_thread_id(
9830 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9831 return IA_CSS_ERR_INTERNAL_ERROR;
9832 /* get the target input terminal */
9833 sp_pipeline_input_terminal =
9834 &(sh_css_sp_group.pipe_io[sp_thread_id].input);
9836 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9837 ia_css_isys_stream_h isys_stream =
9838 &(sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
9839 if (stream->config.isys_config[i].valid && isys_stream->valid)
9840 ia_css_isys_stream_destroy(isys_stream);
9845 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
9847 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR ||
9848 stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
9849 stream->config.mode == IA_CSS_INPUT_MODE_PRBS) {
9851 for (i = 0; i < stream->num_pipes; i++) {
9852 struct ia_css_pipe *entry = stream->pipes[i];
9853 /* free any mipi frames that are remaining:
9854 * some test stream create-destroy cycles do not generate output frames
9855 * and the mipi buffer is not freed in the deque function
9858 free_mipi_frames(entry);
9861 stream_unregister_with_csi_rx(stream);
9864 for (i = 0; i < stream->num_pipes; i++) {
9865 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9866 assert(curr_pipe != NULL);
9867 ia_css_pipe_map_queue(curr_pipe, false);
9870 err = map_sp_threads(stream, false);
9871 if (err != IA_CSS_SUCCESS) {
9872 IA_CSS_LEAVE_ERR_PRIVATE(err);
9877 /* remove references from pipes to stream */
9878 for (i = 0; i < stream->num_pipes; i++) {
9879 struct ia_css_pipe *entry = stream->pipes[i];
9880 assert(entry != NULL);
9881 if (entry != NULL) {
9882 /* clear reference to stream */
9883 entry->stream = NULL;
9884 /* check internal copy pipe */
9885 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9886 entry->pipe_settings.preview.copy_pipe) {
9887 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9888 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9890 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9891 entry->pipe_settings.video.copy_pipe) {
9892 IA_CSS_LOG("clearing stream on internal video copy pipe");
9893 entry->pipe_settings.video.copy_pipe->stream = NULL;
9895 err = sh_css_pipe_unload_binaries(entry);
9898 /* free associated memory of stream struct */
9899 kfree(stream->pipes);
9900 stream->pipes = NULL;
9901 stream->num_pipes = 0;
9903 /* working mode: take out of the seed list */
9904 if (my_css_save.mode == sh_css_mode_working)
9905 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
9906 if (my_css_save.stream_seeds[i].stream == stream)
9908 IA_CSS_LOG("took out stream %d", i);
9909 my_css_save.stream_seeds[i].stream = NULL;
9913 err2 = ia_css_save_restore_remove_stream(stream);
9915 err1 = (err != IA_CSS_SUCCESS) ? err : err2;
9919 IA_CSS_LEAVE_ERR(err);
9921 IA_CSS_LEAVE_ERR(err1);
9932 ia_css_stream_get_info(const struct ia_css_stream *stream,
9933 struct ia_css_stream_info *stream_info)
9935 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9936 assert(stream != NULL);
9937 assert(stream_info != NULL);
9939 *stream_info = stream->info;
9940 return IA_CSS_SUCCESS;
9944 * Rebuild a stream, including allocating structs, setting configuration and
9945 * building the required pipes.
9946 * The data is taken from the css_save struct updated upon stream creation.
9947 * The stream handle is used to identify the correct entry in the css_save struct
9950 ia_css_stream_load(struct ia_css_stream *stream)
9954 enum ia_css_err err;
9955 assert(stream != NULL);
9956 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter, \n");
9957 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9958 if (my_css_save.stream_seeds[i].stream == stream) {
9960 for ( j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9961 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) {
9965 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9970 err = ia_css_stream_create(&(my_css_save.stream_seeds[i].stream_config),
9971 my_css_save.stream_seeds[i].num_pipes,
9972 my_css_save.stream_seeds[i].pipes,
9973 &(my_css_save.stream_seeds[i].stream));
9974 if (err != IA_CSS_SUCCESS) {
9975 ia_css_stream_destroy(stream);
9976 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9977 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9983 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit, \n");
9984 return IA_CSS_SUCCESS;
9986 /* TODO remove function - DEPRECATED */
9988 return IA_CSS_ERR_NOT_SUPPORTED;
9993 ia_css_stream_start(struct ia_css_stream *stream)
9995 enum ia_css_err err = IA_CSS_SUCCESS;
9996 IA_CSS_ENTER("stream = %p", stream);
9997 if ((stream == NULL) || (stream->last_pipe == NULL)) {
9998 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
9999 return IA_CSS_ERR_INVALID_ARGUMENTS;
10001 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
10003 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
10005 /* Create host side pipeline. */
10006 err = create_host_pipeline(stream);
10007 if (err != IA_CSS_SUCCESS) {
10008 IA_CSS_LEAVE_ERR(err);
10012 #if !defined(HAS_NO_INPUT_SYSTEM)
10013 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10014 if((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10015 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10016 stream_register_with_csi_rx(stream);
10020 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10021 /* Initialize mipi size checks */
10022 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10025 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10027 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10028 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = sh_css_get_mipi_sizes_for_check(port, idx);
10033 #if !defined(HAS_NO_INPUT_SYSTEM)
10034 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY) {
10035 err = sh_css_config_input_network(stream);
10036 if (err != IA_CSS_SUCCESS)
10039 #endif /* !HAS_NO_INPUT_SYSTEM */
10041 err = sh_css_pipe_start(stream);
10042 IA_CSS_LEAVE_ERR(err);
10047 ia_css_stream_stop(struct ia_css_stream *stream)
10049 enum ia_css_err err = IA_CSS_SUCCESS;
10051 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10052 assert(stream != NULL);
10053 assert(stream->last_pipe != NULL);
10054 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10055 stream->last_pipe->mode);
10057 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10058 /* De-initialize mipi size checks */
10059 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10062 unsigned int port = (unsigned int) (stream->config.source.port.port) ;
10064 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10065 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10070 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10073 err = sh_css_pipes_stop(stream);
10075 if (err != IA_CSS_SUCCESS)
10078 /* Ideally, unmapping should happen after pipeline_stop, but current
10079 * semantics do not allow that. */
10080 /* err = map_sp_threads(stream, false); */
10086 ia_css_stream_has_stopped(struct ia_css_stream *stream)
10089 assert(stream != NULL);
10092 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10094 stopped = sh_css_pipes_have_stopped(stream);
10102 * Destroy the stream and all the pipes related to it.
10103 * The stream handle is used to identify the correct entry in the css_save struct
10106 ia_css_stream_unload(struct ia_css_stream *stream)
10109 assert(stream != NULL);
10110 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter, \n");
10112 assert (stream != NULL);
10113 for(i=0;i<MAX_ACTIVE_STREAMS;i++)
10114 if (my_css_save.stream_seeds[i].stream == stream)
10117 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload(): unloading %d (%p)\n", i, my_css_save.stream_seeds[i].stream);
10118 ia_css_stream_destroy(stream);
10119 for(j=0;j<my_css_save.stream_seeds[i].num_pipes;j++)
10120 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10121 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);
10124 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit, \n");
10125 return IA_CSS_SUCCESS;
10130 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe, enum ia_css_pipe_id *pipe_id)
10132 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10134 *pipe_id = pipe->mode;
10136 *pipe_id = IA_CSS_PIPE_ID_COPY;
10138 return IA_CSS_SUCCESS;
10141 enum atomisp_input_format
10142 ia_css_stream_get_format(const struct ia_css_stream *stream)
10144 return stream->config.input_config.format;
10148 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream)
10150 return (stream->config.pixels_per_clock == 2);
10153 struct ia_css_binary *
10154 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream *stream)
10156 struct ia_css_pipe *pipe;
10158 assert(stream != NULL);
10160 pipe = stream->pipes[0];
10162 if (stream->num_pipes == 2) {
10163 assert(stream->pipes[1] != NULL);
10164 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10165 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10166 pipe = stream->pipes[1];
10169 return ia_css_pipe_get_shading_correction_binary(pipe);
10172 struct ia_css_binary *
10173 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream)
10176 struct ia_css_pipe *video_pipe = NULL;
10178 /* First we find the video pipe */
10179 for (i=0; i<stream->num_pipes; i++) {
10180 struct ia_css_pipe *pipe = stream->pipes[i];
10181 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10187 return &video_pipe->pipe_settings.video.video_binary;
10191 struct ia_css_binary *
10192 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream)
10194 struct ia_css_pipe *pipe;
10195 struct ia_css_binary *s3a_binary = NULL;
10197 assert(stream != NULL);
10199 pipe = stream->pipes[0];
10201 if (stream->num_pipes == 2) {
10202 assert(stream->pipes[1] != NULL);
10203 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10204 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10205 pipe = stream->pipes[1];
10208 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10215 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream, unsigned int output_padded_width)
10217 struct ia_css_pipe *pipe;
10219 assert(stream != NULL);
10221 pipe = stream->last_pipe;
10223 assert(pipe != NULL);
10225 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10226 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10227 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10229 return IA_CSS_SUCCESS;
10232 static struct ia_css_binary *
10233 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe)
10235 struct ia_css_binary *binary = NULL;
10237 assert(pipe != NULL);
10239 switch (pipe->config.mode) {
10240 case IA_CSS_PIPE_MODE_PREVIEW:
10241 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10243 case IA_CSS_PIPE_MODE_VIDEO:
10244 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10246 case IA_CSS_PIPE_MODE_CAPTURE:
10247 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10250 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10251 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10252 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10257 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10258 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10259 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10260 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10261 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10262 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10263 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10264 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10271 if (binary && binary->info->sp.enable.sc)
10277 static struct ia_css_binary *
10278 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe)
10280 struct ia_css_binary *binary = NULL;
10282 assert(pipe != NULL);
10284 switch (pipe->config.mode) {
10285 case IA_CSS_PIPE_MODE_PREVIEW:
10286 binary = (struct ia_css_binary*)&pipe->pipe_settings.preview.preview_binary;
10288 case IA_CSS_PIPE_MODE_VIDEO:
10289 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10291 case IA_CSS_PIPE_MODE_CAPTURE:
10292 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10294 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10295 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10296 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10301 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER)
10302 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10303 else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10304 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10305 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10306 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10307 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10308 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10317 if (binary && !binary->info->sp.enable.s3a)
10323 static struct ia_css_binary *
10324 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe)
10326 struct ia_css_binary *binary = NULL;
10328 assert(pipe != NULL);
10330 switch (pipe->config.mode) {
10331 case IA_CSS_PIPE_MODE_VIDEO:
10332 binary = (struct ia_css_binary*)&pipe->pipe_settings.video.video_binary;
10338 if (binary && !binary->info->sp.enable.dis)
10344 struct ia_css_pipeline *
10345 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe)
10347 assert(pipe != NULL);
10349 return (struct ia_css_pipeline*)&pipe->pipeline;
10353 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe)
10355 assert(pipe != NULL);
10357 /* KW was not sure this function was not returning a value
10358 that was out of range; so added an assert, and, for the
10359 case when asserts are not enabled, clip to the largest
10360 value; pipe_num is unsigned so the value cannot be too small
10362 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10364 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10365 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10367 return pipe->pipe_num;
10372 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe)
10374 assert(pipe != NULL);
10376 return (unsigned int)pipe->config.isp_pipe_version;
10379 #define SP_START_TIMEOUT_US 30000000
10382 ia_css_start_sp(void)
10384 unsigned long timeout;
10385 enum ia_css_err err = IA_CSS_SUCCESS;
10388 sh_css_sp_start_isp();
10390 /* waiting for the SP is completely started */
10391 timeout = SP_START_TIMEOUT_US;
10392 while((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout) {
10396 if (timeout == 0) {
10397 IA_CSS_ERROR("timeout during SP initialization");
10398 return IA_CSS_ERR_INTERNAL_ERROR;
10401 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10402 /* TODO: Fix this. */
10404 sh_css_init_host_sp_control_vars();
10406 /* buffers should be initialized only when sp is started */
10407 /* AM: At the moment it will be done only when there is no stream active. */
10409 sh_css_setup_queues();
10410 ia_css_bufq_dump_queue_info();
10413 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10414 ia_css_set_system_mode(IA_CSS_SYS_MODE_WORKING);
10417 IA_CSS_LEAVE_ERR(err);
10422 * Time to wait SP for termincate. Only condition when this can happen
10423 * is a fatal hw failure, but we must be able to detect this and emit
10424 * a proper error trace.
10426 #define SP_SHUTDOWN_TIMEOUT_US 200000
10429 ia_css_stop_sp(void)
10431 unsigned long timeout;
10432 enum ia_css_err err = IA_CSS_SUCCESS;
10434 IA_CSS_ENTER("void");
10436 if (!sh_css_sp_is_running()) {
10437 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10438 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10440 /* Return an error - stop SP should not have been called by driver */
10444 /* For now, stop whole SP */
10446 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10448 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate)) {
10449 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10450 ia_css_debug_dump_sp_sw_debug_info();
10451 ia_css_debug_dump_debug_info(NULL);
10454 sh_css_sp_set_sp_running(false);
10456 timeout = SP_SHUTDOWN_TIMEOUT_US;
10457 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout) {
10461 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10462 IA_CSS_WARNING("SP has not terminated (SW)");
10464 if (timeout == 0) {
10465 IA_CSS_WARNING("SP is not idle");
10466 ia_css_debug_dump_sp_sw_debug_info();
10468 timeout = SP_SHUTDOWN_TIMEOUT_US;
10469 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout) {
10473 if (timeout == 0) {
10474 IA_CSS_WARNING("ISP is not idle");
10475 ia_css_debug_dump_sp_sw_debug_info();
10478 sh_css_hmm_buffer_record_uninit();
10481 /* clear pending param sets from refcount */
10482 sh_css_param_clear_param_sets();
10484 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10485 /* clear pending param sets from refcount */
10486 sh_css_param_clear_param_sets();
10487 ia_css_set_system_mode(IA_CSS_SYS_MODE_INIT); /* System is initialized but not 'running' */
10491 IA_CSS_LEAVE_ERR(err);
10496 ia_css_update_continuous_frames(struct ia_css_stream *stream)
10498 struct ia_css_pipe *pipe;
10501 ia_css_debug_dtrace(
10502 IA_CSS_DEBUG_TRACE,
10503 "sh_css_update_continuous_frames() enter:\n");
10505 if (stream == NULL) {
10506 ia_css_debug_dtrace(
10507 IA_CSS_DEBUG_TRACE,
10508 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10509 return IA_CSS_ERR_INVALID_ARGUMENTS;
10512 pipe = stream->continuous_pipe;
10514 for (i = stream->config.init_num_cont_raw_buf;
10515 i < stream->config.target_num_cont_raw_buf; i++) {
10516 sh_css_update_host2sp_offline_frame(i,
10517 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10519 sh_css_update_host2sp_cont_num_raw_frames
10520 (stream->config.target_num_cont_raw_buf, true);
10521 ia_css_debug_dtrace(
10522 IA_CSS_DEBUG_TRACE,
10523 "sh_css_update_continuous_frames() leave: return_void\n");
10525 return IA_CSS_SUCCESS;
10528 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10530 unsigned int thread_id;
10531 enum ia_css_pipe_id pipe_id;
10532 unsigned int pipe_num;
10533 bool need_input_queue;
10536 assert(pipe != NULL);
10538 pipe_id = pipe->mode;
10539 pipe_num = pipe->pipe_num;
10541 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10543 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10544 need_input_queue = true;
10546 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10549 /* map required buffer queues to resources */
10550 /* TODO: to be improved */
10551 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10552 if (need_input_queue)
10553 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10554 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10555 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10556 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10557 #if defined SH_CSS_ENABLE_METADATA
10558 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10560 if (pipe->pipe_settings.preview.preview_binary.info &&
10561 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10562 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10563 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10566 if (need_input_queue)
10567 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10568 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10569 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10570 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10571 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10572 #if defined SH_CSS_ENABLE_METADATA
10573 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10575 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10576 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10577 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10578 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10579 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10583 } else if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
10584 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10585 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10586 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10587 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10588 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10590 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10591 if (need_input_queue)
10592 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10593 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10594 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10595 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10596 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10597 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10598 #if defined SH_CSS_ENABLE_METADATA
10599 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10601 if (pipe->pipe_settings.video.video_binary.info &&
10602 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10603 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10604 if (pipe->pipe_settings.video.video_binary.info &&
10605 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10607 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10608 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10609 if (need_input_queue)
10610 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10611 if (!pipe->stream->config.continuous)
10612 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10613 #if defined SH_CSS_ENABLE_METADATA
10614 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10616 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10617 if (need_input_queue)
10618 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10619 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10620 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10621 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10622 #if defined SH_CSS_ENABLE_METADATA
10623 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10625 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10627 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10628 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10629 if (pipe->enable_viewfinder[idx])
10630 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10632 if (need_input_queue)
10633 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10634 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10635 #if defined SH_CSS_ENABLE_METADATA
10636 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10642 #if CONFIG_ON_FRAME_ENQUEUE()
10643 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info *info, struct frame_data_wrapper *frame)
10645 frame->config_on_frame_enqueue.padded_width = 0;
10647 /* currently we support configuration on frame enqueue only on YUV formats */
10648 /* on other formats the padded_width is zeroed for no configuration override */
10649 switch (info->format) {
10650 case IA_CSS_FRAME_FORMAT_YUV420:
10651 case IA_CSS_FRAME_FORMAT_NV12:
10652 if (info->padded_width > info->res.width)
10654 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10656 else if ((info->padded_width < info->res.width) && (info->padded_width > 0))
10658 return IA_CSS_ERR_INVALID_ARGUMENTS;
10660 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10666 return IA_CSS_SUCCESS;
10671 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id)
10673 enum ia_css_err ret;
10677 /* Only continuous streams have a tagger to which we can send the
10678 * unlock message. */
10679 if (stream == NULL || !stream->config.continuous) {
10680 IA_CSS_ERROR("invalid stream pointer");
10681 return IA_CSS_ERR_INVALID_ARGUMENTS;
10684 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10685 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID) {
10686 IA_CSS_ERROR("invalid expsure ID: %d\n", exp_id);
10687 return IA_CSS_ERR_INVALID_ARGUMENTS;
10690 /* Send the event. Since we verified that the exp_id is valid,
10691 * we can safely assign it to an 8-bit argument here. */
10692 ret = ia_css_bufq_enqueue_psys_event(
10693 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10695 IA_CSS_LEAVE_ERR(ret);
10699 /* @brief Set the state (Enable or Disable) of the Extension stage in the
10703 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool enable)
10705 unsigned int thread_id;
10706 struct ia_css_pipeline_stage *stage;
10707 enum ia_css_err err = IA_CSS_SUCCESS;
10711 /* Parameter Check */
10712 if (pipe == NULL || pipe->stream == NULL) {
10713 IA_CSS_ERROR("Invalid Pipe.");
10714 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10715 } else if (!(pipe->config.acc_extension)) {
10716 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10717 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10718 } else if (!sh_css_sp_is_running()) {
10719 IA_CSS_ERROR("Leaving: queue unavailable.");
10720 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10722 /* Query the threadid and stage_num for the Extension firmware*/
10723 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10724 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10725 if (err == IA_CSS_SUCCESS) {
10726 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10727 err = ia_css_bufq_enqueue_psys_event(
10728 (uint8_t) IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10729 (uint8_t) thread_id,
10730 (uint8_t) stage->stage_num,
10732 if (err == IA_CSS_SUCCESS) {
10734 SH_CSS_QOS_STAGE_ENABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10736 SH_CSS_QOS_STAGE_DISABLE(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num);
10740 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10744 /* @brief Get the state (Enable or Disable) of the Extension stage in the
10748 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle, bool *enable)
10750 struct ia_css_pipeline_stage *stage;
10751 unsigned int thread_id;
10752 enum ia_css_err err = IA_CSS_SUCCESS;
10756 /* Parameter Check */
10757 if (pipe == NULL || pipe->stream == NULL) {
10758 IA_CSS_ERROR("Invalid Pipe.");
10759 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10760 } else if (!(pipe->config.acc_extension)) {
10761 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10762 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10763 } else if (!sh_css_sp_is_running()) {
10764 IA_CSS_ERROR("Leaving: queue unavailable.");
10765 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10767 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10768 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10769 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10771 if (err == IA_CSS_SUCCESS) {
10772 /* Get the Extension State */
10773 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]),stage->stage_num)) ? true : false;
10776 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10782 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe, uint32_t fw_handle,
10783 struct ia_css_isp_param_css_segments *css_seg, struct ia_css_isp_param_isp_segments *isp_seg)
10785 unsigned int HIVE_ADDR_sp_group;
10786 static struct sh_css_sp_group sp_group;
10787 static struct sh_css_sp_stage sp_stage;
10788 static struct sh_css_isp_stage isp_stage;
10789 const struct ia_css_fw_info *fw;
10790 unsigned int thread_id;
10791 struct ia_css_pipeline_stage *stage;
10792 enum ia_css_err err = IA_CSS_SUCCESS;
10794 enum ia_css_isp_memories mem;
10799 fw = &sh_css_sp_fw;
10801 /* Parameter Check */
10802 if (pipe == NULL || pipe->stream == NULL) {
10803 IA_CSS_ERROR("Invalid Pipe.");
10804 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10805 } else if (!(pipe->config.acc_extension)) {
10806 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10807 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10808 } else if (!sh_css_sp_is_running()) {
10809 IA_CSS_ERROR("Leaving: queue unavailable.");
10810 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10812 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10813 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10814 err = ia_css_pipeline_get_stage_from_fw(&(pipe->pipeline), fw_handle, &stage);
10815 if (err == IA_CSS_SUCCESS) {
10816 /* Get the Extension State */
10817 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&(sh_css_sp_group.pipe[thread_id]), stage->stage_num)) ? true : false;
10818 /* Update mapped arg only when extension stage is not enabled */
10820 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10821 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10823 stage_num = stage->stage_num;
10825 HIVE_ADDR_sp_group = fw->info.sp.group;
10826 sp_dmem_load(SP0_ID,
10827 (unsigned int)sp_address_of(sp_group),
10828 &sp_group, sizeof(struct sh_css_sp_group));
10829 mmgr_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10830 &sp_stage, sizeof(struct sh_css_sp_stage));
10832 mmgr_load(sp_stage.isp_stage_addr,
10833 &isp_stage, sizeof(struct sh_css_isp_stage));
10835 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10836 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10837 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10838 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10839 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10840 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10841 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10842 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10843 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10846 mmgr_store(sp_stage.isp_stage_addr,
10847 &isp_stage, sizeof(struct sh_css_isp_stage));
10851 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10855 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10856 static enum ia_css_err
10857 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10858 struct ia_css_pipe *pipes[],
10859 bool *do_crop_status)
10861 enum ia_css_err err = IA_CSS_SUCCESS;
10863 struct ia_css_pipe *curr_pipe;
10864 uint32_t pipe_mask = 0;
10866 if ((curr_stream == NULL) ||
10867 (curr_stream->num_pipes == 0) ||
10869 (do_crop_status == NULL)) {
10870 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10871 IA_CSS_LEAVE_ERR(err);
10875 for (i = 0; i < curr_stream->num_pipes; i++) {
10876 curr_pipe = pipes[i];
10877 pipe_mask |= (1 << curr_pipe->config.mode);
10881 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10882 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10883 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10884 curr_stream->config.continuous);
10885 return IA_CSS_SUCCESS;
10889 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe)
10891 bool status = false;
10893 if ((curr_pipe != NULL) && enabled) {
10894 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10895 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10896 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10903 static enum ia_css_err
10904 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10905 struct ia_css_resolution *effective_res)
10907 enum ia_css_err err = IA_CSS_SUCCESS;
10908 struct ia_css_resolution crop_res;
10909 struct ia_css_resolution *in_res = NULL;
10910 struct ia_css_resolution *out_res = NULL;
10911 bool use_bds_output_info = false;
10912 bool use_vf_pp_in_res = false;
10913 bool use_capt_pp_in_res = false;
10915 if ((curr_pipe == NULL) ||
10916 (effective_res == NULL)) {
10917 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10918 IA_CSS_LEAVE_ERR(err);
10922 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10923 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10924 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE)) {
10925 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10926 IA_CSS_LEAVE_ERR(err);
10930 use_bds_output_info =
10931 ((curr_pipe->bds_output_info.res.width != 0) &&
10932 (curr_pipe->bds_output_info.res.height != 0));
10935 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10936 (curr_pipe->config.vf_pp_in_res.height != 0));
10938 use_capt_pp_in_res =
10939 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10940 (curr_pipe->config.capt_pp_in_res.height != 0));
10942 in_res = &curr_pipe->stream->config.input_config.effective_res;
10943 out_res = &curr_pipe->output_info[0].res;
10945 switch (curr_pipe->config.mode) {
10946 case IA_CSS_PIPE_MODE_PREVIEW:
10947 if (use_bds_output_info)
10948 out_res = &curr_pipe->bds_output_info.res;
10949 else if (use_vf_pp_in_res)
10950 out_res = &curr_pipe->config.vf_pp_in_res;
10952 case IA_CSS_PIPE_MODE_VIDEO:
10953 if (use_bds_output_info)
10954 out_res = &curr_pipe->bds_output_info.res;
10956 case IA_CSS_PIPE_MODE_CAPTURE:
10957 if (use_capt_pp_in_res)
10958 out_res = &curr_pipe->config.capt_pp_in_res;
10960 case IA_CSS_PIPE_MODE_ACC:
10961 case IA_CSS_PIPE_MODE_COPY:
10962 case IA_CSS_PIPE_MODE_YUVPP:
10964 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10965 curr_pipe->config.mode);
10970 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10971 if (err == IA_CSS_SUCCESS) {
10972 *effective_res = crop_res;
10974 /* in case of error fallback to default
10975 * effective resolution from driver. */
10976 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10984 sh_css_hmm_buffer_record_init(void)
10989 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10990 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
10992 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
10993 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10994 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
11001 sh_css_hmm_buffer_record_uninit(void)
11004 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11007 buffer_record = &hmm_buffer_record[0];
11008 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11009 if (buffer_record->in_use) {
11010 if (buffer_record->h_vbuf != NULL)
11011 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11012 sh_css_hmm_buffer_record_reset(buffer_record);
11014 if (ia_css_is_system_mode_suspend_or_resume() == false) { /* skip in suspend/resume flow */
11015 buffer_record = &hmm_buffer_record[0];
11016 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11017 if (buffer_record->in_use) {
11018 if (buffer_record->h_vbuf != NULL)
11019 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11020 sh_css_hmm_buffer_record_reset(buffer_record);
11032 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record)
11034 assert(buffer_record != NULL);
11035 buffer_record->in_use = false;
11036 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11037 buffer_record->h_vbuf = NULL;
11038 buffer_record->kernel_ptr = 0;
11041 static struct sh_css_hmm_buffer_record
11042 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11043 enum ia_css_buffer_type type,
11044 hrt_address kernel_ptr)
11047 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11048 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11050 assert(h_vbuf != NULL);
11051 assert((type > IA_CSS_BUFFER_TYPE_INVALID) && (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11052 assert(kernel_ptr != 0);
11054 buffer_record = &hmm_buffer_record[0];
11055 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11056 if (!buffer_record->in_use) {
11057 buffer_record->in_use = true;
11058 buffer_record->type = type;
11059 buffer_record->h_vbuf = h_vbuf;
11060 buffer_record->kernel_ptr = kernel_ptr;
11061 out_buffer_record = buffer_record;
11067 return out_buffer_record;
11070 static struct sh_css_hmm_buffer_record
11071 *sh_css_hmm_buffer_record_validate(hrt_vaddress ddr_buffer_addr,
11072 enum ia_css_buffer_type type)
11075 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11076 bool found_record = false;
11078 buffer_record = &hmm_buffer_record[0];
11079 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11080 if ((buffer_record->in_use) &&
11081 (buffer_record->type == type) &&
11082 (buffer_record->h_vbuf != NULL) &&
11083 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11084 found_record = true;
11091 return buffer_record;