1 // SPDX-License-Identifier: GPL-2.0
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2015, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 #include <linux/slab.h>
19 #include <linux/vmalloc.h>
24 #include "sh_css_hrt.h" /* only for file 2 MIPI */
25 #include "ia_css_buffer.h"
26 #include "ia_css_binary.h"
27 #include "sh_css_internal.h"
28 #include "sh_css_mipi.h"
29 #include "sh_css_sp.h" /* sh_css_sp_group */
30 #if !defined(HAS_NO_INPUT_SYSTEM)
31 #include "ia_css_isys.h"
33 #include "ia_css_frame.h"
34 #include "sh_css_defs.h"
35 #include "sh_css_firmware.h"
36 #include "sh_css_params.h"
37 #include "sh_css_params_internal.h"
38 #include "sh_css_param_shading.h"
39 #include "ia_css_refcount.h"
40 #include "ia_css_rmgr.h"
41 #include "ia_css_debug.h"
42 #include "ia_css_debug_pipe.h"
43 #include "ia_css_device_access.h"
44 #include "device_access.h"
45 #include "sh_css_legacy.h"
46 #include "ia_css_pipeline.h"
47 #include "ia_css_stream.h"
48 #include "sh_css_stream_format.h"
49 #include "ia_css_pipe.h"
50 #include "ia_css_util.h"
51 #include "ia_css_pipe_util.h"
52 #include "ia_css_pipe_binarydesc.h"
53 #include "ia_css_pipe_stagedesc.h"
54 #ifdef USE_INPUT_SYSTEM_VERSION_2
55 #include "ia_css_isys.h"
59 #include "assert_support.h"
60 #include "math_support.h"
61 #include "sw_event_global.h" /* Event IDs.*/
62 #if !defined(HAS_NO_INPUT_FORMATTER)
63 #include "ia_css_ifmtr.h"
65 #if !defined(HAS_NO_INPUT_SYSTEM)
66 #include "input_system.h"
68 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
69 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
70 #include "gdc_device.h" /* HRT_GDC_N */
71 #include "dma.h" /* dma_set_max_burst_size() */
72 #include "irq.h" /* virq */
73 #include "sp.h" /* cnd_sp_irq_enable() */
74 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
75 #include "gp_device.h" /* gp_device_reg_store() */
76 #define __INLINE_GPIO__
78 #include "timed_ctrl.h"
79 #include "platform_support.h" /* hrt_sleep(), inline */
80 #include "ia_css_inputfifo.h"
81 #define WITH_PC_MONITORING 0
83 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
85 #if WITH_PC_MONITORING
86 #define MULTIPLE_SAMPLES 1
87 #define NOF_SAMPLES 60
88 #include "linux/kthread.h"
89 #include "linux/sched.h"
90 #include "linux/delay.h"
91 #include "sh_css_metrics.h"
92 static int thread_alive;
93 #endif /* WITH_PC_MONITORING */
95 #include "ia_css_spctrl.h"
96 #include "ia_css_version_data.h"
97 #include "sh_css_struct.h"
98 #include "ia_css_bufq.h"
99 #include "ia_css_timer.h" /* clock_value_t */
101 #include "isp/modes/interface/input_buf.isp.h"
103 /* Name of the sp program: should not be built-in */
104 #define SP_PROG_NAME "sp"
105 /* Size of Refcount List */
106 #define REFCOUNT_SIZE 1000
108 /* for JPEG, we don't know the length of the image upfront,
109 * but since we support sensor upto 16MP, we take this as
112 #define JPEG_BYTES (16 * 1024 * 1024)
114 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
115 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
117 struct sh_css my_css;
119 int (*sh_css_printf)(const char *fmt, va_list args) = NULL;
121 /* modes of work: stream_create and stream_destroy will update the save/restore data
122 only when in working mode, not suspend/resume
124 enum ia_sh_css_modes {
125 sh_css_mode_none = 0,
131 /* a stream seed, to save and restore the stream data.
132 the stream seed contains all the data required to "grow" the seed again after it was closed.
134 struct sh_css_stream_seed {
136 **orig_stream; /* pointer to restore the original handle */
137 struct ia_css_stream *stream; /* handle, used as ID too.*/
138 struct ia_css_stream_config stream_config; /* stream config struct */
140 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */
142 **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */
143 struct ia_css_pipe_config
144 pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */
147 #define MAX_ACTIVE_STREAMS 5
148 /* A global struct for save/restore to hold all the data that should sustain power-down:
149 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
152 enum ia_sh_css_modes mode;
153 u32 mmu_base; /* the last mmu_base */
154 enum ia_css_irq_type irq_type;
155 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
156 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
157 struct ia_css_env driver_env; /* driver-supplied env copy */
160 static bool my_css_save_initialized; /* if my_css_save was initialized */
161 static struct sh_css_save my_css_save;
163 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
164 this array is temporary and will be replaced by resource manager*/
165 /* Taking the biggest Size for number of Elements */
166 #define MAX_HMM_BUFFER_NUM \
167 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
169 struct sh_css_hmm_buffer_record {
171 enum ia_css_buffer_type type;
172 struct ia_css_rmgr_vbuf_handle *h_vbuf;
173 hrt_address kernel_ptr;
176 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
178 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN)
180 static bool fw_explicitly_loaded;
187 allocate_delay_frames(struct ia_css_pipe *pipe);
190 sh_css_pipe_start(struct ia_css_stream *stream);
194 * @brief Stop all "ia_css_pipe" instances in the target
195 * "ia_css_stream" instance.
197 * @param[in] stream Point to the target "ia_css_stream" instance.
200 * - 0, if the "stop" requests have been successfully sent out.
201 * - CSS error code, otherwise.
205 * This API sends the "stop" requests to the "ia_css_pipe"
206 * instances in the same "ia_css_stream" instance. It will
207 * return without waiting for all "ia_css_pipe" instatnces
211 sh_css_pipes_stop(struct ia_css_stream *stream);
214 * @brief Check if all "ia_css_pipe" instances in the target
215 * "ia_css_stream" instance have stopped.
217 * @param[in] stream Point to the target "ia_css_stream" instance.
220 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
221 * instance have ben stopped.
222 * - false, otherwise.
226 sh_css_pipes_have_stopped(struct ia_css_stream *stream);
230 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
231 enum ia_css_frame_format format);
235 check_pipe_resolutions(const struct ia_css_pipe *pipe);
238 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
239 struct ia_css_fw_info *firmware);
242 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
243 struct ia_css_fw_info *firmware);
245 ia_css_reset_defaults(struct sh_css *css);
248 sh_css_init_host_sp_control_vars(void);
250 static int set_num_primary_stages(unsigned int *num,
251 enum ia_css_pipe_version version);
254 need_capture_pp(const struct ia_css_pipe *pipe);
257 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
259 static int ia_css_pipe_create_cas_scaler_desc_single_output(
260 struct ia_css_frame_info *cas_scaler_in_info,
261 struct ia_css_frame_info *cas_scaler_out_info,
262 struct ia_css_frame_info *cas_scaler_vf_info,
263 struct ia_css_cas_binary_descr *descr);
265 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
269 need_downscaling(const struct ia_css_resolution in_res,
270 const struct ia_css_resolution out_res);
272 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
275 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
278 int sh_css_pipe_get_viewfinder_frame_info(
279 struct ia_css_pipe *pipe,
280 struct ia_css_frame_info *info,
284 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
285 struct ia_css_frame_info *info,
289 capture_start(struct ia_css_pipe *pipe);
292 video_start(struct ia_css_pipe *pipe);
295 preview_start(struct ia_css_pipe *pipe);
298 yuvpp_start(struct ia_css_pipe *pipe);
300 static bool copy_on_sp(struct ia_css_pipe *pipe);
303 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
304 struct ia_css_frame *vf_frame, unsigned int idx);
307 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
308 struct ia_css_frame *frame, enum ia_css_frame_format format);
311 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
312 struct ia_css_frame *out_frame, unsigned int idx);
315 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
319 alloc_continuous_frames(
320 struct ia_css_pipe *pipe, bool init_time);
323 pipe_global_init(void);
326 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
327 unsigned int *pipe_number);
330 pipe_release_pipe_num(unsigned int pipe_num);
333 create_host_pipeline_structure(struct ia_css_stream *stream);
336 create_host_pipeline(struct ia_css_stream *stream);
339 create_host_preview_pipeline(struct ia_css_pipe *pipe);
342 create_host_video_pipeline(struct ia_css_pipe *pipe);
345 create_host_copy_pipeline(struct ia_css_pipe *pipe,
346 unsigned int max_input_width,
347 struct ia_css_frame *out_frame);
350 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
353 create_host_capture_pipeline(struct ia_css_pipe *pipe);
356 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
359 create_host_acc_pipeline(struct ia_css_pipe *pipe);
362 sh_css_get_sw_interrupt_value(unsigned int irq);
364 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(
365 const struct ia_css_pipe *pipe);
367 static struct ia_css_binary *
368 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
370 static struct ia_css_binary *
371 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
374 sh_css_hmm_buffer_record_init(void);
377 sh_css_hmm_buffer_record_uninit(void);
380 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
382 static struct sh_css_hmm_buffer_record
383 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
384 enum ia_css_buffer_type type,
385 hrt_address kernel_ptr);
387 static struct sh_css_hmm_buffer_record
388 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
389 enum ia_css_buffer_type type);
392 ia_css_get_acc_configs(
393 struct ia_css_pipe *pipe,
394 struct ia_css_isp_config *config);
396 #if CONFIG_ON_FRAME_ENQUEUE()
397 static int set_config_on_frame_enqueue(struct ia_css_frame_info
398 *info, struct frame_data_wrapper *frame);
401 #ifdef USE_INPUT_SYSTEM_VERSION_2401
402 static unsigned int get_crop_lines_for_bayer_order(const struct
403 ia_css_stream_config *config);
404 static unsigned int get_crop_columns_for_bayer_order(const struct
405 ia_css_stream_config *config);
406 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
407 unsigned int *extra_row, unsigned int *extra_column);
409 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
410 struct ia_css_pipe *pipes[],
411 bool *do_crop_status);
414 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe);
417 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
418 struct ia_css_resolution *effective_res);
422 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
426 IA_CSS_ERROR("NULL input parameter");
430 if (pipe->shading_table)
431 ia_css_shading_table_free(pipe->shading_table);
432 pipe->shading_table = NULL;
435 static enum ia_css_frame_format yuv420_copy_formats[] = {
436 IA_CSS_FRAME_FORMAT_NV12,
437 IA_CSS_FRAME_FORMAT_NV21,
438 IA_CSS_FRAME_FORMAT_YV12,
439 IA_CSS_FRAME_FORMAT_YUV420,
440 IA_CSS_FRAME_FORMAT_YUV420_16,
441 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
442 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
445 static enum ia_css_frame_format yuv422_copy_formats[] = {
446 IA_CSS_FRAME_FORMAT_NV12,
447 IA_CSS_FRAME_FORMAT_NV16,
448 IA_CSS_FRAME_FORMAT_NV21,
449 IA_CSS_FRAME_FORMAT_NV61,
450 IA_CSS_FRAME_FORMAT_YV12,
451 IA_CSS_FRAME_FORMAT_YV16,
452 IA_CSS_FRAME_FORMAT_YUV420,
453 IA_CSS_FRAME_FORMAT_YUV420_16,
454 IA_CSS_FRAME_FORMAT_YUV422,
455 IA_CSS_FRAME_FORMAT_YUV422_16,
456 IA_CSS_FRAME_FORMAT_UYVY,
457 IA_CSS_FRAME_FORMAT_YUYV
460 /* Verify whether the selected output format is can be produced
461 * by the copy binary given the stream format.
464 verify_copy_out_frame_format(struct ia_css_pipe *pipe) {
465 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
466 unsigned int i, found = 0;
469 assert(pipe->stream);
471 switch (pipe->stream->config.input_config.format)
473 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
474 case ATOMISP_INPUT_FORMAT_YUV420_8:
475 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
476 found = (out_fmt == yuv420_copy_formats[i]);
478 case ATOMISP_INPUT_FORMAT_YUV420_10:
479 case ATOMISP_INPUT_FORMAT_YUV420_16:
480 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
482 case ATOMISP_INPUT_FORMAT_YUV422_8:
483 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
484 found = (out_fmt == yuv422_copy_formats[i]);
486 case ATOMISP_INPUT_FORMAT_YUV422_10:
487 case ATOMISP_INPUT_FORMAT_YUV422_16:
488 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
489 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
491 case ATOMISP_INPUT_FORMAT_RGB_444:
492 case ATOMISP_INPUT_FORMAT_RGB_555:
493 case ATOMISP_INPUT_FORMAT_RGB_565:
494 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
495 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
497 case ATOMISP_INPUT_FORMAT_RGB_666:
498 case ATOMISP_INPUT_FORMAT_RGB_888:
499 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
500 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
502 case ATOMISP_INPUT_FORMAT_RAW_6:
503 case ATOMISP_INPUT_FORMAT_RAW_7:
504 case ATOMISP_INPUT_FORMAT_RAW_8:
505 case ATOMISP_INPUT_FORMAT_RAW_10:
506 case ATOMISP_INPUT_FORMAT_RAW_12:
507 case ATOMISP_INPUT_FORMAT_RAW_14:
508 case ATOMISP_INPUT_FORMAT_RAW_16:
509 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
510 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
512 case ATOMISP_INPUT_FORMAT_BINARY_8:
513 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
524 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
529 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
530 stream->config.pixels_per_clock == 2);
535 #define GP_ISEL_TPG_MODE 0x90058
537 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
539 sh_css_config_input_network(struct ia_css_stream *stream) {
540 unsigned int fmt_type;
541 struct ia_css_pipe *pipe = stream->last_pipe;
542 struct ia_css_binary *binary = NULL;
548 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
549 "sh_css_config_input_network() enter:\n");
551 if (pipe->pipeline.stages)
552 binary = pipe->pipeline.stages->binary;
554 err = ia_css_isys_convert_stream_format_to_mipi_format(
555 stream->config.input_config.format,
556 stream->csi_rx_config.comp,
560 sh_css_sp_program_input_circuit(fmt_type,
561 stream->config.channel_id,
562 stream->config.mode);
564 if ((binary && (binary->online || stream->config.continuous)) ||
565 pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
567 err = ia_css_ifmtr_configure(&stream->config,
573 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
574 stream->config.mode == IA_CSS_INPUT_MODE_PRBS)
576 unsigned int hblank_cycles = 100,
581 width = (stream->config.input_config.input_res.width) / (1 +
582 (stream->config.pixels_per_clock == 2));
583 height = stream->config.input_config.input_res.height;
584 vblank_cycles = vblank_lines * (width + hblank_cycles);
585 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
588 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
589 /* TODO: move define to proper file in tools */
590 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
594 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
595 "sh_css_config_input_network() leave:\n");
598 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
599 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
600 enum atomisp_input_format format,
601 unsigned int pixels_per_line)
606 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
608 * The frame format layout is shown below.
610 * Line 0: UYY0 UYY0 ... UYY0
611 * Line 1: VYY0 VYY0 ... VYY0
612 * Line 2: UYY0 UYY0 ... UYY0
613 * Line 3: VYY0 VYY0 ... VYY0
615 * Line (n-2): UYY0 UYY0 ... UYY0
616 * Line (n-1): VYY0 VYY0 ... VYY0
618 * In this frame format, the even-line is
619 * as wide as the odd-line.
620 * The 0 is introduced by the input system
623 rval = pixels_per_line * 2;
625 case ATOMISP_INPUT_FORMAT_YUV420_8:
626 case ATOMISP_INPUT_FORMAT_YUV420_10:
627 case ATOMISP_INPUT_FORMAT_YUV420_16:
629 * The frame format layout is shown below.
631 * Line 0: YYYY YYYY ... YYYY
632 * Line 1: UYVY UYVY ... UYVY UYVY
633 * Line 2: YYYY YYYY ... YYYY
634 * Line 3: UYVY UYVY ... UYVY UYVY
636 * Line (n-2): YYYY YYYY ... YYYY
637 * Line (n-1): UYVY UYVY ... UYVY UYVY
639 * In this frame format, the odd-line is twice
640 * wider than the even-line.
642 rval = pixels_per_line * 2;
644 case ATOMISP_INPUT_FORMAT_YUV422_8:
645 case ATOMISP_INPUT_FORMAT_YUV422_10:
646 case ATOMISP_INPUT_FORMAT_YUV422_16:
648 * The frame format layout is shown below.
650 * Line 0: UYVY UYVY ... UYVY
651 * Line 1: UYVY UYVY ... UYVY
652 * Line 2: UYVY UYVY ... UYVY
653 * Line 3: UYVY UYVY ... UYVY
655 * Line (n-2): UYVY UYVY ... UYVY
656 * Line (n-1): UYVY UYVY ... UYVY
658 * In this frame format, the even-line is
659 * as wide as the odd-line.
661 rval = pixels_per_line * 2;
663 case ATOMISP_INPUT_FORMAT_RGB_444:
664 case ATOMISP_INPUT_FORMAT_RGB_555:
665 case ATOMISP_INPUT_FORMAT_RGB_565:
666 case ATOMISP_INPUT_FORMAT_RGB_666:
667 case ATOMISP_INPUT_FORMAT_RGB_888:
669 * The frame format layout is shown below.
671 * Line 0: ABGR ABGR ... ABGR
672 * Line 1: ABGR ABGR ... ABGR
673 * Line 2: ABGR ABGR ... ABGR
674 * Line 3: ABGR ABGR ... ABGR
676 * Line (n-2): ABGR ABGR ... ABGR
677 * Line (n-1): ABGR ABGR ... ABGR
679 * In this frame format, the even-line is
680 * as wide as the odd-line.
682 rval = pixels_per_line * 4;
684 case ATOMISP_INPUT_FORMAT_RAW_6:
685 case ATOMISP_INPUT_FORMAT_RAW_7:
686 case ATOMISP_INPUT_FORMAT_RAW_8:
687 case ATOMISP_INPUT_FORMAT_RAW_10:
688 case ATOMISP_INPUT_FORMAT_RAW_12:
689 case ATOMISP_INPUT_FORMAT_RAW_14:
690 case ATOMISP_INPUT_FORMAT_RAW_16:
691 case ATOMISP_INPUT_FORMAT_BINARY_8:
692 case ATOMISP_INPUT_FORMAT_USER_DEF1:
693 case ATOMISP_INPUT_FORMAT_USER_DEF2:
694 case ATOMISP_INPUT_FORMAT_USER_DEF3:
695 case ATOMISP_INPUT_FORMAT_USER_DEF4:
696 case ATOMISP_INPUT_FORMAT_USER_DEF5:
697 case ATOMISP_INPUT_FORMAT_USER_DEF6:
698 case ATOMISP_INPUT_FORMAT_USER_DEF7:
699 case ATOMISP_INPUT_FORMAT_USER_DEF8:
701 * The frame format layout is shown below.
703 * Line 0: Pixel Pixel ... Pixel
704 * Line 1: Pixel Pixel ... Pixel
705 * Line 2: Pixel Pixel ... Pixel
706 * Line 3: Pixel Pixel ... Pixel
708 * Line (n-2): Pixel Pixel ... Pixel
709 * Line (n-1): Pixel Pixel ... Pixel
711 * In this frame format, the even-line is
712 * as wide as the odd-line.
714 rval = pixels_per_line;
724 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
725 struct ia_css_stream_config *stream_cfg,
726 ia_css_isys_descr_t *isys_stream_descr)
731 switch (stream_cfg->mode) {
732 case IA_CSS_INPUT_MODE_TPG:
734 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
735 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
736 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
737 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
738 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
739 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
743 case IA_CSS_INPUT_MODE_PRBS:
745 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
746 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
747 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
748 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
749 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
750 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
754 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
756 if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
757 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
758 } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
759 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
760 } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
761 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
773 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
774 struct ia_css_stream_config *stream_cfg,
775 ia_css_isys_descr_t *isys_stream_descr)
780 switch (stream_cfg->mode) {
781 case IA_CSS_INPUT_MODE_TPG:
783 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
786 case IA_CSS_INPUT_MODE_PRBS:
788 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
791 case IA_CSS_INPUT_MODE_SENSOR:
792 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
794 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
805 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
806 struct ia_css_stream_config *stream_cfg,
807 ia_css_isys_descr_t *isys_stream_descr,
813 switch (stream_cfg->mode) {
814 case IA_CSS_INPUT_MODE_TPG:
815 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
816 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
817 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
818 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
819 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
820 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
827 * - Make "color_cfg" as part of "ia_css_tpg_config".
829 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
830 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
831 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
832 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
833 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
834 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
836 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask =
837 stream_cfg->source.tpg.x_mask;
838 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask =
839 stream_cfg->source.tpg.y_mask;
840 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask =
841 stream_cfg->source.tpg.xy_mask;
843 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta =
844 stream_cfg->source.tpg.x_delta;
845 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta =
846 stream_cfg->source.tpg.y_delta;
850 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
852 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
853 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
854 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock =
855 stream_cfg->pixels_per_clock;
856 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
857 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line =
858 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
859 isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame =
860 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
863 case IA_CSS_INPUT_MODE_PRBS:
865 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
866 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
870 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
872 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
873 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
874 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock =
875 stream_cfg->pixels_per_clock;
876 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
877 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line =
878 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
879 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame =
880 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
883 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: {
885 unsigned int fmt_type;
887 err = ia_css_isys_convert_stream_format_to_mipi_format(
888 stream_cfg->isys_config[isys_stream_idx].format,
894 isys_stream_descr->csi_port_attr.active_lanes =
895 stream_cfg->source.port.num_lanes;
896 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
897 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
898 #ifdef USE_INPUT_SYSTEM_VERSION_2401
899 isys_stream_descr->online = stream_cfg->online;
901 err |= ia_css_isys_convert_compressed_format(
902 &stream_cfg->source.port.compression,
908 isys_stream_descr->metadata.enable = false;
909 if (stream_cfg->metadata_config.resolution.height > 0) {
910 err = ia_css_isys_convert_stream_format_to_mipi_format(
911 stream_cfg->metadata_config.data_type,
916 isys_stream_descr->metadata.fmt_type = fmt_type;
917 isys_stream_descr->metadata.bits_per_pixel =
918 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
919 isys_stream_descr->metadata.pixels_per_line =
920 stream_cfg->metadata_config.resolution.width;
921 isys_stream_descr->metadata.lines_per_frame =
922 stream_cfg->metadata_config.resolution.height;
923 #ifdef USE_INPUT_SYSTEM_VERSION_2401
924 /* For new input system, number of str2mmio requests must be even.
925 * So we round up number of metadata lines to be even. */
926 if (isys_stream_descr->metadata.lines_per_frame > 0)
927 isys_stream_descr->metadata.lines_per_frame +=
928 (isys_stream_descr->metadata.lines_per_frame & 1);
930 isys_stream_descr->metadata.align_req_in_bytes =
931 ia_css_csi2_calculate_input_system_alignment(
932 stream_cfg->metadata_config.data_type);
933 isys_stream_descr->metadata.enable = true;
946 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
947 struct ia_css_stream_config *stream_cfg,
948 ia_css_isys_descr_t *isys_stream_descr,
951 unsigned int bits_per_subpixel;
952 unsigned int max_subpixels_per_line;
953 unsigned int lines_per_frame;
954 unsigned int align_req_in_bytes;
955 enum atomisp_input_format fmt_type;
957 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
958 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
959 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
960 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
961 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
962 UNCOMPRESSED_BITS_PER_PIXEL_10) {
963 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
964 } else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
965 UNCOMPRESSED_BITS_PER_PIXEL_12) {
966 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
972 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
973 if (bits_per_subpixel == 0)
976 max_subpixels_per_line =
977 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
978 stream_cfg->isys_config[isys_stream_idx].input_res.width);
979 if (max_subpixels_per_line == 0)
982 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
983 if (lines_per_frame == 0)
986 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
988 /* HW needs subpixel info for their settings */
989 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
990 isys_stream_descr->input_port_resolution.pixels_per_line =
991 max_subpixels_per_line;
992 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
993 isys_stream_descr->input_port_resolution.align_req_in_bytes =
999 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
1000 struct ia_css_stream_config *stream_cfg,
1002 ia_css_isys_descr_t *isys_stream_descr,
1003 int isys_stream_idx)
1007 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1008 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
1009 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg,
1011 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg,
1013 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg,
1014 isys_stream_descr, isys_stream_idx);
1015 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
1016 stream_cfg, isys_stream_descr, isys_stream_idx);
1018 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
1019 isys_stream_descr->linked_isys_stream_id = (int8_t)
1020 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
1022 * Early polling is required for timestamp accuracy in certain case.
1023 * The ISYS HW polling is started on
1024 * ia_css_isys_stream_capture_indication() instead of
1025 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
1026 * capture takes longer than getting an ISYS frame
1028 * Only 2401 relevant ??
1030 #if 0 // FIXME: NOT USED on Yocto Aero
1031 isys_stream_descr->polling_mode
1032 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1033 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1034 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1035 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1041 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1042 struct ia_css_binary *binary,
1043 ia_css_isys_descr_t *isys_stream_descr)
1048 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1049 isys_stream_descr->output_port_attr.max_isp_input_width =
1050 binary->info->sp.input.max_width;
1056 sh_css_config_input_network(struct ia_css_stream *stream) {
1058 ia_css_isys_descr_t isys_stream_descr;
1059 unsigned int sp_thread_id;
1060 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1061 struct ia_css_pipe *pipe = NULL;
1062 struct ia_css_binary *binary = NULL;
1065 bool early_polling = false;
1068 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1069 "sh_css_config_input_network() enter 0x%p:\n", stream);
1071 if (stream->config.continuous == true)
1073 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1074 pipe = stream->last_pipe;
1075 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1076 pipe = stream->last_pipe;
1077 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1078 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1079 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1080 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1084 pipe = stream->last_pipe;
1085 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1087 * We need to poll the ISYS HW in capture_indication itself
1088 * for "non-continuous" capture usecase for getting accurate
1089 * isys frame capture timestamps.
1090 * This is because the capturepipe propcessing takes longer
1091 * to execute than the input system frame capture.
1094 early_polling = true;
1102 if (pipe->pipeline.stages)
1103 if (pipe->pipeline.stages->binary)
1104 binary = pipe->pipeline.stages->binary;
1108 /* this was being done in ifmtr in 2400.
1109 * online and cont bypass the init_in_frameinfo_memory_defaults
1110 * so need to do it here
1112 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1115 /* get the SP thread id */
1116 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1119 /* get the target input terminal */
1120 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
1122 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1124 /* initialization */
1125 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1126 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1127 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1129 if (!stream->config.isys_config[i].valid)
1132 /* translate the stream configuration to the Input System (2401) configuration */
1133 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1136 &(isys_stream_descr), i);
1138 if (stream->config.online) {
1139 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1141 &(isys_stream_descr));
1147 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1149 /* create the virtual Input System (2401) */
1150 rc = ia_css_isys_stream_create(
1151 &(isys_stream_descr),
1152 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1157 /* calculate the configuration of the virtual Input System (2401) */
1158 rc = ia_css_isys_stream_calculate_cfg(
1159 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1160 &(isys_stream_descr),
1161 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]);
1163 ia_css_isys_stream_destroy(
1164 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
1169 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1170 "sh_css_config_input_network() leave:\n");
1175 static inline struct ia_css_pipe *stream_get_last_pipe(
1176 struct ia_css_stream *stream)
1178 struct ia_css_pipe *last_pipe = NULL;
1181 last_pipe = stream->last_pipe;
1186 static inline struct ia_css_pipe *stream_get_copy_pipe(
1187 struct ia_css_stream *stream)
1189 struct ia_css_pipe *copy_pipe = NULL;
1190 struct ia_css_pipe *last_pipe = NULL;
1191 enum ia_css_pipe_id pipe_id;
1193 last_pipe = stream_get_last_pipe(stream);
1197 (stream->config.continuous)) {
1198 pipe_id = last_pipe->mode;
1200 case IA_CSS_PIPE_ID_PREVIEW:
1201 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1203 case IA_CSS_PIPE_ID_VIDEO:
1204 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1215 static inline struct ia_css_pipe *stream_get_target_pipe(
1216 struct ia_css_stream *stream)
1218 struct ia_css_pipe *target_pipe;
1220 /* get the pipe that consumes the stream */
1221 if (stream->config.continuous) {
1222 target_pipe = stream_get_copy_pipe(stream);
1224 target_pipe = stream_get_last_pipe(stream);
1230 static int stream_csi_rx_helper(
1231 struct ia_css_stream *stream,
1232 int (*func)(enum mipi_port_id, uint32_t))
1234 int retval = -EINVAL;
1235 u32 sp_thread_id, stream_id;
1237 struct ia_css_pipe *target_pipe = NULL;
1239 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1242 target_pipe = stream_get_target_pipe(stream);
1247 rc = ia_css_pipeline_get_sp_thread_id(
1248 ia_css_pipe_get_pipe_num(target_pipe),
1254 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1257 if (stream->config.isys_config[stream_id].valid) {
1258 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1260 retval = func(stream->config.source.port.port, isys_stream_id);
1263 } while ((retval == 0) &&
1264 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1270 static inline int stream_register_with_csi_rx(
1271 struct ia_css_stream *stream)
1273 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1276 static inline int stream_unregister_with_csi_rx(
1277 struct ia_css_stream *stream)
1279 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1283 #if WITH_PC_MONITORING
1284 static struct task_struct *my_kthread; /* Handle for the monitoring thread */
1285 static int sh_binary_running; /* Enable sampling in the thread */
1287 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1290 unsigned int cnt_run = 0;
1291 unsigned int cnt_stall = 0;
1296 sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1297 sh_css_print("%s PC\turn\tstall\n", core_name);
1299 for (i = 0; i < hist->length; i++) {
1300 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1302 sh_css_print("%s %d\t%d\t%d\n",
1303 core_name, i, hist->run[i], hist->stall[i]);
1304 cnt_run += hist->run[i];
1305 cnt_stall += hist->stall[i];
1308 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, hist->length = %d\n",
1309 core_name, cnt_run, cnt_stall, hist->length);
1312 static void print_pc_histogram(void)
1314 struct ia_css_binary_metrics *metrics;
1316 for (metrics = sh_css_metrics.binary_metrics;
1318 metrics = metrics->next) {
1319 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1320 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1321 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1326 sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1327 print_pc_histo(" ISP", &metrics->isp_histogram);
1328 print_pc_histo(" SP", &metrics->sp_histogram);
1329 sh_css_print("print_pc_histogram() done for binary->id = %d, done.\n",
1333 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1336 static int pc_monitoring(void *data)
1342 if (sh_binary_running) {
1343 sh_css_metrics_sample_pcs();
1344 #if MULTIPLE_SAMPLES
1345 for (i = 0; i < NOF_SAMPLES; i++)
1346 sh_css_metrics_sample_pcs();
1349 usleep_range(10, 50);
1354 static void spying_thread_create(void)
1356 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1357 sh_css_metrics_enable_pc_histogram(1);
1360 static void input_frame_info(struct ia_css_frame_info frame_info)
1362 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, frame->info.res.height = %d, format = %d\n",
1363 frame_info.res.width, frame_info.res.height, frame_info.format);
1365 #endif /* WITH_PC_MONITORING */
1368 start_binary(struct ia_css_pipe *pipe,
1369 struct ia_css_binary *binary)
1371 struct ia_css_stream *stream;
1374 /* Acceleration uses firmware, the binary thus can be NULL */
1375 /* assert(binary != NULL); */
1379 #if !defined(HAS_NO_INPUT_SYSTEM)
1380 stream = pipe->stream;
1387 sh_css_metrics_start_binary(&binary->metrics);
1389 #if WITH_PC_MONITORING
1390 sh_css_print("PC_MONITORING: %s() -- binary id = %d , enable_dvs_envelope = %d\n",
1391 __func__, binary->info->sp.id,
1392 binary->info->sp.enable.dvs_envelope);
1393 input_frame_info(binary->in_frame_info);
1395 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1396 sh_binary_running = true;
1399 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1400 if (stream->reconfigure_css_rx) {
1401 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1402 pipe->stream->config.mode);
1403 stream->reconfigure_css_rx = false;
1408 /* start the copy function on the SP */
1410 start_copy_on_sp(struct ia_css_pipe *pipe,
1411 struct ia_css_frame *out_frame) {
1414 assert(pipe->stream);
1416 if ((!pipe) || (!pipe->stream))
1419 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1420 if (pipe->stream->reconfigure_css_rx)
1421 ia_css_isys_rx_disable();
1424 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1426 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1428 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1429 if (pipe->stream->reconfigure_css_rx)
1431 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1432 pipe->stream->config.mode);
1433 pipe->stream->reconfigure_css_rx = false;
1440 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1444 for (i = 0; i < NUM_TNR_FRAMES; i++)
1445 args->tnr_frames[i] = NULL;
1446 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1447 args->delay_frames[i] = NULL;
1448 args->in_frame = NULL;
1449 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1450 args->out_frame[i] = NULL;
1451 args->out_vf_frame = NULL;
1452 args->copy_vf = false;
1453 args->copy_output = true;
1454 args->vf_downscale_log2 = 0;
1457 static void start_pipe(
1458 struct ia_css_pipe *me,
1459 enum sh_css_pipe_config_override copy_ovrd,
1460 enum ia_css_input_mode input_mode)
1462 const struct ia_css_coordinate *coord = NULL;
1463 const struct ia_css_isp_parameters *params = NULL;
1465 #if defined(HAS_NO_INPUT_SYSTEM)
1469 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1470 me, copy_ovrd, input_mode);
1472 assert(me); /* all callers are in this file and call with non null argument */
1475 coord = &me->config.internal_frame_origin_bqs_on_sctbl;
1476 params = me->stream->isp_params_configs;
1479 sh_css_sp_init_pipeline(&me->pipeline,
1481 (uint8_t)ia_css_pipe_get_pipe_num(me),
1482 me->config.default_capture_config.enable_xnr != 0,
1483 me->stream->config.pixels_per_clock == 2,
1484 me->stream->config.continuous,
1486 me->required_bds_factor,
1489 &me->stream->config.metadata_config,
1490 &me->stream->info.metadata_info
1491 #if !defined(HAS_NO_INPUT_SYSTEM)
1492 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ?
1493 (enum mipi_port_id)0 :
1494 me->stream->config.source.port.port,
1499 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1500 struct ia_css_pipeline_stage *stage;
1502 stage = me->pipeline.stages;
1504 me->pipeline.current_stage = stage;
1505 start_binary(me, stage->binary);
1508 IA_CSS_LEAVE_PRIVATE("void");
1512 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1518 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1519 "sh_css_invalidate_shading_tables() enter:\n");
1521 for (i = 0; i < stream->num_pipes; i++) {
1522 assert(stream->pipes[i]);
1523 sh_css_pipe_free_shading_table(stream->pipes[i]);
1526 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1527 "sh_css_invalidate_shading_tables() leave: return_void\n");
1531 enable_interrupts(enum ia_css_irq_type irq_type)
1533 #ifdef USE_INPUT_SYSTEM_VERSION_2
1534 enum mipi_port_id port;
1536 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1538 IA_CSS_ENTER_PRIVATE("");
1539 /* Enable IRQ on the SP which signals that SP goes to idle
1540 * (aka ready state) */
1541 cnd_sp_irq_enable(SP0_ID, true);
1542 /* Set the IRQ device 0 to either level or pulse */
1543 irq_enable_pulse(IRQ0_ID, enable_pulse);
1545 cnd_virq_enable_channel(virq_sp, true);
1547 /* Enable SW interrupt 0, this is used to signal ISYS events */
1548 cnd_virq_enable_channel(
1549 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1551 /* Enable SW interrupt 1, this is used to signal PSYS events */
1552 cnd_virq_enable_channel(
1553 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1555 #if !defined(HAS_IRQ_MAP_VERSION_2)
1556 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1557 cnd_virq_enable_channel(
1558 (enum virq_id)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1563 #ifdef USE_INPUT_SYSTEM_VERSION_2
1564 for (port = 0; port < N_MIPI_PORT_ID; port++)
1565 ia_css_isys_rx_enable_all_interrupts(port);
1568 IA_CSS_LEAVE_PRIVATE("");
1571 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1572 const char *program,
1573 ia_css_spctrl_cfg *spctrl_cfg)
1575 if ((!fw) || (!spctrl_cfg))
1577 spctrl_cfg->sp_entry = 0;
1578 spctrl_cfg->program_name = (char *)(program);
1580 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1581 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1582 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1583 spctrl_cfg->data_size = fw->blob.data_size;
1584 spctrl_cfg->bss_size = fw->blob.bss_size;
1586 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1587 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1589 spctrl_cfg->code_size = fw->blob.size;
1590 spctrl_cfg->code = fw->blob.code;
1591 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1597 ia_css_unload_firmware(void)
1599 if (sh_css_num_binaries) {
1600 /* we have already loaded before so get rid of the old stuff */
1601 ia_css_binary_uninit();
1602 sh_css_unload_firmware();
1604 fw_explicitly_loaded = false;
1608 ia_css_reset_defaults(struct sh_css *css)
1610 struct sh_css default_css;
1612 /* Reset everything to zero */
1613 memset(&default_css, 0, sizeof(default_css));
1615 /* Initialize the non zero values*/
1616 default_css.check_system_idle = true;
1617 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1619 /* All should be 0: but memset does it already.
1620 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1623 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1625 /*Set the defaults to the output */
1630 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
1631 const struct ia_css_fw *fw) {
1639 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1641 /* make sure we initialize my_css */
1642 if (my_css.flush != env->cpu_mem_env.flush)
1644 ia_css_reset_defaults(&my_css);
1645 my_css.flush = env->cpu_mem_env.flush;
1648 ia_css_unload_firmware(); /* in case we are called twice */
1649 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1652 err = ia_css_binary_init_infos();
1654 fw_explicitly_loaded = true;
1657 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n");
1662 ia_css_init(struct device *dev, const struct ia_css_env *env,
1663 const struct ia_css_fw *fw,
1665 enum ia_css_irq_type irq_type) {
1667 ia_css_spctrl_cfg spctrl_cfg;
1669 void (*flush_func)(struct ia_css_acc_fw *fw);
1670 hrt_data select, enable;
1673 * The C99 standard does not specify the exact object representation of structs;
1674 * the representation is compiler dependent.
1676 * The structs that are communicated between host and SP/ISP should have the
1677 * exact same object representation. The compiler that is used to compile the
1678 * firmware is hivecc.
1680 * To check if a different compiler, used to compile a host application, uses
1681 * another object representation, macros are defined specifying the size of
1682 * the structs as expected by the firmware.
1684 * A host application shall verify that a sizeof( ) of the struct is equal to
1685 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1686 * equal, functionality will break.
1688 /* Check struct sh_css_ddr_address_map */
1689 COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT);
1690 /* Check struct host_sp_queues */
1691 COMPILATION_ERROR_IF(sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT);
1692 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT);
1693 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT);
1695 /* Check struct host_sp_communication */
1696 COMPILATION_ERROR_IF(sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT);
1697 COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT);
1699 /* Check struct sh_css_hmm_buffer */
1700 COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT);
1701 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT);
1702 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT);
1703 COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT);
1705 /* Check struct ia_css_init_dmem_cfg */
1706 COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT);
1708 if (!fw && !fw_explicitly_loaded)
1713 sh_css_printf = env->print_env.debug_print;
1715 IA_CSS_ENTER("void");
1717 flush_func = env->cpu_mem_env.flush;
1720 ia_css_pipeline_init();
1721 ia_css_queue_map_init();
1723 ia_css_device_access_init(&env->hw_access_env);
1725 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1726 & (~GPIO_FLASH_PIN_MASK);
1727 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1728 | GPIO_FLASH_PIN_MASK;
1729 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1731 my_css_save.mmu_base = mmu_l1_base;
1733 ia_css_reset_defaults(&my_css);
1735 my_css_save.driver_env = *env;
1736 my_css.flush = flush_func;
1738 err = ia_css_rmgr_init();
1741 IA_CSS_LEAVE_ERR(err);
1745 IA_CSS_LOG("init: %d", my_css_save_initialized);
1747 if (!my_css_save_initialized)
1749 my_css_save_initialized = true;
1750 my_css_save.mode = sh_css_mode_working;
1751 memset(my_css_save.stream_seeds, 0,
1752 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1753 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1759 /* In case this has been programmed already, update internal
1760 data structure ... DEPRECATED */
1761 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1764 my_css.irq_type = irq_type;
1766 my_css_save.irq_type = irq_type;
1768 enable_interrupts(my_css.irq_type);
1770 /* configure GPIO to output mode */
1771 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1772 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1773 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1775 err = ia_css_refcount_init(REFCOUNT_SIZE);
1778 IA_CSS_LEAVE_ERR(err);
1781 err = sh_css_params_init();
1784 IA_CSS_LEAVE_ERR(err);
1789 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1790 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1792 IA_CSS_LEAVE_ERR(err);
1795 err = ia_css_binary_init_infos();
1797 IA_CSS_LEAVE_ERR(err);
1800 fw_explicitly_loaded = false;
1802 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1805 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg))
1808 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1811 IA_CSS_LEAVE_ERR(err);
1815 #if WITH_PC_MONITORING
1819 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1821 spying_thread_create();
1824 if (!sh_css_hrt_system_is_idle())
1826 IA_CSS_LEAVE_ERR(-EBUSY);
1829 /* can be called here, queuing works, but:
1830 - when sp is started later, it will wipe queued items
1831 so for now we leave it for later and make sure
1832 updates are not called to frequently.
1833 sh_css_init_buffer_queues();
1836 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1837 #if defined(USE_INPUT_SYSTEM_VERSION_2)
1838 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1839 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
1840 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1844 #if !defined(HAS_NO_INPUT_SYSTEM)
1845 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1846 ISP_DMA_MAX_BURST_LENGTH);
1848 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1852 sh_css_params_map_and_store_default_gdc_lut();
1854 IA_CSS_LEAVE_ERR(err);
1859 ia_css_enable_isys_event_queue(bool enable) {
1860 if (sh_css_sp_is_running())
1862 sh_css_sp_enable_isys_event_queue(enable);
1866 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1868 sh_css_flush(struct ia_css_acc_fw *fw)
1870 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1871 if ((fw) && (my_css.flush))
1875 /* Mapping sp threads. Currently, this is done when a stream is created and
1876 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1877 * doing it from stream_create since we could run out of sp threads due to
1878 * allocation on inactive pipelines. */
1880 map_sp_threads(struct ia_css_stream *stream, bool map) {
1881 struct ia_css_pipe *main_pipe = NULL;
1882 struct ia_css_pipe *copy_pipe = NULL;
1883 struct ia_css_pipe *capture_pipe = NULL;
1884 struct ia_css_pipe *acc_pipe = NULL;
1886 enum ia_css_pipe_id pipe_id;
1889 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1890 stream, map ? "true" : "false");
1894 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1898 main_pipe = stream->last_pipe;
1899 pipe_id = main_pipe->mode;
1901 ia_css_pipeline_map(main_pipe->pipe_num, map);
1905 case IA_CSS_PIPE_ID_PREVIEW:
1906 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1907 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1908 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1911 case IA_CSS_PIPE_ID_VIDEO:
1912 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1913 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1916 case IA_CSS_PIPE_ID_CAPTURE:
1917 case IA_CSS_PIPE_ID_ACC:
1924 ia_css_pipeline_map(acc_pipe->pipe_num, map);
1929 ia_css_pipeline_map(capture_pipe->pipe_num, map);
1932 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
1935 ia_css_pipeline_map(copy_pipe->pipe_num, map);
1937 /* DH regular multi pipe - not continuous mode: map the next pipes too */
1938 if (!stream->config.continuous)
1942 for (i = 1; i < stream->num_pipes; i++)
1943 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
1946 IA_CSS_LEAVE_ERR_PRIVATE(err);
1950 /* creates a host pipeline skeleton for all pipes in a stream. Called during
1953 create_host_pipeline_structure(struct ia_css_stream *stream) {
1954 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1955 struct ia_css_pipe *acc_pipe = NULL;
1956 enum ia_css_pipe_id pipe_id;
1957 struct ia_css_pipe *main_pipe = NULL;
1959 unsigned int copy_pipe_delay = 0,
1960 capture_pipe_delay = 0;
1963 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1967 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1971 main_pipe = stream->last_pipe;
1975 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1979 pipe_id = main_pipe->mode;
1983 case IA_CSS_PIPE_ID_PREVIEW:
1984 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1985 copy_pipe_delay = main_pipe->dvs_frame_delay;
1986 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1987 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1988 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1989 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1990 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1993 case IA_CSS_PIPE_ID_VIDEO:
1994 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1995 copy_pipe_delay = main_pipe->dvs_frame_delay;
1996 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1997 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1998 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1999 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2002 case IA_CSS_PIPE_ID_CAPTURE:
2003 capture_pipe = main_pipe;
2004 capture_pipe_delay = main_pipe->dvs_frame_delay;
2007 case IA_CSS_PIPE_ID_YUVPP:
2008 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2009 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2012 case IA_CSS_PIPE_ID_ACC:
2013 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2014 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2021 if (!(err) && copy_pipe)
2023 err = ia_css_pipeline_create(©_pipe->pipeline,
2025 copy_pipe->pipe_num,
2029 if (!(err) && capture_pipe)
2031 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2033 capture_pipe->pipe_num,
2034 capture_pipe_delay);
2037 if (!(err) && acc_pipe)
2039 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
2040 acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2043 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2044 if (!stream->config.continuous)
2048 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
2049 main_pipe = stream->pipes[i];
2050 err = ia_css_pipeline_create(&main_pipe->pipeline,
2052 main_pipe->pipe_num,
2053 main_pipe->dvs_frame_delay);
2057 IA_CSS_LEAVE_ERR_PRIVATE(err);
2061 /* creates a host pipeline for all pipes in a stream. Called during
2064 create_host_pipeline(struct ia_css_stream *stream) {
2065 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2066 struct ia_css_pipe *acc_pipe = NULL;
2067 enum ia_css_pipe_id pipe_id;
2068 struct ia_css_pipe *main_pipe = NULL;
2070 unsigned int max_input_width = 0;
2072 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2075 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2079 main_pipe = stream->last_pipe;
2080 pipe_id = main_pipe->mode;
2082 /* No continuous frame allocation for capture pipe. It uses the
2083 * "main" pipe's frames. */
2084 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2085 (pipe_id == IA_CSS_PIPE_ID_VIDEO))
2087 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2088 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2089 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2090 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2091 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2093 if (stream->config.continuous ||
2094 (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
2095 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2096 err = alloc_continuous_frames(main_pipe, true);
2102 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2103 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2104 if (pipe_id != IA_CSS_PIPE_ID_ACC)
2106 err = allocate_mipi_frames(main_pipe, &stream->info);
2110 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2111 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2112 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY))
2114 err = allocate_mipi_frames(main_pipe, &stream->info);
2122 case IA_CSS_PIPE_ID_PREVIEW:
2123 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2124 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2125 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2127 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2129 err = create_host_preview_pipeline(main_pipe);
2135 case IA_CSS_PIPE_ID_VIDEO:
2136 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2137 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2139 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2141 err = create_host_video_pipeline(main_pipe);
2147 case IA_CSS_PIPE_ID_CAPTURE:
2148 capture_pipe = main_pipe;
2152 case IA_CSS_PIPE_ID_YUVPP:
2153 err = create_host_yuvpp_pipeline(main_pipe);
2159 case IA_CSS_PIPE_ID_ACC:
2160 err = create_host_acc_pipeline(main_pipe);
2173 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2174 main_pipe->continuous_frames[0]);
2181 err = create_host_capture_pipeline(capture_pipe);
2188 err = create_host_acc_pipeline(acc_pipe);
2193 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2194 if (!stream->config.continuous)
2198 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
2199 switch (stream->pipes[i]->mode) {
2200 case IA_CSS_PIPE_ID_PREVIEW:
2201 err = create_host_preview_pipeline(stream->pipes[i]);
2203 case IA_CSS_PIPE_ID_VIDEO:
2204 err = create_host_video_pipeline(stream->pipes[i]);
2206 case IA_CSS_PIPE_ID_CAPTURE:
2207 err = create_host_capture_pipeline(stream->pipes[i]);
2209 case IA_CSS_PIPE_ID_YUVPP:
2210 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2212 case IA_CSS_PIPE_ID_ACC:
2213 err = create_host_acc_pipeline(stream->pipes[i]);
2224 IA_CSS_LEAVE_ERR_PRIVATE(err);
2228 static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
2229 static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2230 static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2231 static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2232 static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2235 init_pipe_defaults(enum ia_css_pipe_mode mode,
2236 struct ia_css_pipe *pipe,
2241 IA_CSS_ERROR("NULL pipe parameter");
2245 /* Initialize pipe to pre-defined defaults */
2246 memcpy(pipe, &default_pipe, sizeof(default_pipe));
2248 /* TODO: JB should not be needed, but temporary backward reference */
2251 case IA_CSS_PIPE_MODE_PREVIEW:
2252 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2253 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview));
2255 case IA_CSS_PIPE_MODE_CAPTURE:
2257 pipe->mode = IA_CSS_PIPE_ID_COPY;
2259 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2261 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture));
2263 case IA_CSS_PIPE_MODE_VIDEO:
2264 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2265 memcpy(&pipe->pipe_settings.video, &video, sizeof(video));
2267 case IA_CSS_PIPE_MODE_ACC:
2268 pipe->mode = IA_CSS_PIPE_ID_ACC;
2270 case IA_CSS_PIPE_MODE_COPY:
2271 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2273 case IA_CSS_PIPE_MODE_YUVPP:
2274 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2275 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp));
2285 pipe_global_init(void)
2289 my_css.pipe_counter = 0;
2290 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2291 my_css.all_pipes[i] = NULL;
2296 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
2297 unsigned int *pipe_number) {
2298 const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
2299 u8 pipe_num = INVALID_PIPE_NUM;
2304 IA_CSS_ERROR("NULL pipe parameter");
2308 /* Assign a new pipe_num .... search for empty place */
2309 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
2311 if (!my_css.all_pipes[i]) {
2312 /*position is reserved */
2313 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2318 if (pipe_num == INVALID_PIPE_NUM)
2320 /* Max number of pipes already allocated */
2321 IA_CSS_ERROR("Max number of pipes already created");
2325 my_css.pipe_counter++;
2327 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2329 *pipe_number = pipe_num;
2334 pipe_release_pipe_num(unsigned int pipe_num)
2336 my_css.all_pipes[pipe_num] = NULL;
2337 my_css.pipe_counter--;
2338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2339 "pipe_release_pipe_num (%d)\n", pipe_num);
2343 create_pipe(enum ia_css_pipe_mode mode,
2344 struct ia_css_pipe **pipe,
2347 struct ia_css_pipe *me;
2351 IA_CSS_ERROR("NULL pipe parameter");
2355 me = kmalloc(sizeof(*me), GFP_KERNEL);
2359 err = init_pipe_defaults(mode, me, copy_pipe);
2366 err = pipe_generate_pipe_num(me, &me->pipe_num);
2377 struct ia_css_pipe *
2378 find_pipe_by_num(uint32_t pipe_num)
2382 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2383 if (my_css.all_pipes[i] &&
2384 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2385 return my_css.all_pipes[i];
2391 static void sh_css_pipe_free_acc_binaries(
2392 struct ia_css_pipe *pipe)
2394 struct ia_css_pipeline *pipeline;
2395 struct ia_css_pipeline_stage *stage;
2399 IA_CSS_ERROR("NULL input pointer");
2402 pipeline = &pipe->pipeline;
2404 /* loop through the stages and unload them */
2405 for (stage = pipeline->stages; stage; stage = stage->next) {
2406 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2409 ia_css_pipe_unload_extension(pipe, firmware);
2414 ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
2417 IA_CSS_ENTER("pipe = %p", pipe);
2421 IA_CSS_LEAVE_ERR(-EINVAL);
2427 IA_CSS_LOG("ia_css_stream_destroy not called!");
2428 IA_CSS_LEAVE_ERR(-EINVAL);
2432 switch (pipe->config.mode)
2434 case IA_CSS_PIPE_MODE_PREVIEW:
2435 /* need to take into account that this function is also called
2436 on the internal copy pipe */
2437 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2438 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2439 pipe->continuous_frames);
2440 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2441 pipe->cont_md_buffers);
2442 if (pipe->pipe_settings.preview.copy_pipe) {
2443 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2444 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2445 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2450 case IA_CSS_PIPE_MODE_VIDEO:
2451 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2452 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2453 pipe->continuous_frames);
2454 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2455 pipe->cont_md_buffers);
2456 if (pipe->pipe_settings.video.copy_pipe) {
2457 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2458 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2459 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2464 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2465 pipe->pipe_settings.video.tnr_frames);
2467 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2468 pipe->pipe_settings.video.tnr_frames);
2470 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2471 pipe->pipe_settings.video.delay_frames);
2473 case IA_CSS_PIPE_MODE_CAPTURE:
2474 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2475 pipe->pipe_settings.capture.delay_frames);
2477 case IA_CSS_PIPE_MODE_ACC:
2478 sh_css_pipe_free_acc_binaries(pipe);
2480 case IA_CSS_PIPE_MODE_COPY:
2482 case IA_CSS_PIPE_MODE_YUVPP:
2486 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2487 pipe->scaler_pp_lut = mmgr_NULL;
2489 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2490 sh_css_pipe_free_shading_table(pipe);
2492 ia_css_pipeline_destroy(&pipe->pipeline);
2493 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2495 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2496 if (pipe->config.acc_extension)
2498 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2501 IA_CSS_LEAVE("err = %d", err);
2508 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2509 #if WITH_PC_MONITORING
2510 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2511 print_pc_histogram();
2514 sh_css_params_free_default_gdc_lut();
2516 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2517 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2518 /* cleanup generic data */
2519 sh_css_params_uninit();
2520 ia_css_refcount_uninit();
2522 ia_css_rmgr_uninit();
2524 #if !defined(HAS_NO_INPUT_FORMATTER)
2525 /* needed for reprogramming the inputformatter after power cycle of css */
2526 ifmtr_set_if_blocking_mode_reset = true;
2529 if (!fw_explicitly_loaded) {
2530 ia_css_unload_firmware();
2532 ia_css_spctrl_unload_fw(SP0_ID);
2533 sh_css_sp_set_sp_running(false);
2534 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2535 /* check and free any remaining mipi frames */
2536 free_mipi_frames(NULL);
2539 sh_css_sp_reset_global_vars();
2541 #if !defined(HAS_NO_INPUT_SYSTEM)
2542 ia_css_isys_uninit();
2545 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2548 #if defined(HAS_IRQ_MAP_VERSION_2)
2549 int ia_css_irq_translate(
2550 unsigned int *irq_infos)
2553 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2554 unsigned int infos = 0;
2556 /* irq_infos can be NULL, but that would make the function useless */
2557 /* assert(irq_infos != NULL); */
2558 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2559 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2561 while (status == hrt_isp_css_irq_status_more_irqs) {
2562 status = virq_get_channel_id(&irq);
2563 if (status == hrt_isp_css_irq_status_error)
2566 #if WITH_PC_MONITORING
2567 sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n",
2569 sh_binary_running = 0;
2574 /* When SP goes to idle, info is available in the
2576 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2580 #if !defined(HAS_NO_INPUT_SYSTEM)
2582 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2585 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2588 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2591 #if !defined(HAS_NO_INPUT_FORMATTER)
2593 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2597 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2600 infos |= sh_css_get_sw_interrupt_value(0);
2603 infos |= sh_css_get_sw_interrupt_value(1);
2604 /* pqiao TODO: also assumption here */
2614 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2615 "ia_css_irq_translate() leave: irq_infos=%u\n",
2621 int ia_css_irq_enable(
2622 enum ia_css_irq_info info,
2625 enum virq_id irq = N_virq_id;
2627 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2630 #if !defined(HAS_NO_INPUT_FORMATTER)
2631 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2632 irq = virq_isys_sof;
2634 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2635 irq = virq_isys_eof;
2637 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2638 irq = virq_isys_csi;
2640 case IA_CSS_IRQ_INFO_IF_ERROR:
2641 irq = virq_ifmt0_id;
2644 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2645 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2646 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2647 case IA_CSS_IRQ_INFO_IF_ERROR:
2648 /* Just ignore those unused IRQs without printing errors */
2651 case IA_CSS_IRQ_INFO_DMA_ERROR:
2654 case IA_CSS_IRQ_INFO_SW_0:
2655 irq = virq_sw_pin_0;
2657 case IA_CSS_IRQ_INFO_SW_1:
2658 irq = virq_sw_pin_1;
2661 IA_CSS_LEAVE_ERR(-EINVAL);
2665 cnd_virq_enable_channel(irq, enable);
2667 IA_CSS_LEAVE_ERR(0);
2672 #error "sh_css.c: IRQ MAP must be one of { IRQ_MAP_VERSION_2 }"
2676 sh_css_get_sw_interrupt_value(unsigned int irq)
2678 unsigned int irq_value;
2680 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2681 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2682 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2683 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2684 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2688 /* configure and load the copy binary, the next binary is used to
2689 determine whether the copy binary needs to do left padding. */
2690 static int load_copy_binary(
2691 struct ia_css_pipe *pipe,
2692 struct ia_css_binary *copy_binary,
2693 struct ia_css_binary *next_binary)
2695 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2696 unsigned int left_padding;
2698 struct ia_css_binary_descr copy_descr;
2700 /* next_binary can be NULL */
2702 assert(copy_binary);
2703 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2704 "load_copy_binary() enter:\n");
2707 copy_out_info = next_binary->in_frame_info;
2708 left_padding = next_binary->left_padding;
2710 copy_out_info = pipe->output_info[0];
2711 copy_vf_info = pipe->vf_output_info[0];
2712 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2716 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2717 ©_in_info, ©_out_info,
2718 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/);
2719 err = ia_css_binary_find(©_descr, copy_binary);
2722 copy_binary->left_padding = left_padding;
2727 alloc_continuous_frames(
2728 struct ia_css_pipe *pipe, bool init_time) {
2730 struct ia_css_frame_info ref_info;
2731 enum ia_css_pipe_id pipe_id;
2733 unsigned int i, idx;
2734 unsigned int num_frames;
2735 struct ia_css_pipe *capture_pipe = NULL;
2737 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2739 if ((!pipe) || (!pipe->stream))
2741 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2745 pipe_id = pipe->mode;
2746 continuous = pipe->stream->config.continuous;
2751 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2752 pipe->stream->continuous_pipe = pipe;
2754 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2757 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2760 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2762 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2763 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2765 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2768 /* should not happen */
2769 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2773 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2774 /* For CSI2+, the continuous frame will hold the full input frame */
2775 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2776 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2778 /* Ensure padded width is aligned for 2401 */
2779 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2782 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2783 if (pipe->stream->config.pack_raw_pixels)
2785 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2786 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2787 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2791 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2792 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2793 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2796 /* Write format back to binary */
2797 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2799 pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2801 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2802 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2804 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2805 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2808 /* should not happen */
2809 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2816 idx = pipe->stream->config.init_num_cont_raw_buf;
2818 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++)
2820 /* free previous frame */
2821 if (pipe->continuous_frames[i]) {
2822 ia_css_frame_free(pipe->continuous_frames[i]);
2823 pipe->continuous_frames[i] = NULL;
2825 /* free previous metadata buffer */
2826 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2827 pipe->cont_md_buffers[i] = NULL;
2829 /* check if new frame needed */
2830 if (i < num_frames) {
2831 /* allocate new frame */
2832 err = ia_css_frame_allocate_from_info(
2833 &pipe->continuous_frames[i],
2836 IA_CSS_LEAVE_ERR_PRIVATE(err);
2839 /* allocate metadata buffer */
2840 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2841 &pipe->stream->info.metadata_info);
2844 IA_CSS_LEAVE_ERR_PRIVATE(0);
2849 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) {
2852 return alloc_continuous_frames(stream->continuous_pipe, false);
2856 load_preview_binaries(struct ia_css_pipe *pipe) {
2857 struct ia_css_frame_info prev_in_info,
2861 struct ia_css_binary_descr preview_descr;
2864 bool continuous, need_vf_pp = false;
2865 bool need_isp_copy_binary = false;
2866 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2867 bool sensor = false;
2869 /* preview only have 1 output pin now */
2870 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2871 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2873 IA_CSS_ENTER_PRIVATE("");
2875 assert(pipe->stream);
2876 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2878 online = pipe->stream->config.online;
2879 continuous = pipe->stream->config.continuous;
2880 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2881 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2884 if (mycs->preview_binary.info)
2887 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2890 err = ia_css_frame_check_info(pipe_out_info);
2894 /* Note: the current selection of vf_pp binary and
2895 * parameterization of the preview binary contains a few pieces
2896 * of hardcoded knowledge. This needs to be cleaned up such that
2897 * the binary selection becomes more generic.
2898 * The vf_pp binary is needed if one or more of the following features
2900 * 1. YUV downscaling.
2902 * 3. An output format that is not supported by the preview binary.
2903 * In practice this means something other than yuv_line or nv12.
2904 * The decision if the vf_pp binary is needed for YUV downscaling is
2905 * made after the preview binary selection, since some preview binaries
2906 * can perform the requested YUV downscaling.
2908 need_vf_pp = pipe->config.enable_dz;
2909 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2910 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2911 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2912 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2914 /* Preview step 1 */
2915 if (pipe->vf_yuv_ds_input_info.res.width)
2916 prev_vf_info = pipe->vf_yuv_ds_input_info;
2918 prev_vf_info = *pipe_out_info;
2919 /* If vf_pp is needed, then preview must output yuv_line.
2920 * The exception is when vf_pp is manually disabled, that is only
2921 * used in combination with a pipeline extension that requires
2922 * yuv_line as input.
2925 ia_css_frame_info_set_format(&prev_vf_info,
2926 IA_CSS_FRAME_FORMAT_YUV_LINE);
2928 err = ia_css_pipe_get_preview_binarydesc(
2937 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2942 /* The delay latency determines the number of invalid frames after
2943 * a stream is started. */
2944 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2945 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2947 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2948 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2949 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2952 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2953 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2954 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2956 /* When vf_pp is needed, then the output format of the selected
2957 * preview binary must be yuv_line. If this is not the case,
2958 * then the preview binary selection is done again.
2961 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE))
2963 /* Preview step 2 */
2964 if (pipe->vf_yuv_ds_input_info.res.width)
2965 prev_vf_info = pipe->vf_yuv_ds_input_info;
2967 prev_vf_info = *pipe_out_info;
2969 ia_css_frame_info_set_format(&prev_vf_info,
2970 IA_CSS_FRAME_FORMAT_YUV_LINE);
2972 err = ia_css_pipe_get_preview_binarydesc(
2981 err = ia_css_binary_find(&preview_descr,
2982 &mycs->preview_binary);
2989 struct ia_css_binary_descr vf_pp_descr;
2991 /* Viewfinder post-processing */
2992 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
2993 &mycs->preview_binary.out_frame_info[0],
2995 err = ia_css_binary_find(&vf_pp_descr,
2996 &mycs->vf_pp_binary);
3001 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3002 /* When the input system is 2401, only the Direct Sensor Mode
3003 * Offline Preview uses the ISP copy binary.
3005 need_isp_copy_binary = !online && sensor;
3007 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3008 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3009 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3010 * copies sensor data to DDR) does not have much use.
3013 need_isp_copy_binary = !online && !continuous;
3015 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3019 if (need_isp_copy_binary)
3021 err = load_copy_binary(pipe,
3023 &mycs->preview_binary);
3028 if (pipe->shading_table)
3030 ia_css_shading_table_free(pipe->shading_table);
3031 pipe->shading_table = NULL;
3038 ia_css_binary_unload(struct ia_css_binary *binary)
3040 ia_css_binary_destroy_isp_parameters(binary);
3044 unload_preview_binaries(struct ia_css_pipe *pipe) {
3045 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3047 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3049 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3052 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3053 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3054 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3056 IA_CSS_LEAVE_ERR_PRIVATE(0);
3060 static const struct ia_css_fw_info *last_output_firmware(
3061 const struct ia_css_fw_info *fw)
3063 const struct ia_css_fw_info *last_fw = NULL;
3064 /* fw can be NULL */
3065 IA_CSS_ENTER_LEAVE_PRIVATE("");
3067 for (; fw; fw = fw->next) {
3068 const struct ia_css_fw_info *info = fw;
3070 if (info->info.isp.sp.enable.output)
3076 static int add_firmwares(
3077 struct ia_css_pipeline *me,
3078 struct ia_css_binary *binary,
3079 const struct ia_css_fw_info *fw,
3080 const struct ia_css_fw_info *last_fw,
3081 unsigned int binary_mode,
3082 struct ia_css_frame *in_frame,
3083 struct ia_css_frame *out_frame,
3084 struct ia_css_frame *vf_frame,
3085 struct ia_css_pipeline_stage **my_stage,
3086 struct ia_css_pipeline_stage **vf_stage)
3089 struct ia_css_pipeline_stage *extra_stage = NULL;
3090 struct ia_css_pipeline_stage_desc stage_desc;
3092 /* all args can be NULL ??? */
3093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3094 "add_firmwares() enter:\n");
3096 for (; fw; fw = fw->next) {
3097 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3098 struct ia_css_frame *in = NULL;
3099 struct ia_css_frame *vf = NULL;
3101 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3104 if (fw->info.isp.sp.enable.in_frame != 0) {
3107 if (fw->info.isp.sp.enable.out_frame != 0) {
3110 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3111 out, in, vf, fw, binary_mode);
3112 err = ia_css_pipeline_create_and_add_stage(me,
3117 if (fw->info.isp.sp.enable.output != 0)
3118 in_frame = extra_stage->args.out_frame[0];
3119 if (my_stage && !*my_stage && extra_stage)
3120 *my_stage = extra_stage;
3121 if (vf_stage && !*vf_stage && extra_stage &&
3122 fw->info.isp.sp.enable.vf_veceven)
3123 *vf_stage = extra_stage;
3128 static int add_vf_pp_stage(
3129 struct ia_css_pipe *pipe,
3130 struct ia_css_frame *in_frame,
3131 struct ia_css_frame *out_frame,
3132 struct ia_css_binary *vf_pp_binary,
3133 struct ia_css_pipeline_stage **vf_pp_stage)
3135 struct ia_css_pipeline *me = NULL;
3136 const struct ia_css_fw_info *last_fw = NULL;
3138 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3139 struct ia_css_pipeline_stage_desc stage_desc;
3141 /* out_frame can be NULL ??? */
3152 ia_css_pipe_util_create_output_frames(out_frames);
3153 me = &pipe->pipeline;
3155 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3156 "add_vf_pp_stage() enter:\n");
3158 *vf_pp_stage = NULL;
3160 last_fw = last_output_firmware(pipe->vf_stage);
3161 if (!pipe->extra_config.disable_vf_pp) {
3163 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3164 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3165 out_frames, in_frame, NULL);
3167 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3168 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3169 out_frames, in_frame, NULL);
3171 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3174 in_frame = (*vf_pp_stage)->args.out_frame[0];
3176 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3177 IA_CSS_BINARY_MODE_VF_PP,
3178 in_frame, out_frame, NULL,
3183 static int add_yuv_scaler_stage(
3184 struct ia_css_pipe *pipe,
3185 struct ia_css_pipeline *me,
3186 struct ia_css_frame *in_frame,
3187 struct ia_css_frame *out_frame,
3188 struct ia_css_frame *internal_out_frame,
3189 struct ia_css_binary *yuv_scaler_binary,
3190 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3192 const struct ia_css_fw_info *last_fw;
3194 struct ia_css_frame *vf_frame = NULL;
3195 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3196 struct ia_css_pipeline_stage_desc stage_desc;
3198 /* out_frame can be NULL ??? */
3202 assert(yuv_scaler_binary);
3203 assert(pre_vf_pp_stage);
3204 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3205 "add_yuv_scaler_stage() enter:\n");
3207 *pre_vf_pp_stage = NULL;
3208 ia_css_pipe_util_create_output_frames(out_frames);
3210 last_fw = last_output_firmware(pipe->output_stage);
3213 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3214 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3215 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3217 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3218 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3219 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3220 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3222 err = ia_css_pipeline_create_and_add_stage(me,
3227 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3229 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3230 IA_CSS_BINARY_MODE_CAPTURE_PP,
3231 in_frame, out_frame, vf_frame,
3232 NULL, pre_vf_pp_stage);
3233 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3234 (*pre_vf_pp_stage)->args.vf_downscale_log2 =
3235 yuv_scaler_binary->vf_downscale_log2;
3237 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3238 "add_yuv_scaler_stage() leave:\n");
3242 static int add_capture_pp_stage(
3243 struct ia_css_pipe *pipe,
3244 struct ia_css_pipeline *me,
3245 struct ia_css_frame *in_frame,
3246 struct ia_css_frame *out_frame,
3247 struct ia_css_binary *capture_pp_binary,
3248 struct ia_css_pipeline_stage **capture_pp_stage)
3250 const struct ia_css_fw_info *last_fw = NULL;
3252 struct ia_css_frame *vf_frame = NULL;
3253 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3254 struct ia_css_pipeline_stage_desc stage_desc;
3256 /* out_frame can be NULL ??? */
3260 assert(capture_pp_binary);
3261 assert(capture_pp_stage);
3262 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3263 "add_capture_pp_stage() enter:\n");
3265 *capture_pp_stage = NULL;
3266 ia_css_pipe_util_create_output_frames(out_frames);
3268 last_fw = last_output_firmware(pipe->output_stage);
3269 err = ia_css_frame_allocate_from_info(&vf_frame,
3270 &capture_pp_binary->vf_frame_info);
3274 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3275 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3276 capture_pp_binary, out_frames, NULL, vf_frame);
3278 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3279 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3280 capture_pp_binary, out_frames, NULL, vf_frame);
3282 err = ia_css_pipeline_create_and_add_stage(me,
3287 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3288 IA_CSS_BINARY_MODE_CAPTURE_PP,
3289 in_frame, out_frame, vf_frame,
3290 NULL, capture_pp_stage);
3291 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3292 if (*capture_pp_stage) {
3293 (*capture_pp_stage)->args.vf_downscale_log2 =
3294 capture_pp_binary->vf_downscale_log2;
3299 static void sh_css_setup_queues(void)
3301 const struct ia_css_fw_info *fw;
3302 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3304 sh_css_hmm_buffer_record_init();
3306 sh_css_event_init_irq_mask();
3309 HIVE_ADDR_host_sp_queues_initialized =
3310 fw->info.sp.host_sp_queues_initialized;
3314 /* set "host_sp_queues_initialized" to "true" */
3315 sp_dmem_store_uint32(SP0_ID,
3316 (unsigned int)sp_address_of(host_sp_queues_initialized),
3318 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3322 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3323 struct ia_css_frame *vf_frame, unsigned int idx) {
3325 unsigned int thread_id;
3326 enum sh_css_queue_id queue_id;
3330 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3331 vf_frame->contiguous = false;
3332 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3333 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3334 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3335 vf_frame->dynamic_queue_id = queue_id;
3336 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3338 err = ia_css_frame_init_planes(vf_frame);
3342 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3344 get_crop_lines_for_bayer_order(
3345 const struct ia_css_stream_config *config)
3348 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
3349 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3356 get_crop_columns_for_bayer_order(
3357 const struct ia_css_stream_config *config)
3360 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
3361 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3367 /* This function is to get the sum of all extra pixels in addition to the effective
3368 * input, it includes dvs envelop and filter run-in */
3369 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3370 unsigned int *extra_row, unsigned int *extra_column)
3372 enum ia_css_pipe_id pipe_id = pipe->mode;
3373 unsigned int left_cropping = 0, top_cropping = 0;
3375 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3377 /* The dvs envelope info may not be correctly sent down via pipe config
3378 * The check is made and the correct value is populated in the binary info
3379 * Use this value when computing crop, else excess lines may get trimmed
3382 case IA_CSS_PIPE_ID_PREVIEW:
3383 if (pipe->pipe_settings.preview.preview_binary.info) {
3385 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3387 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3389 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3391 case IA_CSS_PIPE_ID_VIDEO:
3392 if (pipe->pipe_settings.video.video_binary.info) {
3394 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3396 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3398 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3400 case IA_CSS_PIPE_ID_CAPTURE:
3401 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3402 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3404 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3406 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3409 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3411 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3418 *extra_row = top_cropping + dvs_env.height;
3419 *extra_column = left_cropping + dvs_env.width;
3423 ia_css_get_crop_offsets(
3424 struct ia_css_pipe *pipe,
3425 struct ia_css_frame_info *in_frame)
3427 unsigned int row = 0;
3428 unsigned int column = 0;
3429 struct ia_css_resolution *input_res;
3430 struct ia_css_resolution *effective_res;
3431 unsigned int extra_row = 0, extra_col = 0;
3432 unsigned int min_reqd_height, min_reqd_width;
3435 assert(pipe->stream);
3438 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3439 pipe, pipe->config.input_effective_res.width,
3440 pipe->config.input_effective_res.height);
3442 input_res = &pipe->stream->config.input_config.input_res;
3444 effective_res = &pipe->stream->config.input_config.effective_res;
3446 effective_res = &pipe->config.input_effective_res;
3449 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3451 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3453 min_reqd_height = effective_res->height + extra_row;
3454 min_reqd_width = effective_res->width + extra_col;
3456 if (input_res->height > min_reqd_height) {
3457 row = (input_res->height - min_reqd_height) / 2;
3460 if (input_res->width > min_reqd_width) {
3461 column = (input_res->width - min_reqd_width) / 2;
3467 * 1. Require the special support for RAW10 packed mode.
3468 * 2. Require the special support for the online use cases.
3471 /* ISP expects GRBG bayer order, we skip one line and/or one row
3472 * to correct in case the input bayer order is different.
3474 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3475 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3477 in_frame->crop_info.start_column = column;
3478 in_frame->crop_info.start_line = row;
3480 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3487 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3488 struct ia_css_frame *frame, enum ia_css_frame_format format) {
3489 struct ia_css_frame *in_frame;
3491 unsigned int thread_id;
3492 enum sh_css_queue_id queue_id;
3497 in_frame->info.format = format;
3499 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3500 if (format == IA_CSS_FRAME_FORMAT_RAW)
3501 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3502 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3505 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3506 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3507 in_frame->info.raw_bit_depth =
3508 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3509 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3510 in_frame->contiguous = false;
3511 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3512 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3513 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3514 in_frame->dynamic_queue_id = queue_id;
3515 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3516 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3517 ia_css_get_crop_offsets(pipe, &in_frame->info);
3519 err = ia_css_frame_init_planes(in_frame);
3521 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3522 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3528 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3529 struct ia_css_frame *out_frame, unsigned int idx) {
3531 unsigned int thread_id;
3532 enum sh_css_queue_id queue_id;
3536 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3537 out_frame->contiguous = false;
3538 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3539 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3540 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3541 out_frame->dynamic_queue_id = queue_id;
3542 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3543 err = ia_css_frame_init_planes(out_frame);
3548 /* Create stages for video pipe */
3549 static int create_host_video_pipeline(struct ia_css_pipe *pipe)
3551 struct ia_css_pipeline_stage_desc stage_desc;
3552 struct ia_css_binary *copy_binary, *video_binary,
3553 *yuv_scaler_binary, *vf_pp_binary;
3554 struct ia_css_pipeline_stage *copy_stage = NULL;
3555 struct ia_css_pipeline_stage *video_stage = NULL;
3556 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3557 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3558 struct ia_css_pipeline *me;
3559 struct ia_css_frame *in_frame = NULL;
3560 struct ia_css_frame *out_frame;
3561 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3562 struct ia_css_frame *vf_frame = NULL;
3564 bool need_copy = false;
3565 bool need_vf_pp = false;
3566 bool need_yuv_pp = false;
3567 unsigned int num_output_pins;
3568 bool need_in_frameinfo_memory = false;
3570 unsigned int i, num_yuv_scaler;
3571 bool *is_output_stage = NULL;
3573 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3574 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3575 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3578 ia_css_pipe_util_create_output_frames(out_frames);
3579 out_frame = &pipe->out_frame_struct;
3581 /* pipeline already created as part of create_host_pipeline_structure */
3582 me = &pipe->pipeline;
3583 ia_css_pipeline_clean(me);
3585 me->dvs_frame_delay = pipe->dvs_frame_delay;
3587 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3588 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3589 * except for the following: online or continuous
3591 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3592 pipe->stream->config.continuous);
3594 /* Construct in_frame info (only in case we have dynamic input */
3595 need_in_frameinfo_memory = pipe->stream->config.mode ==
3596 IA_CSS_INPUT_MODE_MEMORY;
3599 /* Construct in_frame info (only in case we have dynamic input */
3600 if (need_in_frameinfo_memory) {
3601 in_frame = &pipe->in_frame_struct;
3602 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3603 IA_CSS_FRAME_FORMAT_RAW);
3608 out_frame->data = 0;
3609 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3613 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3614 vf_frame = &pipe->vf_frame_struct;
3616 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3621 copy_binary = &pipe->pipe_settings.video.copy_binary;
3622 video_binary = &pipe->pipe_settings.video.video_binary;
3623 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3624 num_output_pins = video_binary->info->num_output_pins;
3626 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3627 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3628 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3630 need_copy = (copy_binary && copy_binary->info);
3631 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3632 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3635 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3636 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3637 out_frames, NULL, NULL);
3638 err = ia_css_pipeline_create_and_add_stage(me,
3643 in_frame = me->stages->args.out_frame[0];
3644 } else if (pipe->stream->config.continuous) {
3645 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3646 /* When continuous is enabled, configure in_frame with the
3647 * last pipe, which is the copy pipe.
3649 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3651 in_frame = pipe->continuous_frames[0];
3655 ia_css_pipe_util_set_output_frames(out_frames, 0,
3656 need_yuv_pp ? NULL : out_frame);
3658 /* when the video binary supports a second output pin,
3659 it can directly produce the vf_frame. */
3661 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3662 out_frames, in_frame, NULL);
3664 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3665 out_frames, in_frame, vf_frame);
3667 err = ia_css_pipeline_create_and_add_stage(me,
3673 /* If we use copy iso video, the input must be yuv iso raw */
3675 video_stage->args.copy_vf =
3676 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3677 video_stage->args.copy_output = video_stage->args.copy_vf;
3680 /* when the video binary supports only 1 output pin, vf_pp is needed to
3681 produce the vf_frame.*/
3682 if (need_vf_pp && video_stage) {
3683 in_frame = video_stage->args.out_vf_frame;
3684 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3692 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3693 video_stage->args.tnr_frames[frm] =
3694 pipe->pipe_settings.video.tnr_frames[frm];
3696 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3697 video_stage->args.delay_frames[frm] =
3698 pipe->pipe_settings.video.delay_frames[frm];
3702 /* Append Extension on Video out, if enabled */
3703 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3704 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3705 struct ia_css_frame *out = NULL;
3706 struct ia_css_frame *in = NULL;
3708 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3709 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3710 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3711 /* In/Out Frame mapping to support output frame extension.*/
3712 out = video_stage->args.out_frame[0];
3713 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3716 video_stage->args.out_frame[0] = in;
3719 err = add_firmwares(me, video_binary, pipe->output_stage,
3720 last_output_firmware(pipe->output_stage),
3721 IA_CSS_BINARY_MODE_VIDEO,
3722 in, out, NULL, &video_stage, NULL);
3727 if (need_yuv_pp && video_stage) {
3728 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3729 struct ia_css_frame *tmp_out_frame = NULL;
3731 for (i = 0; i < num_yuv_scaler; i++) {
3732 if (is_output_stage[i] == true) {
3733 tmp_out_frame = out_frame;
3735 tmp_out_frame = NULL;
3737 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3739 &yuv_scaler_binary[i],
3743 IA_CSS_LEAVE_ERR_PRIVATE(err);
3746 /* we use output port 1 as internal output port */
3747 if (yuv_scaler_stage)
3748 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3752 pipe->pipeline.acquire_isp_each_stage = false;
3753 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3754 pipe->stream->config.continuous);
3757 IA_CSS_LEAVE_ERR_PRIVATE(err);
3762 create_host_acc_pipeline(struct ia_css_pipe *pipe) {
3764 const struct ia_css_fw_info *fw;
3767 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3768 if ((!pipe) || (!pipe->stream))
3770 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3774 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3775 /* Reset pipe_qos_config to default disable all QOS extension stages */
3776 if (pipe->config.acc_extension)
3777 pipe->pipeline.pipe_qos_config = 0;
3779 fw = pipe->vf_stage;
3780 for (i = 0; fw; fw = fw->next)
3782 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3787 for (i = 0; i < pipe->config.num_acc_stages; i++)
3789 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3791 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3796 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3799 IA_CSS_LEAVE_ERR_PRIVATE(err);
3803 /* Create stages for preview */
3805 create_host_preview_pipeline(struct ia_css_pipe *pipe) {
3806 struct ia_css_pipeline_stage *copy_stage = NULL;
3807 struct ia_css_pipeline_stage *preview_stage = NULL;
3808 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3809 struct ia_css_pipeline_stage_desc stage_desc;
3810 struct ia_css_pipeline *me = NULL;
3811 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3812 struct ia_css_frame *in_frame = NULL;
3814 struct ia_css_frame *out_frame;
3815 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3816 bool need_in_frameinfo_memory = false;
3817 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3818 bool sensor = false;
3819 bool buffered_sensor = false;
3820 bool online = false;
3821 bool continuous = false;
3824 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3825 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3827 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3831 ia_css_pipe_util_create_output_frames(out_frames);
3832 /* pipeline already created as part of create_host_pipeline_structure */
3833 me = &pipe->pipeline;
3834 ia_css_pipeline_clean(me);
3836 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3837 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3838 * except for the following:
3839 * - Direct Sensor Mode Online Preview
3840 * - Buffered Sensor Mode Online Preview
3841 * - Direct Sensor Mode Continuous Preview
3842 * - Buffered Sensor Mode Continuous Preview
3844 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3845 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3846 online = pipe->stream->config.online;
3847 continuous = pipe->stream->config.continuous;
3848 need_in_frameinfo_memory =
3849 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3851 /* Construct in_frame info (only in case we have dynamic input */
3852 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3854 if (need_in_frameinfo_memory)
3856 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3857 IA_CSS_FRAME_FORMAT_RAW);
3861 in_frame = &me->in_frame;
3867 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3870 out_frame = &me->out_frame[0];
3872 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3873 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3874 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3875 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3877 if (pipe->pipe_settings.preview.copy_binary.info)
3879 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3880 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3881 out_frames, NULL, NULL);
3882 err = ia_css_pipeline_create_and_add_stage(me,
3887 in_frame = me->stages->args.out_frame[0];
3892 } else if (pipe->stream->config.continuous)
3895 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3896 /* When continuous is enabled, configure in_frame with the
3897 * last pipe, which is the copy pipe.
3899 if (continuous || !online) {
3900 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3903 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);
3914 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3915 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3916 out_frames, in_frame, NULL);
3918 err = ia_css_pipeline_create_and_add_stage(me,
3923 /* If we use copy iso preview, the input must be yuv iso raw */
3924 preview_stage->args.copy_vf =
3925 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3926 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3927 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame)
3929 /* in case of copy, use the vf frame as output frame */
3930 preview_stage->args.out_vf_frame =
3931 preview_stage->args.out_frame[0];
3935 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3936 in_frame = preview_stage->args.out_vf_frame;
3938 in_frame = preview_stage->args.out_frame[0];
3939 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3945 pipe->pipeline.acquire_isp_each_stage = false;
3946 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3949 IA_CSS_LEAVE_ERR_PRIVATE(err);
3953 static void send_raw_frames(struct ia_css_pipe *pipe)
3955 if (pipe->stream->config.continuous) {
3958 sh_css_update_host2sp_cont_num_raw_frames
3959 (pipe->stream->config.init_num_cont_raw_buf, true);
3960 sh_css_update_host2sp_cont_num_raw_frames
3961 (pipe->stream->config.target_num_cont_raw_buf, false);
3963 /* Hand-over all the SP-internal buffers */
3964 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3965 sh_css_update_host2sp_offline_frame(i,
3966 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3974 preview_start(struct ia_css_pipe *pipe) {
3975 struct ia_css_pipeline *me;
3976 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3978 struct ia_css_pipe *copy_pipe, *capture_pipe;
3979 struct ia_css_pipe *acc_pipe;
3980 enum sh_css_pipe_config_override copy_ovrd;
3981 enum ia_css_input_mode preview_pipe_input_mode;
3982 const struct ia_css_coordinate *coord = NULL;
3983 const struct ia_css_isp_parameters *params = NULL;
3985 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3986 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3988 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3992 me = &pipe->pipeline;
3994 preview_pipe_input_mode = pipe->stream->config.mode;
3996 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3997 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3998 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4000 copy_binary = &pipe->pipe_settings.preview.copy_binary;
4001 preview_binary = &pipe->pipe_settings.preview.preview_binary;
4002 if (pipe->pipe_settings.preview.vf_pp_binary.info)
4003 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4005 sh_css_metrics_start_frame();
4007 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4008 /* multi stream video needs mipi buffers */
4009 err = send_mipi_frames(pipe);
4011 IA_CSS_LEAVE_ERR_PRIVATE(err);
4015 send_raw_frames(pipe);
4018 unsigned int thread_id;
4020 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4021 copy_ovrd = 1 << thread_id;
4023 if (pipe->stream->cont_capt)
4025 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4027 copy_ovrd |= 1 << thread_id;
4032 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
4033 params = pipe->stream->isp_params_configs;
4036 /* Construct and load the copy pipe */
4037 if (pipe->stream->config.continuous)
4039 sh_css_sp_init_pipeline(©_pipe->pipeline,
4040 IA_CSS_PIPE_ID_COPY,
4041 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4043 pipe->stream->config.pixels_per_clock == 2, false,
4044 false, pipe->required_bds_factor,
4046 pipe->stream->config.mode,
4047 &pipe->stream->config.metadata_config,
4048 &pipe->stream->info.metadata_info,
4049 #if !defined(HAS_NO_INPUT_SYSTEM)
4050 pipe->stream->config.source.port.port,
4055 /* make the preview pipe start with mem mode input, copy handles
4057 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4060 /* Construct and load the capture pipe */
4061 if (pipe->stream->cont_capt)
4063 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4064 IA_CSS_PIPE_ID_CAPTURE,
4065 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4066 capture_pipe->config.default_capture_config.enable_xnr != 0,
4067 capture_pipe->stream->config.pixels_per_clock == 2,
4068 true, /* continuous */
4069 false, /* offline */
4070 capture_pipe->required_bds_factor,
4072 IA_CSS_INPUT_MODE_MEMORY,
4073 &pipe->stream->config.metadata_config,
4074 &pipe->stream->info.metadata_info,
4075 #if !defined(HAS_NO_INPUT_SYSTEM)
4076 (enum mipi_port_id)0,
4084 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4086 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
4088 pipe->stream->config.pixels_per_clock == 2,
4089 false, /* continuous */
4090 false, /* offline */
4091 pipe->required_bds_factor,
4093 IA_CSS_INPUT_MODE_MEMORY,
4096 #if !defined(HAS_NO_INPUT_SYSTEM)
4097 (enum mipi_port_id)0,
4103 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4105 IA_CSS_LEAVE_ERR_PRIVATE(err);
4110 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4111 const struct ia_css_buffer *buffer) {
4113 unsigned int thread_id;
4114 enum sh_css_queue_id queue_id;
4115 struct ia_css_pipeline *pipeline;
4116 struct ia_css_pipeline_stage *stage;
4117 struct ia_css_rmgr_vbuf_handle p_vbuf;
4118 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4119 struct sh_css_hmm_buffer ddr_buffer;
4120 enum ia_css_buffer_type buf_type;
4121 enum ia_css_pipe_id pipe_id;
4124 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4126 if ((!pipe) || (!buffer))
4128 IA_CSS_LEAVE_ERR(-EINVAL);
4132 buf_type = buffer->type;
4133 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4136 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4138 bool found_pipe = false;
4140 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4141 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4142 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4151 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4153 bool found_pipe = false;
4155 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4156 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4157 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4167 pipe_id = pipe->mode;
4169 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4171 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4172 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4173 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4174 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4175 (pipe_id >= IA_CSS_PIPE_ID_NUM))
4177 IA_CSS_LEAVE_ERR(-EINVAL);
4181 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4184 IA_CSS_LEAVE_ERR(-EINVAL);
4188 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4191 IA_CSS_LEAVE_ERR(-EINVAL);
4195 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4197 IA_CSS_LEAVE_ERR(-EINVAL);
4201 if (!sh_css_sp_is_running())
4203 IA_CSS_LOG("SP is not running!");
4204 IA_CSS_LEAVE_ERR(-EBUSY);
4205 /* SP is not running. The queues are not valid */
4209 pipeline = &pipe->pipeline;
4212 pipe_id == IA_CSS_PIPE_ID_COPY ||
4213 pipe_id == IA_CSS_PIPE_ID_ACC);
4215 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4216 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4217 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4218 ddr_buffer.timing_data = buffer->timing_data;
4220 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4222 if (!buffer->data.stats_3a) {
4223 IA_CSS_LEAVE_ERR(-EINVAL);
4226 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4227 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4228 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4230 if (!buffer->data.stats_dvs) {
4231 IA_CSS_LEAVE_ERR(-EINVAL);
4234 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4235 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4236 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA)
4238 if (!buffer->data.metadata) {
4239 IA_CSS_LEAVE_ERR(-EINVAL);
4242 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4243 ddr_buffer.payload.metadata = *buffer->data.metadata;
4244 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4245 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4246 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4247 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4248 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME))
4250 if (!buffer->data.frame) {
4251 IA_CSS_LEAVE_ERR(-EINVAL);
4254 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4255 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4256 ddr_buffer.payload.frame.flashed = 0;
4258 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4259 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4260 buf_type, buffer->data.frame->data);
4262 #if CONFIG_ON_FRAME_ENQUEUE()
4263 return_err = set_config_on_frame_enqueue(
4264 &buffer->data.frame->info,
4265 &ddr_buffer.payload.frame);
4267 IA_CSS_LEAVE_ERR(return_err);
4273 /* start of test for using rmgr for acq/rel memory */
4276 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4278 /* TODO: change next to correct pool for optimization */
4279 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4282 assert(h_vbuf->vptr != 0x0);
4284 if ((!h_vbuf) || (h_vbuf->vptr == 0x0))
4286 IA_CSS_LEAVE_ERR(-EINVAL);
4290 hmm_store(h_vbuf->vptr,
4291 (void *)(&ddr_buffer),
4292 sizeof(struct sh_css_hmm_buffer));
4293 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4294 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4295 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS))
4298 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4299 IA_CSS_LOG("pipeline is empty!");
4300 IA_CSS_LEAVE_ERR(-EINVAL);
4304 for (stage = pipeline->stages; stage; stage = stage->next) {
4305 /* The SP will read the params
4306 after it got empty 3a and dis */
4307 if (STATS_ENABLED(stage)) {
4308 /* there is a stage that needs it */
4309 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4311 (uint32_t)h_vbuf->vptr);
4314 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4315 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4316 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4317 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4318 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4319 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA))
4321 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4323 (uint32_t)h_vbuf->vptr);
4324 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4325 if (!(return_err) &&
4326 (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) {
4327 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4328 ddr_buffer.payload.frame.frame_data,
4329 queue_id, thread_id);
4336 if (sh_css_hmm_buffer_record_acquire(
4338 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4339 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4341 return_err = -EINVAL;
4342 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4347 * Tell the SP which queues are not empty,
4348 * by sending the software event.
4352 if (!sh_css_sp_is_running()) {
4353 /* SP is not running. The queues are not valid */
4354 IA_CSS_LOG("SP is not running!");
4355 IA_CSS_LEAVE_ERR(-EBUSY);
4358 return_err = ia_css_bufq_enqueue_psys_event(
4359 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4365 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4366 IA_CSS_ERROR("buffer not enqueued");
4369 IA_CSS_LEAVE("return value = %d", return_err);
4375 * TODO: Free up the hmm memory space.
4378 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4379 struct ia_css_buffer *buffer) {
4381 enum sh_css_queue_id queue_id;
4382 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
4383 struct sh_css_hmm_buffer ddr_buffer;
4384 enum ia_css_buffer_type buf_type;
4385 enum ia_css_pipe_id pipe_id;
4386 unsigned int thread_id;
4387 hrt_address kernel_ptr = 0;
4390 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4392 if ((!pipe) || (!buffer))
4394 IA_CSS_LEAVE_ERR(-EINVAL);
4398 pipe_id = pipe->mode;
4400 buf_type = buffer->type;
4402 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4404 ddr_buffer.kernel_ptr = 0;
4406 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4409 IA_CSS_LEAVE_ERR(-EINVAL);
4413 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4416 IA_CSS_LEAVE_ERR(-EINVAL);
4420 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4422 IA_CSS_LEAVE_ERR(-EINVAL);
4426 if (!sh_css_sp_is_running())
4428 IA_CSS_LOG("SP is not running!");
4429 IA_CSS_LEAVE_ERR(-EBUSY);
4430 /* SP is not running. The queues are not valid */
4434 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4435 (uint32_t *)&ddr_buffer_addr);
4439 struct ia_css_frame *frame;
4440 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4442 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4444 /* Validate the ddr_buffer_addr and buf_type */
4445 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4446 ddr_buffer_addr, buf_type);
4447 if (hmm_buffer_record) {
4448 /* valid hmm_buffer_record found. Save the kernel_ptr
4449 * for validation after performing hmm_load. The
4450 * vbuf handle and buffer_record can be released.
4452 kernel_ptr = hmm_buffer_record->kernel_ptr;
4453 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4454 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4456 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4457 ddr_buffer_addr, buf_type);
4458 IA_CSS_LEAVE_ERR(-EINVAL);
4462 hmm_load(ddr_buffer_addr,
4464 sizeof(struct sh_css_hmm_buffer));
4466 /* if the kernel_ptr is 0 or an invalid, return an error.
4467 * do not access the buffer via the kernal_ptr.
4469 if ((ddr_buffer.kernel_ptr == 0) ||
4470 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4471 IA_CSS_ERROR("kernel_ptr invalid");
4472 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4473 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4474 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4475 IA_CSS_LEAVE_ERR(-EINVAL);
4479 if (ddr_buffer.kernel_ptr != 0) {
4480 /* buffer->exp_id : all instances to be removed later once the driver change
4481 * is completed. See patch #5758 for reference */
4483 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4484 buffer->timing_data = ddr_buffer.timing_data;
4486 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4487 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4488 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4492 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4493 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4494 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4495 if ((pipe) && (pipe->stop_requested == true)) {
4496 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4497 /* free mipi frames only for old input system
4498 * for 2401 it is done in ia_css_stream_destroy call
4500 return_err = free_mipi_frames(pipe);
4502 IA_CSS_LOG("free_mipi_frames() failed");
4503 IA_CSS_LEAVE_ERR(return_err);
4507 pipe->stop_requested = false;
4510 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4511 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4512 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4513 buffer->data.frame = frame;
4514 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4515 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4516 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4517 if (ddr_buffer.payload.frame.flashed == 1)
4518 frame->flash_state =
4519 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4520 if (ddr_buffer.payload.frame.flashed == 2)
4521 frame->flash_state =
4522 IA_CSS_FRAME_FLASH_STATE_FULL;
4523 frame->valid = pipe->num_invalid_frames == 0;
4525 pipe->num_invalid_frames--;
4527 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4528 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4529 frame->planes.binary.size = frame->data_bytes;
4531 frame->planes.binary.size =
4532 sh_css_sp_get_binary_copy_size();
4535 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4536 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4537 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4538 frame->data, frame->isp_config_id, thread_id);
4542 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4543 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4544 buf_type, buffer->data.frame->data);
4547 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4548 buffer->data.stats_3a =
4549 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4550 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4551 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4552 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4554 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4555 buffer->data.stats_dvs =
4556 (struct ia_css_isp_dvs_statistics *)
4557 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4558 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4559 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4561 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4563 case IA_CSS_BUFFER_TYPE_METADATA:
4564 buffer->data.metadata =
4565 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4566 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4567 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4570 return_err = -EINVAL;
4577 * Tell the SP which queues are not full,
4578 * by sending the software event.
4582 if (!sh_css_sp_is_running()) {
4583 IA_CSS_LOG("SP is not running!");
4584 IA_CSS_LEAVE_ERR(-EBUSY);
4585 /* SP is not running. The queues are not valid */
4588 ia_css_bufq_enqueue_psys_event(
4589 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4594 IA_CSS_LEAVE("buffer=%p", buffer);
4600 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4601 * TODO: modify and move it if possible.
4603 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4604 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4605 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4606 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4607 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4609 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4610 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */
4611 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */
4612 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */
4613 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */
4614 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */
4615 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */
4616 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */
4617 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */
4618 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */
4619 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */
4620 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */
4621 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */
4622 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */
4623 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */
4624 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */
4625 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */
4626 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4630 ia_css_dequeue_event(struct ia_css_event *event) {
4631 return ia_css_dequeue_psys_event(event);
4635 ia_css_dequeue_psys_event(struct ia_css_event *event) {
4636 enum ia_css_pipe_id pipe_id = 0;
4637 u8 payload[4] = {0, 0, 0, 0};
4641 * a) use generic decoding function , same as the one used by sp.
4642 * b) group decode and dequeue into eventQueue module
4644 * We skip the IA_CSS_ENTER logging call
4645 * to avoid flooding the logs when the host application
4650 if (!sh_css_sp_is_running())
4652 /* SP is not running. The queues are not valid */
4656 /* dequeue the event (if any) from the psys event queue */
4657 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4661 IA_CSS_LOG("event dequeued from psys event queue");
4663 /* Tell the SP that we dequeued an event from the event queue. */
4664 ia_css_bufq_enqueue_psys_event(
4665 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4667 /* Events are decoded into 4 bytes of payload, the first byte
4668 * contains the sp event type. This is converted to a host enum.
4669 * TODO: can this enum conversion be eliminated */
4670 event->type = convert_event_sp_to_host_domain[payload[0]];
4671 /* Some sane default values since not all events use all fields. */
4673 event->port = MIPI_PORT0_ID;
4675 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4676 event->fw_handle = 0;
4677 event->timer_data = 0;
4678 event->timer_code = 0;
4679 event->timer_subcode = 0;
4681 if (event->type == IA_CSS_EVENT_TYPE_TIMER)
4683 /* timer event ??? get the 2nd event and decode the data into the event struct */
4685 /* 1st event: LSB 16-bit timer data and code */
4686 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4687 event->timer_code = payload[2];
4688 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4689 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4691 /* no 2nd event ??? an error */
4692 /* Putting IA_CSS_ERROR is resulting in failures in
4693 * Merrifield smoke testing */
4694 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4697 ia_css_bufq_enqueue_psys_event(
4698 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4699 event->type = convert_event_sp_to_host_domain[payload[0]];
4701 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4702 /* 2nd event data: MSB 16-bit timer and subcode */
4703 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4704 event->timer_data |= (tmp_data << 16);
4705 event->timer_subcode = payload[2];
4707 /* It's a non timer event. So clear first half of the timer event data.
4708 * If the second part of the TIMER event is not received, we discard
4709 * the first half of the timer data and process the non timer event without
4710 * affecting the flow. So the non timer event falls through
4713 event->timer_data = 0;
4714 event->timer_code = 0;
4715 event->timer_subcode = 0;
4716 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4719 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF)
4721 event->port = (enum mipi_port_id)payload[1];
4722 event->exp_id = payload[3];
4723 } 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)
4732 event->fw_assert_module_id = payload[1]; /* module */
4733 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4734 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4735 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER)
4737 /* pipe related events.
4738 * payload[1] contains the pipe_num,
4739 * payload[2] contains the pipe_id. These are different. */
4740 event->pipe = find_pipe_by_num(payload[1]);
4741 pipe_id = (enum ia_css_pipe_id)payload[2];
4742 /* Check to see if pipe still exists */
4746 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4747 /* find the capture pipe that goes with this */
4750 n = event->pipe->stream->num_pipes;
4751 for (i = 0; i < n; i++) {
4752 struct ia_css_pipe *p =
4753 event->pipe->stream->pipes[i];
4754 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4759 event->exp_id = payload[3];
4761 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4762 /* payload[3] contains the acc fw handle. */
4763 u32 stage_num = (uint32_t)payload[3];
4765 ret_err = ia_css_pipeline_get_fw_from_stage(
4766 &event->pipe->pipeline,
4770 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4778 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4780 IA_CSS_LEAVE("event_id=%d", event->type);
4786 ia_css_dequeue_isys_event(struct ia_css_event *event) {
4787 u8 payload[4] = {0, 0, 0, 0};
4790 /* We skip the IA_CSS_ENTER logging call
4791 * to avoid flooding the logs when the host application
4796 if (!sh_css_sp_is_running())
4798 /* SP is not running. The queues are not valid */
4802 err = ia_css_bufq_dequeue_isys_event(payload);
4806 IA_CSS_LOG("event dequeued from isys event queue");
4808 /* Update SP state to indicate that element was dequeued. */
4809 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4811 /* Fill return struct with appropriate info */
4812 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4813 /* EOF events are associated with a CSI port, not with a pipe */
4815 event->port = payload[1];
4816 event->exp_id = payload[3];
4818 IA_CSS_LEAVE_ERR(err);
4823 acc_start(struct ia_css_pipe *pipe)
4826 assert(pipe->stream);
4828 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4829 pipe->stream->config.mode);
4833 sh_css_pipe_start(struct ia_css_stream *stream) {
4836 struct ia_css_pipe *pipe;
4837 enum ia_css_pipe_id pipe_id;
4838 unsigned int thread_id;
4840 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4844 IA_CSS_LEAVE_ERR(-EINVAL);
4847 pipe = stream->last_pipe;
4850 IA_CSS_LEAVE_ERR(-EINVAL);
4854 pipe_id = pipe->mode;
4856 if (stream->started == true)
4858 IA_CSS_WARNING("Cannot start stream that is already started");
4859 IA_CSS_LEAVE_ERR(err);
4863 pipe->stop_requested = false;
4867 case IA_CSS_PIPE_ID_PREVIEW:
4868 err = preview_start(pipe);
4870 case IA_CSS_PIPE_ID_VIDEO:
4871 err = video_start(pipe);
4873 case IA_CSS_PIPE_ID_CAPTURE:
4874 err = capture_start(pipe);
4876 case IA_CSS_PIPE_ID_YUVPP:
4877 err = yuvpp_start(pipe);
4879 case IA_CSS_PIPE_ID_ACC:
4885 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4886 if (!stream->config.continuous)
4890 for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
4891 switch (stream->pipes[i]->mode) {
4892 case IA_CSS_PIPE_ID_PREVIEW:
4893 stream->pipes[i]->stop_requested = false;
4894 err = preview_start(stream->pipes[i]);
4896 case IA_CSS_PIPE_ID_VIDEO:
4897 stream->pipes[i]->stop_requested = false;
4898 err = video_start(stream->pipes[i]);
4900 case IA_CSS_PIPE_ID_CAPTURE:
4901 stream->pipes[i]->stop_requested = false;
4902 err = capture_start(stream->pipes[i]);
4904 case IA_CSS_PIPE_ID_YUVPP:
4905 stream->pipes[i]->stop_requested = false;
4906 err = yuvpp_start(stream->pipes[i]);
4908 case IA_CSS_PIPE_ID_ACC:
4909 stream->pipes[i]->stop_requested = false;
4910 acc_start(stream->pipes[i]);
4919 IA_CSS_LEAVE_ERR_PRIVATE(err);
4923 /* Force ISP parameter calculation after a mode change
4924 * Acceleration API examples pass NULL for stream but they
4925 * don't use ISP parameters anyway. So this should be okay.
4926 * The SP binary (jpeg) copy does not use any parameters.
4928 if (!copy_on_sp(pipe))
4930 sh_css_invalidate_params(stream);
4931 err = sh_css_param_update_isp_params(pipe,
4932 stream->isp_params_configs, true, NULL);
4934 IA_CSS_LEAVE_ERR_PRIVATE(err);
4939 ia_css_debug_pipe_graph_dump_epilogue();
4941 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4943 if (!sh_css_sp_is_running())
4945 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
4946 /* SP is not running. The queues are not valid */
4949 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4950 (uint8_t)thread_id, 0, 0);
4952 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4953 if (!stream->config.continuous)
4957 for (i = 1; i < stream->num_pipes; i++) {
4958 ia_css_pipeline_get_sp_thread_id(
4959 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4961 ia_css_bufq_enqueue_psys_event(
4962 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4963 (uint8_t)thread_id, 0, 0);
4967 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4968 if (pipe->stream->config.continuous)
4970 struct ia_css_pipe *copy_pipe = NULL;
4972 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4973 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4974 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4975 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4978 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4981 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4983 /* by the time we reach here q is initialized and handle is available.*/
4984 ia_css_bufq_enqueue_psys_event(
4985 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4986 (uint8_t)thread_id, 0, 0);
4988 if (pipe->stream->cont_capt)
4990 struct ia_css_pipe *capture_pipe = NULL;
4992 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4993 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4994 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4995 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4997 if (!capture_pipe) {
4998 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5001 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5003 /* by the time we reach here q is initialized and handle is available.*/
5004 ia_css_bufq_enqueue_psys_event(
5005 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5006 (uint8_t)thread_id, 0, 0);
5009 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
5010 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5012 struct ia_css_pipe *acc_pipe = NULL;
5014 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5017 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
5019 /* by the time we reach here q is initialized and handle is available.*/
5020 ia_css_bufq_enqueue_psys_event(
5021 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5022 (uint8_t)thread_id, 0, 0);
5026 stream->started = true;
5028 IA_CSS_LEAVE_ERR_PRIVATE(err);
5034 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5036 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5037 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5038 //my_css.cont_capt = enable;
5039 my_css.stop_copy_preview = stop_copy_preview;
5043 sh_css_continuous_is_enabled(uint8_t pipe_num)
5045 struct ia_css_pipe *pipe;
5048 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5049 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5051 pipe = find_pipe_by_num(pipe_num);
5052 continuous = pipe && pipe->stream->config.continuous;
5053 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5054 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5061 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
5062 int *buffer_depth) {
5065 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5067 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5072 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
5073 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
5075 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5077 /* ok, value allowed */
5078 stream->config.target_num_cont_raw_buf = buffer_depth;
5079 /* TODO: check what to regarding initialization */
5085 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
5086 int *buffer_depth) {
5089 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5091 *buffer_depth = stream->config.target_num_cont_raw_buf;
5096 * @brief Stop all "ia_css_pipe" instances in the target
5097 * "ia_css_stream" instance.
5099 * Refer to "Local prototypes" for more info.
5103 sh_css_pipes_stop(struct ia_css_stream *stream)
5106 struct ia_css_pipe *main_pipe;
5107 enum ia_css_pipe_id main_pipe_id;
5113 IA_CSS_LOG("stream does NOT exist!");
5118 main_pipe = stream->last_pipe;
5122 IA_CSS_LOG("main_pipe does NOT exist!");
5127 main_pipe_id = main_pipe->mode;
5128 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5131 * Stop all "ia_css_pipe" instances in this target
5132 * "ia_css_stream" instance.
5134 for (i = 0; i < stream->num_pipes; i++)
5136 /* send the "stop" request to the "ia_css_pipe" instance */
5137 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5138 stream->pipes[i]->pipeline.pipe_id);
5139 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5142 * Exit this loop if "ia_css_pipeline_request_stop()"
5143 * returns the error code.
5145 * The error code would be generated in the following
5147 * (1) The Scalar Processor has already been stopped.
5148 * (2) The "Host->SP" event queue is full.
5150 * As the convention of using CSS API 2.0/2.1, such CSS
5151 * error code would be propogated from the CSS-internal
5152 * API returned value to the CSS API returned value. Then
5153 * the CSS driver should capture these error code and
5154 * handle it in the driver exception handling mechanism.
5162 * In the CSS firmware use scenario "Continuous Preview"
5163 * as well as "Continuous Video", the "ia_css_pipe" instance
5164 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5165 * the CSS firmware so that it is not listed in the target
5166 * "ia_css_stream" instance.
5168 * We need to stop this "Copy Pipe", as well.
5170 if (main_pipe->stream->config.continuous)
5172 struct ia_css_pipe *copy_pipe = NULL;
5174 /* get the reference to "Copy Pipe" */
5175 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5176 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5177 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5178 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5180 /* return the error code if "Copy Pipe" does NOT exist */
5183 IA_CSS_LOG("Copy Pipe does NOT exist!");
5188 /* send the "stop" request to "Copy Pipe" */
5189 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5190 copy_pipe->pipeline.pipe_id);
5191 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
5195 IA_CSS_LEAVE_ERR_PRIVATE(err);
5200 * @brief Check if all "ia_css_pipe" instances in the target
5201 * "ia_css_stream" instance have stopped.
5203 * Refer to "Local prototypes" for more info.
5207 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5211 struct ia_css_pipe *main_pipe;
5212 enum ia_css_pipe_id main_pipe_id;
5218 IA_CSS_LOG("stream does NOT exist!");
5223 main_pipe = stream->last_pipe;
5227 IA_CSS_LOG("main_pipe does NOT exist!");
5232 main_pipe_id = main_pipe->mode;
5233 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5236 * Check if every "ia_css_pipe" instance in this target
5237 * "ia_css_stream" instance has stopped.
5239 for (i = 0; i < stream->num_pipes; i++) {
5240 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5241 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5242 stream->pipes[i]->pipeline.pipe_id,
5247 * In the CSS firmware use scenario "Continuous Preview"
5248 * as well as "Continuous Video", the "ia_css_pipe" instance
5249 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5250 * the CSS firmware so that it is not listed in the target
5251 * "ia_css_stream" instance.
5253 * We need to check if this "Copy Pipe" has stopped, as well.
5255 if (main_pipe->stream->config.continuous) {
5256 struct ia_css_pipe *copy_pipe = NULL;
5258 /* get the reference to "Copy Pipe" */
5259 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5260 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5261 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5262 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5264 /* return if "Copy Pipe" does NOT exist */
5267 IA_CSS_LOG("Copy Pipe does NOT exist!");
5273 /* check if "Copy Pipe" has stopped or not */
5274 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5275 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5276 copy_pipe->pipeline.pipe_id,
5281 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5285 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5287 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5289 OP___assert(port < N_CSI_PORTS);
5290 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5291 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5292 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5293 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5294 return my_css.mipi_sizes_for_check[port][idx];
5298 static int sh_css_pipe_configure_output(
5299 struct ia_css_pipe *pipe,
5301 unsigned int height,
5302 unsigned int padded_width,
5303 enum ia_css_frame_format format,
5308 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
5309 pipe, width, height, padded_width, format, idx);
5311 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5315 err = ia_css_util_check_res(width, height);
5317 IA_CSS_LEAVE_ERR_PRIVATE(err);
5320 if (pipe->output_info[idx].res.width != width ||
5321 pipe->output_info[idx].res.height != height ||
5322 pipe->output_info[idx].format != format) {
5323 ia_css_frame_info_init(
5324 &pipe->output_info[idx],
5330 IA_CSS_LEAVE_ERR_PRIVATE(0);
5335 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5336 struct ia_css_shading_info *shading_info,
5337 struct ia_css_pipe_config *pipe_config)
5340 struct ia_css_binary *binary = NULL;
5342 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5343 "sh_css_pipe_get_shading_info() enter:\n");
5345 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5349 err = ia_css_binary_get_shading_info(binary,
5350 IA_CSS_SHADING_CORRECTION_TYPE_1,
5351 pipe->required_bds_factor,
5352 (const struct ia_css_stream_config *)&pipe->stream->config,
5353 shading_info, pipe_config);
5355 /* Other function calls can be added here when other shading correction types will be added
5360 /* When the pipe does not have a binary which has the shading
5361 * correction, this function does not need to fill the shading
5362 * information. It is not a error case, and then
5363 * this function should return 0.
5365 memset(shading_info, 0, sizeof(*shading_info));
5371 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5372 struct ia_css_grid_info *info) {
5374 struct ia_css_binary *binary = NULL;
5379 IA_CSS_ENTER_PRIVATE("");
5381 binary = ia_css_pipe_get_s3a_binary(pipe);
5385 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5389 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5391 binary = ia_css_pipe_get_sdis_binary(pipe);
5395 ia_css_binary_dvs_grid_info(binary, info, pipe);
5396 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5399 memset(&info->dvs_grid.dvs_grid_info, 0,
5400 sizeof(info->dvs_grid.dvs_grid_info));
5401 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5402 sizeof(info->dvs_grid.dvs_stat_grid_info));
5407 /* copy pipe does not have ISP binary*/
5408 info->isp_in_width = binary->internal_frame_info.res.width;
5409 info->isp_in_height = binary->internal_frame_info.res.height;
5412 #if defined(HAS_VAMEM_VERSION_2)
5413 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5414 #elif defined(HAS_VAMEM_VERSION_1)
5415 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5417 #error "Unknown VAMEM version"
5421 IA_CSS_LEAVE_ERR_PRIVATE(err);
5427 * @brief Check if a format is supported by the pipe.
5431 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
5432 enum ia_css_frame_format format) {
5433 const enum ia_css_frame_format *supported_formats;
5434 int number_of_formats;
5438 IA_CSS_ENTER_PRIVATE("");
5440 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info)
5442 IA_CSS_ERROR("Pipe or binary info is not set");
5443 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5447 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5448 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
5450 for (i = 0; i < number_of_formats && !found; i++)
5452 if (supported_formats[i] == format) {
5459 IA_CSS_ERROR("Requested format is not supported by binary");
5460 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5464 IA_CSS_LEAVE_ERR_PRIVATE(0);
5469 static int load_video_binaries(struct ia_css_pipe *pipe)
5471 struct ia_css_frame_info video_in_info, tnr_info,
5472 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5475 bool continuous = pipe->stream->config.continuous;
5477 unsigned int num_output_pins;
5478 struct ia_css_frame_info video_bin_out_info;
5479 bool need_scaler = false;
5480 bool vf_res_different_than_output = false;
5481 bool need_vf_pp = false;
5483 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5485 IA_CSS_ENTER_PRIVATE("");
5487 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5488 /* we only test the video_binary because offline video doesn't need a
5489 * vf_pp binary and online does not (always use) the copy_binary.
5490 * All are always reset at the same time anyway.
5492 if (mycs->video_binary.info)
5495 online = pipe->stream->config.online;
5496 pipe_out_info = &pipe->output_info[0];
5497 pipe_vf_out_info = &pipe->vf_output_info[0];
5499 assert(pipe_out_info);
5502 * There is no explicit input format requirement for raw or yuv
5503 * What matters is that there is a binary that supports the stream format.
5504 * This is checked in the binary_find(), so no need to check it here
5506 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5509 /* cannot have online video and input_mode memory */
5510 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5512 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5513 err = ia_css_util_check_vf_out_info(pipe_out_info,
5518 err = ia_css_frame_check_info(pipe_out_info);
5523 if (pipe->out_yuv_ds_input_info.res.width)
5524 video_bin_out_info = pipe->out_yuv_ds_input_info;
5526 video_bin_out_info = *pipe_out_info;
5529 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5530 video_vf_info = pipe_vf_out_info;
5531 vf_res_different_than_output = (video_vf_info->res.width !=
5532 video_bin_out_info.res.width) ||
5533 (video_vf_info->res.height != video_bin_out_info.res.height);
5535 video_vf_info = NULL;
5538 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5540 /* we build up the pipeline starting at the end */
5541 /* YUV post-processing if needed */
5543 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5545 /* NV12 is the common format that is supported by both */
5546 /* yuv_scaler and the video_xx_isp2_min binaries. */
5547 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5549 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5550 &video_bin_out_info,
5556 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5557 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5558 sizeof(struct ia_css_binary), GFP_KERNEL);
5559 if (!mycs->yuv_scaler_binary) {
5563 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5564 * sizeof(bool), GFP_KERNEL);
5565 if (!mycs->is_output_stage) {
5569 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5570 struct ia_css_binary_descr yuv_scaler_descr;
5572 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5573 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5574 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5575 &cas_scaler_descr.out_info[i],
5576 &cas_scaler_descr.internal_out_info[i],
5577 &cas_scaler_descr.vf_info[i]);
5578 err = ia_css_binary_find(&yuv_scaler_descr,
5579 &mycs->yuv_scaler_binary[i]);
5581 kfree(mycs->is_output_stage);
5582 mycs->is_output_stage = NULL;
5586 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5590 struct ia_css_binary_descr video_descr;
5591 enum ia_css_frame_format vf_info_format;
5593 err = ia_css_pipe_get_video_binarydesc(pipe,
5594 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5596 pipe->stream->config.left_padding);
5600 /* In the case where video_vf_info is not NULL, this allows
5601 * us to find a potential video library with desired vf format.
5602 * If success, no vf_pp binary is needed.
5603 * If failed, we will look up video binary with YUV_LINE vf format
5605 err = ia_css_binary_find(&video_descr,
5606 &mycs->video_binary);
5609 if (video_vf_info) {
5610 /* This will do another video binary lookup later for YUV_LINE format*/
5614 } else if (video_vf_info) {
5615 /* The first video binary lookup is successful, but we may
5616 * still need vf_pp binary based on additiona check */
5617 num_output_pins = mycs->video_binary.info->num_output_pins;
5618 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5620 /* If the binary has dual output pins, we need vf_pp if the resolution
5622 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5624 /* If the binary has single output pin, we need vf_pp if additional
5625 * scaling is needed for vf */
5626 need_vf_pp |= ((num_output_pins == 1) &&
5627 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5628 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5632 /* save the current vf_info format for restoration later */
5633 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5634 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5636 vf_info_format = video_vf_info->format;
5638 if (!pipe->config.enable_vfpp_bci)
5639 ia_css_frame_info_set_format(video_vf_info,
5640 IA_CSS_FRAME_FORMAT_YUV_LINE);
5642 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5644 err = ia_css_binary_find(&video_descr,
5645 &mycs->video_binary);
5647 /* restore original vf_info format */
5648 ia_css_frame_info_set_format(video_vf_info,
5655 /* If a video binary does not use a ref_frame, we set the frame delay
5656 * to 0. This is the case for the 1-stage low-power video binary. */
5657 if (!mycs->video_binary.info->sp.enable.ref_frame)
5658 pipe->dvs_frame_delay = 0;
5660 /* The delay latency determines the number of invalid frames after
5661 * a stream is started. */
5662 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5663 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5665 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5666 * outputs a viewfinder output, then we need double the number of
5669 pipe->num_invalid_frames *= 2;
5671 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5672 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5673 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5675 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5676 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5678 if (!online && !continuous) {
5679 /* TODO: what exactly needs doing, prepend the copy binary to
5680 * video base this only on !online?
5682 err = load_copy_binary(pipe,
5684 &mycs->video_binary);
5692 #if !defined(HAS_OUTPUT_SYSTEM)
5693 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5694 struct ia_css_binary_descr vf_pp_descr;
5696 if (mycs->video_binary.vf_frame_info.format
5697 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5698 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5699 &mycs->video_binary.vf_frame_info,
5702 /* output from main binary is not yuv line. currently this is
5703 * possible only when bci is enabled on vfpp output */
5704 assert(pipe->config.enable_vfpp_bci == true);
5705 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5706 &mycs->video_binary.vf_frame_info,
5707 pipe_vf_out_info, NULL, NULL);
5710 err = ia_css_binary_find(&vf_pp_descr,
5711 &mycs->vf_pp_binary);
5717 err = allocate_delay_frames(pipe);
5722 if (mycs->video_binary.info->sp.enable.block_output) {
5723 unsigned int tnr_width;
5724 unsigned int tnr_height;
5726 tnr_info = mycs->video_binary.out_frame_info[0];
5729 /* Select resolution for TNR. If
5730 * output_system_in_resolution(GDC_out_resolution) is
5731 * being used, then select that as it will also be in resolution for
5732 * TNR. At present, it only make sense for Skycam */
5733 if (pipe->config.output_system_in_res.width &&
5734 pipe->config.output_system_in_res.height) {
5735 tnr_width = pipe->config.output_system_in_res.width;
5736 tnr_height = pipe->config.output_system_in_res.height;
5738 tnr_width = tnr_info.res.width;
5739 tnr_height = tnr_info.res.height;
5742 /* Make tnr reference buffers output block width(in pix) align */
5743 tnr_info.res.width = CEIL_MUL(tnr_width,
5744 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5745 tnr_info.padded_width = tnr_info.res.width;
5747 tnr_height = tnr_info.res.height;
5750 /* Make tnr reference buffers output block height align */
5751 tnr_info.res.height = CEIL_MUL(tnr_height,
5752 mycs->video_binary.info->sp.block.output_block_height);
5754 tnr_info = mycs->video_binary.internal_frame_info;
5756 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5757 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5759 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5760 if (mycs->tnr_frames[i]) {
5761 ia_css_frame_free(mycs->tnr_frames[i]);
5762 mycs->tnr_frames[i] = NULL;
5764 err = ia_css_frame_allocate_from_info(
5765 &mycs->tnr_frames[i],
5770 IA_CSS_LEAVE_PRIVATE("");
5775 unload_video_binaries(struct ia_css_pipe *pipe) {
5778 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5780 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO))
5782 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5785 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5786 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5787 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5789 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5790 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5792 kfree(pipe->pipe_settings.video.is_output_stage);
5793 pipe->pipe_settings.video.is_output_stage = NULL;
5794 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5795 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5797 IA_CSS_LEAVE_ERR_PRIVATE(0);
5801 static int video_start(struct ia_css_pipe *pipe)
5803 struct ia_css_binary *copy_binary;
5805 struct ia_css_pipe *copy_pipe, *capture_pipe;
5806 enum sh_css_pipe_config_override copy_ovrd;
5807 enum ia_css_input_mode video_pipe_input_mode;
5809 const struct ia_css_coordinate *coord = NULL;
5810 const struct ia_css_isp_parameters *params = NULL;
5812 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5813 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5814 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5818 video_pipe_input_mode = pipe->stream->config.mode;
5820 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5821 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5823 copy_binary = &pipe->pipe_settings.video.copy_binary;
5825 sh_css_metrics_start_frame();
5827 /* multi stream video needs mipi buffers */
5829 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5830 err = send_mipi_frames(pipe);
5835 send_raw_frames(pipe);
5837 unsigned int thread_id;
5839 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5840 copy_ovrd = 1 << thread_id;
5842 if (pipe->stream->cont_capt) {
5843 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5845 copy_ovrd |= 1 << thread_id;
5850 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
5851 params = pipe->stream->isp_params_configs;
5854 /* Construct and load the copy pipe */
5855 if (pipe->stream->config.continuous) {
5856 sh_css_sp_init_pipeline(©_pipe->pipeline,
5857 IA_CSS_PIPE_ID_COPY,
5858 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5860 pipe->stream->config.pixels_per_clock == 2, false,
5861 false, pipe->required_bds_factor,
5863 pipe->stream->config.mode,
5864 &pipe->stream->config.metadata_config,
5865 &pipe->stream->info.metadata_info,
5866 #if !defined(HAS_NO_INPUT_SYSTEM)
5867 pipe->stream->config.source.port.port,
5872 /* make the video pipe start with mem mode input, copy handles
5874 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5877 /* Construct and load the capture pipe */
5878 if (pipe->stream->cont_capt) {
5879 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5880 IA_CSS_PIPE_ID_CAPTURE,
5881 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5882 capture_pipe->config.default_capture_config.enable_xnr != 0,
5883 capture_pipe->stream->config.pixels_per_clock == 2,
5884 true, /* continuous */
5885 false, /* offline */
5886 capture_pipe->required_bds_factor,
5888 IA_CSS_INPUT_MODE_MEMORY,
5889 &pipe->stream->config.metadata_config,
5890 &pipe->stream->info.metadata_info,
5891 #if !defined(HAS_NO_INPUT_SYSTEM)
5892 (enum mipi_port_id)0,
5898 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5900 IA_CSS_LEAVE_ERR_PRIVATE(err);
5905 int sh_css_pipe_get_viewfinder_frame_info(
5906 struct ia_css_pipe *pipe,
5907 struct ia_css_frame_info *info,
5913 /* We could print the pointer as input arg, and the values as output */
5914 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5915 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5917 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5918 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5919 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5921 /* offline video does not generate viewfinder output */
5922 *info = pipe->vf_output_info[idx];
5924 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5925 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5926 info.res.width=%d, info.res.height=%d, \
5927 info.padded_width=%d, info.format=%d, \
5928 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5929 info->res.width, info->res.height,
5930 info->padded_width, info->format,
5931 info->raw_bit_depth, info->raw_bayer_order);
5937 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
5938 unsigned int height, unsigned int min_width,
5939 enum ia_css_frame_format format,
5943 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
5944 pipe, width, height, min_width, format, idx);
5948 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5952 err = ia_css_util_check_res(width, height);
5955 IA_CSS_LEAVE_ERR_PRIVATE(err);
5958 if (pipe->vf_output_info[idx].res.width != width ||
5959 pipe->vf_output_info[idx].res.height != height ||
5960 pipe->vf_output_info[idx].format != format)
5962 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
5965 IA_CSS_LEAVE_ERR_PRIVATE(0);
5969 static int load_copy_binaries(struct ia_css_pipe *pipe)
5974 IA_CSS_ENTER_PRIVATE("");
5976 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5977 pipe->mode == IA_CSS_PIPE_ID_COPY);
5978 if (pipe->pipe_settings.capture.copy_binary.info)
5981 err = ia_css_frame_check_info(&pipe->output_info[0]);
5985 err = verify_copy_out_frame_format(pipe);
5989 err = load_copy_binary(pipe,
5990 &pipe->pipe_settings.capture.copy_binary,
5994 IA_CSS_LEAVE_ERR_PRIVATE(err);
5998 static bool need_capture_pp(
5999 const struct ia_css_pipe *pipe)
6001 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6003 IA_CSS_ENTER_LEAVE_PRIVATE("");
6005 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6008 /* ldc and capture_pp are not supported in the same pipeline */
6009 if (need_capt_ldc(pipe) == true)
6013 /* determine whether we need to use the capture_pp binary.
6014 * This is needed for:
6016 * 2. Digital Zoom or
6017 * 3. YUV downscaling
6019 if (pipe->out_yuv_ds_input_info.res.width &&
6020 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6021 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6024 if (pipe->config.default_capture_config.enable_xnr != 0)
6027 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6028 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6029 pipe->config.enable_dz)
6035 static bool need_capt_ldc(
6036 const struct ia_css_pipe *pipe)
6038 IA_CSS_ENTER_LEAVE_PRIVATE("");
6040 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6041 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
6044 static int set_num_primary_stages(unsigned int *num,
6045 enum ia_css_pipe_version version)
6053 case IA_CSS_PIPE_VERSION_2_6_1:
6054 *num = NUM_PRIMARY_HQ_STAGES;
6056 case IA_CSS_PIPE_VERSION_2_2:
6057 case IA_CSS_PIPE_VERSION_1:
6058 *num = NUM_PRIMARY_STAGES;
6068 static int load_primary_binaries(
6069 struct ia_css_pipe *pipe)
6071 bool online = false;
6072 bool memory = false;
6073 bool continuous = false;
6074 bool need_pp = false;
6075 bool need_isp_copy_binary = false;
6076 bool need_ldc = false;
6077 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6078 bool sensor = false;
6080 struct ia_css_frame_info prim_in_info,
6082 capt_pp_out_info, vf_info,
6083 *vf_pp_in_info, *pipe_out_info,
6084 *pipe_vf_out_info, *capt_pp_in_info,
6087 struct ia_css_capture_settings *mycs;
6089 bool need_extra_yuv_scaler = false;
6090 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6092 IA_CSS_ENTER_PRIVATE("");
6094 assert(pipe->stream);
6095 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6096 pipe->mode == IA_CSS_PIPE_ID_COPY);
6098 online = pipe->stream->config.online;
6099 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6100 continuous = pipe->stream->config.continuous;
6101 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6102 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6105 mycs = &pipe->pipe_settings.capture;
6106 pipe_out_info = &pipe->output_info[0];
6107 pipe_vf_out_info = &pipe->vf_output_info[0];
6109 if (mycs->primary_binary[0].info)
6112 err = set_num_primary_stages(&mycs->num_primary_stage,
6113 pipe->config.isp_pipe_version);
6115 IA_CSS_LEAVE_ERR_PRIVATE(err);
6119 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6120 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6122 IA_CSS_LEAVE_ERR_PRIVATE(err);
6126 err = ia_css_frame_check_info(pipe_out_info);
6128 IA_CSS_LEAVE_ERR_PRIVATE(err);
6132 need_pp = need_capture_pp(pipe);
6134 /* we use the vf output info to get the primary/capture_pp binary
6135 configured for vf_veceven. It will select the closest downscaling
6137 vf_info = *pipe_vf_out_info;
6140 * WARNING: The #if def flag has been added below as a
6141 * temporary solution to solve the problem of enabling the
6142 * view finder in a single binary in a capture flow. The
6143 * vf-pp stage has been removed for Skycam in the solution
6144 * provided. The vf-pp stage should be re-introduced when
6145 * required. This should not be considered as a clean solution.
6146 * Proper investigation should be done to come up with the clean
6149 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6151 /* TODO: All this yuv_scaler and capturepp calculation logic
6152 * can be shared later. Capture_pp is also a yuv_scale binary
6153 * with extra XNR funcionality. Therefore, it can be made as the
6154 * first step of the cascade. */
6155 capt_pp_out_info = pipe->out_yuv_ds_input_info;
6156 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6157 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
6158 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6159 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6161 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6162 pipe_out_info->res);
6164 if (need_extra_yuv_scaler) {
6165 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6167 err = ia_css_pipe_create_cas_scaler_desc_single_output(
6173 IA_CSS_LEAVE_ERR_PRIVATE(err);
6176 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6177 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6178 sizeof(struct ia_css_binary), GFP_KERNEL);
6179 if (!mycs->yuv_scaler_binary) {
6181 IA_CSS_LEAVE_ERR_PRIVATE(err);
6184 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6185 sizeof(bool), GFP_KERNEL);
6186 if (!mycs->is_output_stage) {
6188 IA_CSS_LEAVE_ERR_PRIVATE(err);
6191 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6192 struct ia_css_binary_descr yuv_scaler_descr;
6194 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6195 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6196 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6197 &cas_scaler_descr.out_info[i],
6198 &cas_scaler_descr.internal_out_info[i],
6199 &cas_scaler_descr.vf_info[i]);
6200 err = ia_css_binary_find(&yuv_scaler_descr,
6201 &mycs->yuv_scaler_binary[i]);
6203 IA_CSS_LEAVE_ERR_PRIVATE(err);
6207 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6210 capt_pp_out_info = pipe->output_info[0];
6213 /* TODO Do we disable ldc for skycam */
6214 need_ldc = need_capt_ldc(pipe);
6215 if (IS_ISP2401 && need_ldc) {
6216 /* ldc and capt_pp are not supported in the same pipeline */
6217 struct ia_css_binary_descr capt_ldc_descr;
6219 ia_css_pipe_get_ldc_binarydesc(pipe,
6220 &capt_ldc_descr, &prim_out_info,
6223 err = ia_css_binary_find(&capt_ldc_descr,
6224 &mycs->capture_ldc_binary);
6226 IA_CSS_LEAVE_ERR_PRIVATE(err);
6233 /* we build up the pipeline starting at the end */
6234 /* Capture post-processing */
6236 struct ia_css_binary_descr capture_pp_descr;
6239 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6241 capt_pp_in_info = &prim_out_info;
6243 ia_css_pipe_get_capturepp_binarydesc(pipe,
6244 &capture_pp_descr, capt_pp_in_info,
6245 &capt_pp_out_info, &vf_info);
6246 err = ia_css_binary_find(&capture_pp_descr,
6247 &mycs->capture_pp_binary);
6249 IA_CSS_LEAVE_ERR_PRIVATE(err);
6254 struct ia_css_binary_descr capt_ldc_descr;
6256 ia_css_pipe_get_ldc_binarydesc(pipe,
6257 &capt_ldc_descr, &prim_out_info,
6258 &capt_ldc_out_info);
6260 err = ia_css_binary_find(&capt_ldc_descr,
6261 &mycs->capture_ldc_binary);
6263 IA_CSS_LEAVE_ERR_PRIVATE(err);
6268 prim_out_info = *pipe_out_info;
6272 for (i = 0; i < mycs->num_primary_stage; i++) {
6273 struct ia_css_frame_info *local_vf_info = NULL;
6275 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
6276 (i == mycs->num_primary_stage - 1))
6277 local_vf_info = &vf_info;
6278 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info,
6279 &prim_out_info, local_vf_info, i);
6280 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6282 IA_CSS_LEAVE_ERR_PRIVATE(err);
6287 /* Viewfinder post-processing */
6289 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
6291 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6294 * WARNING: The #if def flag has been added below as a
6295 * temporary solution to solve the problem of enabling the
6296 * view finder in a single binary in a capture flow. The
6297 * vf-pp stage has been removed for Skycam in the solution
6298 * provided. The vf-pp stage should be re-introduced when
6299 * required. Thisshould not be considered as a clean solution.
6300 * Proper * investigation should be done to come up with the clean
6303 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6304 struct ia_css_binary_descr vf_pp_descr;
6306 ia_css_pipe_get_vfpp_binarydesc(pipe,
6307 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6308 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6310 IA_CSS_LEAVE_ERR_PRIVATE(err);
6314 err = allocate_delay_frames(pipe);
6319 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6320 /* When the input system is 2401, only the Direct Sensor Mode
6321 * Offline Capture uses the ISP copy binary.
6323 need_isp_copy_binary = !online && sensor;
6325 need_isp_copy_binary = !online && !continuous && !memory;
6329 if (need_isp_copy_binary) {
6330 err = load_copy_binary(pipe,
6332 &mycs->primary_binary[0]);
6334 IA_CSS_LEAVE_ERR_PRIVATE(err);
6343 allocate_delay_frames(struct ia_css_pipe *pipe) {
6344 unsigned int num_delay_frames = 0, i = 0;
6345 unsigned int dvs_frame_delay = 0;
6346 struct ia_css_frame_info ref_info;
6348 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6349 struct ia_css_frame **delay_frames = NULL;
6351 IA_CSS_ENTER_PRIVATE("");
6355 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6360 dvs_frame_delay = pipe->dvs_frame_delay;
6362 if (dvs_frame_delay > 0)
6363 num_delay_frames = dvs_frame_delay + 1;
6367 case IA_CSS_PIPE_ID_CAPTURE: {
6368 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6373 case IA_CSS_PIPE_ID_VIDEO: {
6374 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6376 ref_info = mycs_video->video_binary.internal_frame_info;
6377 /*The ref frame expects
6379 * 2. UV plane with line interleaving, like below
6380 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6382 * This format is not YUV420(which has Y, U and V planes).
6383 * Its closer to NV12, except that the UV plane has UV
6384 * interleaving, like UVUVUVUVUVUVUVUVU...
6386 * TODO: make this ref_frame format as a separate frame format
6388 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6389 delay_frames = mycs_video->delay_frames;
6392 case IA_CSS_PIPE_ID_PREVIEW: {
6393 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6395 ref_info = mycs_preview->preview_binary.internal_frame_info;
6396 /*The ref frame expects
6398 * 2. UV plane with line interleaving, like below
6399 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6401 * This format is not YUV420(which has Y, U and V planes).
6402 * Its closer to NV12, except that the UV plane has UV
6403 * interleaving, like UVUVUVUVUVUVUVUVU...
6405 * TODO: make this ref_frame format as a separate frame format
6407 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6408 delay_frames = mycs_preview->delay_frames;
6415 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6417 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6418 for (i = 0; i < num_delay_frames; i++)
6420 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6424 IA_CSS_LEAVE_PRIVATE("");
6428 static int load_advanced_binaries(
6429 struct ia_css_pipe *pipe) {
6430 struct ia_css_frame_info pre_in_info, gdc_in_info,
6431 post_in_info, post_out_info,
6432 vf_info, *vf_pp_in_info, *pipe_out_info,
6435 bool need_isp_copy = true;
6438 IA_CSS_ENTER_PRIVATE("");
6441 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6442 pipe->mode == IA_CSS_PIPE_ID_COPY);
6443 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6445 pipe_out_info = &pipe->output_info[0];
6446 pipe_vf_out_info = &pipe->vf_output_info[0];
6448 vf_info = *pipe_vf_out_info;
6449 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6452 need_pp = need_capture_pp(pipe);
6454 ia_css_frame_info_set_format(&vf_info,
6455 IA_CSS_FRAME_FORMAT_YUV_LINE);
6457 /* we build up the pipeline starting at the end */
6458 /* Capture post-processing */
6460 struct ia_css_binary_descr capture_pp_descr;
6462 ia_css_pipe_get_capturepp_binarydesc(pipe,
6463 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6464 err = ia_css_binary_find(&capture_pp_descr,
6465 &pipe->pipe_settings.capture.capture_pp_binary);
6469 post_out_info = *pipe_out_info;
6474 struct ia_css_binary_descr post_gdc_descr;
6476 ia_css_pipe_get_post_gdc_binarydesc(pipe,
6477 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6478 err = ia_css_binary_find(&post_gdc_descr,
6479 &pipe->pipe_settings.capture.post_isp_binary);
6486 struct ia_css_binary_descr gdc_descr;
6488 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6489 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6490 err = ia_css_binary_find(&gdc_descr,
6491 &pipe->pipe_settings.capture.anr_gdc_binary);
6495 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6496 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6500 struct ia_css_binary_descr pre_gdc_descr;
6502 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6503 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6504 err = ia_css_binary_find(&pre_gdc_descr,
6505 &pipe->pipe_settings.capture.pre_isp_binary);
6509 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6510 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6512 /* Viewfinder post-processing */
6515 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6518 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6522 struct ia_css_binary_descr vf_pp_descr;
6524 ia_css_pipe_get_vfpp_binarydesc(pipe,
6525 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6526 err = ia_css_binary_find(&vf_pp_descr,
6527 &pipe->pipe_settings.capture.vf_pp_binary);
6533 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6534 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6535 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6538 load_copy_binary(pipe,
6539 &pipe->pipe_settings.capture.copy_binary,
6540 &pipe->pipe_settings.capture.pre_isp_binary);
6545 static int load_bayer_isp_binaries(
6546 struct ia_css_pipe *pipe) {
6547 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6549 struct ia_css_binary_descr pre_de_descr;
6551 IA_CSS_ENTER_PRIVATE("");
6553 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6554 pipe->mode == IA_CSS_PIPE_ID_COPY);
6555 pipe_out_info = &pipe->output_info[0];
6557 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6560 err = ia_css_frame_check_info(pipe_out_info);
6564 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6568 err = ia_css_binary_find(&pre_de_descr,
6569 &pipe->pipe_settings.capture.pre_isp_binary);
6574 static int load_low_light_binaries(
6575 struct ia_css_pipe *pipe) {
6576 struct ia_css_frame_info pre_in_info, anr_in_info,
6577 post_in_info, post_out_info,
6578 vf_info, *pipe_vf_out_info, *pipe_out_info,
6581 bool need_isp_copy = true;
6584 IA_CSS_ENTER_PRIVATE("");
6586 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6587 pipe->mode == IA_CSS_PIPE_ID_COPY);
6589 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6591 pipe_vf_out_info = &pipe->vf_output_info[0];
6592 pipe_out_info = &pipe->output_info[0];
6594 vf_info = *pipe_vf_out_info;
6595 err = ia_css_util_check_vf_out_info(pipe_out_info,
6599 need_pp = need_capture_pp(pipe);
6601 ia_css_frame_info_set_format(&vf_info,
6602 IA_CSS_FRAME_FORMAT_YUV_LINE);
6604 /* we build up the pipeline starting at the end */
6605 /* Capture post-processing */
6607 struct ia_css_binary_descr capture_pp_descr;
6609 ia_css_pipe_get_capturepp_binarydesc(pipe,
6610 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6611 err = ia_css_binary_find(&capture_pp_descr,
6612 &pipe->pipe_settings.capture.capture_pp_binary);
6616 post_out_info = *pipe_out_info;
6621 struct ia_css_binary_descr post_anr_descr;
6623 ia_css_pipe_get_post_anr_binarydesc(pipe,
6624 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6625 err = ia_css_binary_find(&post_anr_descr,
6626 &pipe->pipe_settings.capture.post_isp_binary);
6633 struct ia_css_binary_descr anr_descr;
6635 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6636 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6637 err = ia_css_binary_find(&anr_descr,
6638 &pipe->pipe_settings.capture.anr_gdc_binary);
6642 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6643 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6647 struct ia_css_binary_descr pre_anr_descr;
6649 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6650 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6651 err = ia_css_binary_find(&pre_anr_descr,
6652 &pipe->pipe_settings.capture.pre_isp_binary);
6656 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6657 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6659 /* Viewfinder post-processing */
6662 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6665 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6669 struct ia_css_binary_descr vf_pp_descr;
6671 ia_css_pipe_get_vfpp_binarydesc(pipe,
6672 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6673 err = ia_css_binary_find(&vf_pp_descr,
6674 &pipe->pipe_settings.capture.vf_pp_binary);
6680 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6681 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6682 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6685 err = load_copy_binary(pipe,
6686 &pipe->pipe_settings.capture.copy_binary,
6687 &pipe->pipe_settings.capture.pre_isp_binary);
6692 static bool copy_on_sp(struct ia_css_pipe *pipe)
6697 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6701 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6703 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6705 rval &= ((pipe->stream->config.input_config.format ==
6706 ATOMISP_INPUT_FORMAT_BINARY_8) ||
6707 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6712 static int load_capture_binaries(
6713 struct ia_css_pipe *pipe) {
6717 IA_CSS_ENTER_PRIVATE("");
6719 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6720 pipe->mode == IA_CSS_PIPE_ID_COPY);
6722 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6723 IA_CSS_LEAVE_ERR_PRIVATE(0);
6727 /* in primary, advanced,low light or bayer,
6728 the input format must be raw */
6730 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6731 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6732 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6733 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6735 IA_CSS_LEAVE_ERR_PRIVATE(err);
6738 if (copy_on_sp(pipe) &&
6739 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6740 ia_css_frame_info_init(
6741 &pipe->output_info[0],
6744 IA_CSS_FRAME_FORMAT_BINARY_8,
6746 IA_CSS_LEAVE_ERR_PRIVATE(0);
6750 switch (pipe->config.default_capture_config.mode) {
6751 case IA_CSS_CAPTURE_MODE_RAW:
6752 err = load_copy_binaries(pipe);
6753 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6755 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6758 case IA_CSS_CAPTURE_MODE_BAYER:
6759 err = load_bayer_isp_binaries(pipe);
6761 case IA_CSS_CAPTURE_MODE_PRIMARY:
6762 err = load_primary_binaries(pipe);
6764 case IA_CSS_CAPTURE_MODE_ADVANCED:
6765 err = load_advanced_binaries(pipe);
6767 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6768 err = load_low_light_binaries(pipe);
6772 IA_CSS_LEAVE_ERR_PRIVATE(err);
6776 IA_CSS_LEAVE_ERR_PRIVATE(err);
6781 unload_capture_binaries(struct ia_css_pipe *pipe) {
6784 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6786 if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY)))
6788 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6791 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6792 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6793 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6794 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6795 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6796 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6797 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6798 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6799 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6801 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6802 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6804 kfree(pipe->pipe_settings.capture.is_output_stage);
6805 pipe->pipe_settings.capture.is_output_stage = NULL;
6806 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6807 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6809 IA_CSS_LEAVE_ERR_PRIVATE(0);
6814 need_downscaling(const struct ia_css_resolution in_res,
6815 const struct ia_css_resolution out_res) {
6816 if (in_res.width > out_res.width || in_res.height > out_res.height)
6823 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
6825 struct ia_css_resolution in_res, out_res;
6827 bool need_format_conversion = false;
6829 IA_CSS_ENTER_PRIVATE("");
6831 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6833 /* TODO: make generic function */
6834 need_format_conversion =
6835 ((pipe->stream->config.input_config.format ==
6836 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6837 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6839 in_res = pipe->config.input_effective_res;
6841 if (pipe->config.enable_dz)
6844 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6847 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6848 out_res = pipe->output_info[i].res;
6850 /* A non-zero width means it is a valid output port */
6851 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6858 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6859 /* which has some hard-coded knowledge which prevents reuse of the function. */
6860 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6861 static int ia_css_pipe_create_cas_scaler_desc_single_output(
6862 struct ia_css_frame_info *cas_scaler_in_info,
6863 struct ia_css_frame_info *cas_scaler_out_info,
6864 struct ia_css_frame_info *cas_scaler_vf_info,
6865 struct ia_css_cas_binary_descr *descr) {
6867 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6869 struct ia_css_frame_info tmp_in_info;
6871 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6873 assert(cas_scaler_in_info);
6874 assert(cas_scaler_out_info);
6876 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6877 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6879 /* We assume that this function is used only for single output port case. */
6880 descr->num_output_stage = 1;
6882 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6883 cas_scaler_out_info->res.width);
6884 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6885 cas_scaler_out_info->res.height);
6886 /* use the same horizontal and vertical downscaling factor for simplicity */
6887 assert(hor_ds_factor == ver_ds_factor);
6890 while (i < hor_ds_factor) {
6892 i *= max_scale_factor_per_stage;
6895 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6897 if (!descr->in_info) {
6901 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
6902 struct ia_css_frame_info), GFP_KERNEL);
6903 if (!descr->internal_out_info) {
6907 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6909 if (!descr->out_info) {
6913 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6915 if (!descr->vf_info) {
6919 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
6920 if (!descr->is_output_stage) {
6925 tmp_in_info = *cas_scaler_in_info;
6926 for (i = 0; i < descr->num_stage; i++) {
6927 descr->in_info[i] = tmp_in_info;
6928 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6929 cas_scaler_out_info->res.width) {
6930 descr->is_output_stage[i] = true;
6931 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6932 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
6933 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
6934 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
6935 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6937 assert(i == (descr->num_stage - 1));
6938 descr->internal_out_info[i].res.width = 0;
6939 descr->internal_out_info[i].res.height = 0;
6941 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
6942 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
6943 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
6944 descr->out_info[i].format = cas_scaler_out_info->format;
6945 if (cas_scaler_vf_info) {
6946 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
6947 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
6948 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
6949 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6951 descr->vf_info[i].res.width = 0;
6952 descr->vf_info[i].res.height = 0;
6953 descr->vf_info[i].padded_width = 0;
6956 descr->is_output_stage[i] = false;
6957 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6958 max_scale_factor_per_stage;
6959 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6960 max_scale_factor_per_stage;
6961 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6962 ia_css_frame_info_init(&descr->internal_out_info[i],
6963 tmp_in_info.res.width / max_scale_factor_per_stage,
6964 tmp_in_info.res.height / max_scale_factor_per_stage,
6965 IA_CSS_FRAME_FORMAT_YUV420, 0);
6966 descr->out_info[i].res.width = 0;
6967 descr->out_info[i].res.height = 0;
6968 descr->vf_info[i].res.width = 0;
6969 descr->vf_info[i].res.height = 0;
6971 tmp_in_info = descr->internal_out_info[i];
6974 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6975 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6980 /* FIXME: merge most of this and single output version */
6981 static int ia_css_pipe_create_cas_scaler_desc(
6982 struct ia_css_pipe *pipe,
6983 struct ia_css_cas_binary_descr *descr) {
6984 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6985 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6986 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6987 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6989 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6990 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6992 unsigned int num_stages = 0;
6995 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6997 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6998 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7000 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7002 vf_out_info[i] = NULL;
7003 hor_scale_factor[i] = 0;
7004 ver_scale_factor[i] = 0;
7007 in_info.res = pipe->config.input_effective_res;
7008 in_info.padded_width = in_info.res.width;
7009 descr->num_output_stage = 0;
7010 /* Find out how much scaling we need for each output */
7011 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7012 if (pipe->output_info[i].res.width != 0) {
7013 out_info[i] = &pipe->output_info[i];
7014 if (pipe->vf_output_info[i].res.width != 0)
7015 vf_out_info[i] = &pipe->vf_output_info[i];
7016 descr->num_output_stage += 1;
7020 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7021 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7022 /* use the same horizontal and vertical scaling factor for simplicity */
7023 assert(hor_scale_factor[i] == ver_scale_factor[i]);
7027 scale_factor *= max_scale_factor_per_stage;
7028 } while (scale_factor < hor_scale_factor[i]);
7030 in_info.res = out_info[i]->res;
7034 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7037 descr->num_stage = num_stages;
7039 descr->in_info = kmalloc_array(descr->num_stage,
7040 sizeof(struct ia_css_frame_info), GFP_KERNEL);
7041 if (!descr->in_info) {
7045 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
7046 struct ia_css_frame_info), GFP_KERNEL);
7047 if (!descr->internal_out_info) {
7051 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7053 if (!descr->out_info) {
7057 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7059 if (!descr->vf_info) {
7063 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7064 if (!descr->is_output_stage) {
7069 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7072 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
7073 (out_info[i - 1]->res.height >= out_info[i]->res.height));
7078 tmp_in_info.res = pipe->config.input_effective_res;
7079 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7080 for (i = 0, j = 0; i < descr->num_stage; i++) {
7082 assert(out_info[j]);
7084 descr->in_info[i] = tmp_in_info;
7085 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
7086 out_info[j]->res.width) {
7087 descr->is_output_stage[i] = true;
7088 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7089 descr->internal_out_info[i].res.width = out_info[j]->res.width;
7090 descr->internal_out_info[i].res.height = out_info[j]->res.height;
7091 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7092 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7094 assert(i == (descr->num_stage - 1));
7095 descr->internal_out_info[i].res.width = 0;
7096 descr->internal_out_info[i].res.height = 0;
7098 descr->out_info[i].res.width = out_info[j]->res.width;
7099 descr->out_info[i].res.height = out_info[j]->res.height;
7100 descr->out_info[i].padded_width = out_info[j]->padded_width;
7101 descr->out_info[i].format = out_info[j]->format;
7102 if (vf_out_info[j]) {
7103 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7104 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7105 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7106 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7108 descr->vf_info[i].res.width = 0;
7109 descr->vf_info[i].res.height = 0;
7110 descr->vf_info[i].padded_width = 0;
7114 descr->is_output_stage[i] = false;
7115 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
7116 max_scale_factor_per_stage;
7117 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
7118 max_scale_factor_per_stage;
7119 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7120 ia_css_frame_info_init(&descr->internal_out_info[i],
7121 tmp_in_info.res.width / max_scale_factor_per_stage,
7122 tmp_in_info.res.height / max_scale_factor_per_stage,
7123 IA_CSS_FRAME_FORMAT_YUV420, 0);
7124 descr->out_info[i].res.width = 0;
7125 descr->out_info[i].res.height = 0;
7126 descr->vf_info[i].res.width = 0;
7127 descr->vf_info[i].res.height = 0;
7129 tmp_in_info = descr->internal_out_info[i];
7132 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7133 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7138 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
7140 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7141 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7142 kfree(descr->in_info);
7143 descr->in_info = NULL;
7144 kfree(descr->internal_out_info);
7145 descr->internal_out_info = NULL;
7146 kfree(descr->out_info);
7147 descr->out_info = NULL;
7148 kfree(descr->vf_info);
7149 descr->vf_info = NULL;
7150 kfree(descr->is_output_stage);
7151 descr->is_output_stage = NULL;
7152 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7153 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7157 load_yuvpp_binaries(struct ia_css_pipe *pipe) {
7159 bool need_scaler = false;
7160 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7161 struct ia_css_yuvpp_settings *mycs;
7162 struct ia_css_binary *next_binary;
7163 struct ia_css_cas_binary_descr cas_scaler_descr = { };
7165 bool need_isp_copy_binary = false;
7167 IA_CSS_ENTER_PRIVATE("");
7169 assert(pipe->stream);
7170 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7172 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7175 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7176 err = ia_css_util_check_input(&pipe->stream->config, false, false);
7180 mycs = &pipe->pipe_settings.yuvpp;
7182 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7184 if (pipe->vf_output_info[i].res.width != 0) {
7185 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7186 &pipe->vf_output_info[i]);
7190 vf_pp_in_info[i] = NULL;
7193 need_scaler = need_yuv_scaler_stage(pipe);
7195 /* we build up the pipeline starting at the end */
7196 /* Capture post-processing */
7199 struct ia_css_binary_descr yuv_scaler_descr;
7201 err = ia_css_pipe_create_cas_scaler_desc(pipe,
7205 mycs->num_output = cas_scaler_descr.num_output_stage;
7206 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
7207 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7208 sizeof(struct ia_css_binary), GFP_KERNEL);
7209 if (!mycs->yuv_scaler_binary) {
7213 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7214 sizeof(bool), GFP_KERNEL);
7215 if (!mycs->is_output_stage) {
7219 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7220 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7221 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7222 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7223 &cas_scaler_descr.out_info[i],
7224 &cas_scaler_descr.internal_out_info[i],
7225 &cas_scaler_descr.vf_info[i]);
7226 err = ia_css_binary_find(&yuv_scaler_descr,
7227 &mycs->yuv_scaler_binary[i]);
7231 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7234 mycs->num_output = 1;
7239 next_binary = &mycs->yuv_scaler_binary[0];
7245 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7248 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7249 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
7251 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7252 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7253 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7255 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7256 * _scale_binary". It would translate the input-frame to the frame formats that
7257 * are supported by the "yuv_scale_binary".
7259 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7260 * pp_defs.h" for the list of input-frame formats that are supported by the
7261 * "yuv_scale_binary".
7263 need_isp_copy_binary =
7264 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7265 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7266 need_isp_copy_binary = true;
7267 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7269 if (need_isp_copy_binary)
7271 err = load_copy_binary(pipe,
7280 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7282 * In some use cases, the first stage in the "yuvpp" pipe is the
7283 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7284 * the input from either the system DDR or from the IPU internal VMEM.
7285 * So it provides the flag "online" to specify where its input is from,
7288 * (1) "online <= true", the input is from the IPU internal VMEM.
7289 * (2) "online <= false", the input is from the system DDR.
7291 * In other use cases, the first stage in the "yuvpp" pipe is the
7292 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7293 * input ONLY from the system DDR. So it does not provide the flag "online"
7294 * to specify where its input is from.
7296 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7299 /* Viewfinder post-processing */
7302 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7303 if (mycs->is_output_stage[i]) {
7306 &mycs->yuv_scaler_binary[i].vf_frame_info;
7310 mycs->num_vf_pp = j;
7314 &mycs->copy_binary.vf_frame_info;
7315 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7316 vf_pp_in_info[i] = NULL;
7318 mycs->num_vf_pp = 1;
7320 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7322 if (!mycs->vf_pp_binary)
7329 struct ia_css_binary_descr vf_pp_descr;
7331 for (i = 0; i < mycs->num_vf_pp; i++)
7333 if (pipe->vf_output_info[i].res.width != 0) {
7334 ia_css_pipe_get_vfpp_binarydesc(pipe,
7335 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7336 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7349 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7351 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7357 unload_yuvpp_binaries(struct ia_css_pipe *pipe) {
7360 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7362 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7364 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7367 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7368 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
7370 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7372 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
7374 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7376 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7377 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7378 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7379 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7380 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7381 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7383 IA_CSS_LEAVE_ERR_PRIVATE(0);
7387 static int yuvpp_start(struct ia_css_pipe *pipe)
7389 struct ia_css_binary *copy_binary;
7391 enum sh_css_pipe_config_override copy_ovrd;
7392 enum ia_css_input_mode yuvpp_pipe_input_mode;
7394 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7395 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7396 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7400 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7402 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7404 sh_css_metrics_start_frame();
7406 /* multi stream video needs mipi buffers */
7408 #if !defined(HAS_NO_INPUT_SYSTEM) && (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401))
7409 err = send_mipi_frames(pipe);
7411 IA_CSS_LEAVE_ERR_PRIVATE(err);
7417 unsigned int thread_id;
7419 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7420 copy_ovrd = 1 << thread_id;
7423 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7425 IA_CSS_LEAVE_ERR_PRIVATE(err);
7430 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
7433 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7437 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7440 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7441 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7443 IA_CSS_LEAVE_ERR_PRIVATE(0);
7449 case IA_CSS_PIPE_ID_PREVIEW:
7450 err = unload_preview_binaries(pipe);
7452 case IA_CSS_PIPE_ID_VIDEO:
7453 err = unload_video_binaries(pipe);
7455 case IA_CSS_PIPE_ID_CAPTURE:
7456 err = unload_capture_binaries(pipe);
7458 case IA_CSS_PIPE_ID_YUVPP:
7459 err = unload_yuvpp_binaries(pipe);
7464 IA_CSS_LEAVE_ERR_PRIVATE(err);
7469 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
7473 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7475 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7476 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7481 case IA_CSS_PIPE_ID_PREVIEW:
7482 err = load_preview_binaries(pipe);
7484 case IA_CSS_PIPE_ID_VIDEO:
7485 err = load_video_binaries(pipe);
7487 case IA_CSS_PIPE_ID_CAPTURE:
7488 err = load_capture_binaries(pipe);
7490 case IA_CSS_PIPE_ID_YUVPP:
7491 err = load_yuvpp_binaries(pipe);
7493 case IA_CSS_PIPE_ID_ACC:
7501 if (sh_css_pipe_unload_binaries(pipe)) {
7502 /* currently css does not support multiple error returns in a single function,
7503 * using -EINVAL in this case */
7511 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
7512 struct ia_css_pipeline *me;
7514 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7516 *yuv_scaler_stage = NULL;
7517 struct ia_css_binary *copy_binary,
7520 bool need_scaler = false;
7521 unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7524 struct ia_css_frame *in_frame = NULL;
7525 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7526 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7527 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7528 struct ia_css_pipeline_stage_desc stage_desc;
7529 bool need_in_frameinfo_memory = false;
7530 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7531 bool sensor = false;
7532 bool buffered_sensor = false;
7533 bool online = false;
7534 bool continuous = false;
7537 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7538 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7540 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7543 me = &pipe->pipeline;
7544 ia_css_pipeline_clean(me);
7545 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7547 out_frame[i] = NULL;
7550 ia_css_pipe_util_create_output_frames(bin_out_frame);
7551 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7552 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp;
7553 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7555 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7556 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7557 * except for the following:
7558 * - Direct Sensor Mode Online Capture
7559 * - Direct Sensor Mode Continuous Capture
7560 * - Buffered Sensor Mode Continuous Capture
7562 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7563 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7564 online = pipe->stream->config.online;
7565 continuous = pipe->stream->config.continuous;
7566 need_in_frameinfo_memory =
7567 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7569 /* Construct in_frame info (only in case we have dynamic input */
7570 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7572 /* the input frame can come from:
7573 * a) memory: connect yuvscaler to me->in_frame
7574 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7575 if (need_in_frameinfo_memory)
7577 /* TODO: improve for different input formats. */
7580 * "pipe->stream->config.input_config.format" represents the sensor output
7581 * frame format, e.g. YUV422 8-bit.
7583 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7586 int in_frame_format;
7588 if (pipe->stream->config.input_config.format ==
7589 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7590 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7591 } else if (pipe->stream->config.input_config.format ==
7592 ATOMISP_INPUT_FORMAT_YUV422_8) {
7594 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
7595 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7598 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7599 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7601 * By now, the "isp_copy_var" binary does NOT provide a separated
7602 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7603 * the YUV422-8 pixels in the frame-line buffer which is designed to
7604 * store the Bayer-Quad RAW pixels.
7606 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7607 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7610 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7612 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7615 err = init_in_frameinfo_memory_defaults(pipe,
7620 IA_CSS_LEAVE_ERR_PRIVATE(err);
7624 in_frame = &me->in_frame;
7630 for (i = 0; i < num_output_stage; i++)
7632 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7633 if (pipe->output_info[i].res.width != 0) {
7634 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7636 IA_CSS_LEAVE_ERR_PRIVATE(err);
7639 out_frame[i] = &me->out_frame[i];
7642 /* Construct vf_frame info (only in case we have VF) */
7643 if (pipe->vf_output_info[i].res.width != 0) {
7644 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7646 IA_CSS_LEAVE_ERR_PRIVATE(err);
7649 vf_frame[i] = &me->vf_frame[i];
7653 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7654 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7655 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7656 need_scaler = need_yuv_scaler_stage(pipe);
7658 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7660 struct ia_css_frame *in_frame_local = NULL;
7662 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7663 /* After isp copy is enabled in_frame needs to be passed. */
7665 in_frame_local = in_frame;
7669 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7670 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7671 bin_out_frame, in_frame_local, NULL);
7673 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7674 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7675 bin_out_frame, in_frame_local, NULL);
7678 err = ia_css_pipeline_create_and_add_stage(me,
7683 IA_CSS_LEAVE_ERR_PRIVATE(err);
7688 /* if we use yuv scaler binary, vf output should be from there */
7689 copy_stage->args.copy_vf = !need_scaler;
7690 /* for yuvpp pipe, it should always be enabled */
7691 copy_stage->args.copy_output = true;
7692 /* connect output of copy binary to input of yuv scaler */
7693 in_frame = copy_stage->args.out_frame[0];
7699 struct ia_css_frame *tmp_out_frame = NULL;
7700 struct ia_css_frame *tmp_vf_frame = NULL;
7701 struct ia_css_frame *tmp_in_frame = in_frame;
7703 for (i = 0, j = 0; i < num_stage; i++) {
7704 assert(j < num_output_stage);
7705 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7706 tmp_out_frame = out_frame[j];
7707 tmp_vf_frame = vf_frame[j];
7709 tmp_out_frame = NULL;
7710 tmp_vf_frame = NULL;
7713 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7715 &yuv_scaler_binary[i],
7719 IA_CSS_LEAVE_ERR_PRIVATE(err);
7722 /* we use output port 1 as internal output port */
7723 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7724 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7725 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7726 in_frame = yuv_scaler_stage->args.out_vf_frame;
7727 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7731 IA_CSS_LEAVE_ERR_PRIVATE(err);
7738 } else if (copy_stage)
7740 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7741 in_frame = copy_stage->args.out_vf_frame;
7742 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7746 IA_CSS_LEAVE_ERR_PRIVATE(err);
7751 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7753 IA_CSS_LEAVE_ERR_PRIVATE(0);
7759 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7760 unsigned int max_input_width,
7761 struct ia_css_frame *out_frame) {
7762 struct ia_css_pipeline *me;
7764 struct ia_css_pipeline_stage_desc stage_desc;
7766 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7767 "create_host_copy_pipeline() enter:\n");
7769 /* pipeline already created as part of create_host_pipeline_structure */
7770 me = &pipe->pipeline;
7771 ia_css_pipeline_clean(me);
7773 /* Construct out_frame info */
7774 out_frame->contiguous = false;
7775 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7777 if (copy_on_sp(pipe) &&
7778 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
7780 ia_css_frame_info_init(
7784 IA_CSS_FRAME_FORMAT_BINARY_8,
7786 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW)
7788 out_frame->info.raw_bit_depth =
7789 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7793 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7794 pipe->mode = IA_CSS_PIPE_ID_COPY;
7796 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7797 IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7798 err = ia_css_pipeline_create_and_add_stage(me,
7802 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7804 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7805 "create_host_copy_pipeline() leave:\n");
7811 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
7812 struct ia_css_pipeline *me = &pipe->pipeline;
7814 struct ia_css_pipeline_stage_desc stage_desc;
7815 struct ia_css_frame *out_frame = &me->out_frame[0];
7816 struct ia_css_pipeline_stage *out_stage = NULL;
7817 unsigned int thread_id;
7818 enum sh_css_queue_id queue_id;
7819 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7821 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7822 "create_host_isyscopy_capture_pipeline() enter:\n");
7823 ia_css_pipeline_clean(me);
7825 /* Construct out_frame info */
7826 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7829 out_frame->contiguous = false;
7830 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7831 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7832 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7833 out_frame->dynamic_queue_id = queue_id;
7834 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7837 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7838 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7839 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7840 IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7841 err = ia_css_pipeline_create_and_add_stage(me,
7842 &stage_desc, &out_stage);
7846 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7848 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7849 "create_host_isyscopy_capture_pipeline() leave:\n");
7855 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
7856 struct ia_css_pipeline *me;
7858 enum ia_css_capture_mode mode;
7859 struct ia_css_pipeline_stage *current_stage = NULL;
7860 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7861 struct ia_css_binary *copy_binary,
7862 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7869 *capture_ldc_binary;
7870 bool need_pp = false;
7873 struct ia_css_frame *in_frame;
7874 struct ia_css_frame *out_frame;
7875 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7876 struct ia_css_frame *vf_frame;
7877 struct ia_css_pipeline_stage_desc stage_desc;
7878 bool need_in_frameinfo_memory = false;
7879 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7880 bool sensor = false;
7881 bool buffered_sensor = false;
7882 bool online = false;
7883 bool continuous = false;
7885 unsigned int i, num_yuv_scaler, num_primary_stage;
7886 bool need_yuv_pp = false;
7887 bool *is_output_stage = NULL;
7888 bool need_ldc = false;
7890 IA_CSS_ENTER_PRIVATE("");
7892 assert(pipe->stream);
7893 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7895 me = &pipe->pipeline;
7896 mode = pipe->config.default_capture_config.mode;
7897 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7898 ia_css_pipeline_clean(me);
7899 ia_css_pipe_util_create_output_frames(out_frames);
7901 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7902 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7903 * except for the following:
7904 * - Direct Sensor Mode Online Capture
7905 * - Direct Sensor Mode Online Capture
7906 * - Direct Sensor Mode Continuous Capture
7907 * - Buffered Sensor Mode Continuous Capture
7909 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7910 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7911 online = pipe->stream->config.online;
7912 continuous = pipe->stream->config.continuous;
7913 need_in_frameinfo_memory =
7914 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7916 /* Construct in_frame info (only in case we have dynamic input */
7917 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7919 if (need_in_frameinfo_memory)
7921 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
7922 IA_CSS_FRAME_FORMAT_RAW);
7924 IA_CSS_LEAVE_ERR_PRIVATE(err);
7928 in_frame = &me->in_frame;
7934 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7937 IA_CSS_LEAVE_ERR_PRIVATE(err);
7940 out_frame = &me->out_frame[0];
7942 /* Construct vf_frame info (only in case we have VF) */
7943 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
7945 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7946 /* These modes don't support viewfinder output */
7949 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7950 vf_frame = &me->vf_frame[0];
7957 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7958 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7959 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY))
7961 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7964 for (i = 0; i < num_primary_stage; i++)
7966 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7968 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7969 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7970 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
7971 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
7972 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
7973 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
7974 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
7975 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
7976 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
7978 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
7979 mode != IA_CSS_CAPTURE_MODE_RAW &&
7980 mode != IA_CSS_CAPTURE_MODE_BAYER;
7981 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
7982 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
7984 if (pipe->pipe_settings.capture.copy_binary.info)
7987 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7988 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
7990 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7991 out_frames, in_frame, NULL);
7993 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7994 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7995 out_frames, in_frame, NULL);
7998 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7999 out_frames, NULL, NULL);
8002 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
8003 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8004 out_frames, NULL, NULL);
8007 err = ia_css_pipeline_create_and_add_stage(me,
8011 IA_CSS_LEAVE_ERR_PRIVATE(err);
8014 } else if (pipe->stream->config.continuous)
8016 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8019 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY)
8021 struct ia_css_frame *local_in_frame = NULL;
8022 struct ia_css_frame *local_out_frame = NULL;
8024 for (i = 0; i < num_primary_stage; i++) {
8026 local_in_frame = in_frame;
8028 local_in_frame = NULL;
8030 if (!need_pp && (i == num_primary_stage - 1))
8032 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8034 local_out_frame = out_frame;
8036 local_out_frame = NULL;
8037 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8039 * WARNING: The #if def flag has been added below as a
8040 * temporary solution to solve the problem of enabling the
8041 * view finder in a single binary in a capture flow. The
8042 * vf-pp stage has been removed from Skycam in the solution
8043 * provided. The vf-pp stage should be re-introduced when
8044 * required. This * should not be considered as a clean solution.
8045 * Proper investigation should be done to come up with the clean
8048 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8049 out_frames, local_in_frame, NULL);
8050 err = ia_css_pipeline_create_and_add_stage(me,
8054 IA_CSS_LEAVE_ERR_PRIVATE(err);
8058 /* If we use copy iso primary,
8059 the input must be yuv iso raw */
8060 current_stage->args.copy_vf =
8061 primary_binary[0]->info->sp.pipeline.mode ==
8062 IA_CSS_BINARY_MODE_COPY;
8063 current_stage->args.copy_output = current_stage->args.copy_vf;
8064 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8065 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT)
8067 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8068 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8069 out_frames, in_frame, NULL);
8070 err = ia_css_pipeline_create_and_add_stage(me,
8073 IA_CSS_LEAVE_ERR_PRIVATE(err);
8076 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8077 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8078 out_frames, NULL, NULL);
8079 err = ia_css_pipeline_create_and_add_stage(me,
8082 IA_CSS_LEAVE_ERR_PRIVATE(err);
8087 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8088 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8089 out_frames, NULL, NULL);
8091 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8092 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8093 out_frames, NULL, NULL);
8096 err = ia_css_pipeline_create_and_add_stage(me,
8097 &stage_desc, ¤t_stage);
8099 IA_CSS_LEAVE_ERR_PRIVATE(err);
8102 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER)
8104 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8105 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8106 out_frames, in_frame, NULL);
8107 err = ia_css_pipeline_create_and_add_stage(me,
8111 IA_CSS_LEAVE_ERR_PRIVATE(err);
8117 if (need_pp && current_stage)
8119 struct ia_css_frame *local_in_frame = NULL;
8121 local_in_frame = current_stage->args.out_frame[0];
8124 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8125 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8126 out_frames, local_in_frame, NULL);
8127 err = ia_css_pipeline_create_and_add_stage(me,
8130 local_in_frame = current_stage->args.out_frame[0];
8132 err = add_capture_pp_stage(pipe, me, local_in_frame,
8133 need_yuv_pp ? NULL : out_frame,
8135 /* ldc and capture_pp not supported in same pipeline */
8136 if (need_ldc && current_stage)
8138 in_frame = current_stage->args.out_frame[0];
8139 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8140 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8141 out_frames, in_frame, NULL);
8142 err = ia_css_pipeline_create_and_add_stage(me,
8145 } else if (need_pp && current_stage)
8147 in_frame = current_stage->args.out_frame[0];
8148 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8153 IA_CSS_LEAVE_ERR_PRIVATE(err);
8158 if (need_yuv_pp && current_stage)
8160 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8161 struct ia_css_frame *tmp_out_frame = NULL;
8163 for (i = 0; i < num_yuv_scaler; i++) {
8164 if (is_output_stage[i] == true)
8165 tmp_out_frame = out_frame;
8167 tmp_out_frame = NULL;
8169 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8171 &yuv_scaler_binary[i],
8174 IA_CSS_LEAVE_ERR_PRIVATE(err);
8177 /* we use output port 1 as internal output port */
8178 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8183 * WARNING: The #if def flag has been added below as a
8184 * temporary solution to solve the problem of enabling the
8185 * view finder in a single binary in a capture flow. The vf-pp
8186 * stage has been removed from Skycam in the solution provided.
8187 * The vf-pp stage should be re-introduced when required. This
8188 * should not be considered as a clean solution. Proper
8189 * investigation should be done to come up with the clean solution.
8191 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame)
8193 in_frame = current_stage->args.out_vf_frame;
8194 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8197 IA_CSS_LEAVE_ERR_PRIVATE(err);
8201 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8203 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8204 "create_host_regular_capture_pipeline() leave:\n");
8210 create_host_capture_pipeline(struct ia_css_pipe *pipe) {
8213 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8215 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8216 err = create_host_isyscopy_capture_pipeline(pipe);
8218 err = create_host_regular_capture_pipeline(pipe);
8221 IA_CSS_LEAVE_ERR_PRIVATE(err);
8225 IA_CSS_LEAVE_ERR_PRIVATE(err);
8230 static int capture_start(
8231 struct ia_css_pipe *pipe) {
8232 struct ia_css_pipeline *me;
8235 enum sh_css_pipe_config_override copy_ovrd;
8237 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8239 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8243 me = &pipe->pipeline;
8245 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8246 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
8247 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8248 if (copy_on_sp(pipe)) {
8249 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8250 IA_CSS_LEAVE_ERR_PRIVATE(err);
8255 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8256 /* old isys: need to send_mipi_frames() in all pipe modes */
8257 err = send_mipi_frames(pipe);
8259 IA_CSS_LEAVE_ERR_PRIVATE(err);
8262 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8263 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8264 err = send_mipi_frames(pipe);
8266 IA_CSS_LEAVE_ERR_PRIVATE(err);
8274 unsigned int thread_id;
8276 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8277 copy_ovrd = 1 << thread_id;
8279 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8281 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8283 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8284 * which is currently done in start_binary(); but COPY pipe contains no binary,
8285 * and does not call start_binary(); so we need to configure the rx here.
8287 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
8288 pipe->stream->reconfigure_css_rx) {
8289 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
8290 pipe->stream->config.mode);
8291 pipe->stream->reconfigure_css_rx = false;
8295 IA_CSS_LEAVE_ERR_PRIVATE(err);
8300 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8301 struct ia_css_frame_info *info,
8306 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8307 "sh_css_pipe_get_output_frame_info() enter:\n");
8309 *info = pipe->output_info[idx];
8310 if (copy_on_sp(pipe) &&
8311 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
8313 ia_css_frame_info_init(
8317 IA_CSS_FRAME_FORMAT_BINARY_8,
8319 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8320 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
8322 info->raw_bit_depth =
8323 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8326 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8327 "sh_css_pipe_get_output_frame_info() leave:\n");
8331 #if !defined(HAS_NO_INPUT_SYSTEM)
8333 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8334 const unsigned short *data,
8336 unsigned int height) {
8339 ia_css_inputfifo_send_input_frame(
8340 data, width, height,
8341 stream->config.channel_id,
8342 stream->config.input_config.format,
8343 stream->config.pixels_per_clock == 2);
8347 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
8350 ia_css_inputfifo_start_frame(
8351 stream->config.channel_id,
8352 stream->config.input_config.format,
8353 stream->config.pixels_per_clock == 2);
8357 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8358 const unsigned short *data,
8360 const unsigned short *data2,
8361 unsigned int width2) {
8364 ia_css_inputfifo_send_line(stream->config.channel_id,
8365 data, width, data2, width2);
8369 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8370 enum atomisp_input_format format,
8371 const unsigned short *data,
8372 unsigned int width) {
8374 if (!data || width == 0)
8376 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8377 format, data, width);
8381 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) {
8384 ia_css_inputfifo_end_frame(stream->config.channel_id);
8389 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8390 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
8392 IA_CSS_ERROR("NULL fw_info");
8393 IA_CSS_LEAVE_PRIVATE("");
8399 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8400 IA_CSS_LEAVE_PRIVATE("");
8404 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8409 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8411 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8412 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8415 static int upload_isp_code(struct ia_css_fw_info *firmware)
8420 IA_CSS_ERROR("NULL input parameter");
8423 binary = firmware->info.isp.xmem_addr;
8426 unsigned int size = firmware->blob.size;
8427 const unsigned char *blob;
8428 const unsigned char *binary_name;
8431 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8433 blob = binary_name +
8434 strlen((const char *)binary_name) +
8436 binary = sh_css_load_blob(blob, size);
8437 firmware->info.isp.xmem_addr = binary;
8446 acc_load_extension(struct ia_css_fw_info *firmware) {
8448 struct ia_css_fw_info *hd = firmware;
8452 err = upload_isp_code(hd);
8460 firmware->loaded = true;
8465 acc_unload_extension(struct ia_css_fw_info *firmware) {
8466 struct ia_css_fw_info *hd = firmware;
8467 struct ia_css_fw_info *hdn = NULL;
8469 if (!firmware) /* should not happen */
8471 /* unload and remove multiple firmwares */
8473 hdn = (hd->next) ? &(*hd->next) : NULL;
8474 if (hd->info.isp.xmem_addr) {
8475 hmm_free(hd->info.isp.xmem_addr);
8476 hd->info.isp.xmem_addr = mmgr_NULL;
8478 hd->isp_code = NULL;
8483 firmware->loaded = false;
8486 /* Load firmware for extension */
8488 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8489 struct ia_css_fw_info *firmware) {
8492 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8494 if ((!firmware) || (!pipe))
8496 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8500 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8501 append_firmware(&pipe->output_stage, firmware);
8502 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8503 append_firmware(&pipe->vf_stage, firmware);
8504 err = acc_load_extension(firmware);
8506 IA_CSS_LEAVE_ERR_PRIVATE(err);
8510 /* Unload firmware for extension */
8512 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8513 struct ia_css_fw_info *firmware) {
8514 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8516 if ((!firmware) || (!pipe)) {
8517 IA_CSS_ERROR("NULL input parameters");
8518 IA_CSS_LEAVE_PRIVATE("");
8522 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8523 remove_firmware(&pipe->output_stage, firmware);
8524 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8525 remove_firmware(&pipe->vf_stage, firmware);
8526 acc_unload_extension(firmware);
8528 IA_CSS_LEAVE_PRIVATE("");
8532 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
8533 struct ia_css_pipeline_stage *stage;
8537 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8538 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8540 for (stage = me->stages; stage; stage = stage->next)
8541 if (stage->binary_info && stage->binary_info->enable.params) {
8542 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8543 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
8546 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8547 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8552 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8553 const void *acc_fw) {
8554 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8555 /* In QoS case, load_extension already called, so skipping */
8558 if (fw->loaded == false)
8559 err = acc_load_extension(fw);
8561 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8562 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
8567 struct ia_css_pipeline_stage_desc stage_desc;
8569 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8570 err = ia_css_pipeline_create_and_add_stage(pipeline,
8575 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8576 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
8581 * @brief Tag a specific frame in continuous capture.
8582 * Refer to "sh_css_internal.h" for details.
8584 int ia_css_stream_capture_frame(struct ia_css_stream *stream,
8585 unsigned int exp_id) {
8586 struct sh_css_tag_descr tag_descr;
8587 u32 encoded_tag_descr;
8591 IA_CSS_ENTER("exp_id=%d", exp_id);
8593 /* Only continuous streams have a tagger */
8594 if (exp_id == 0 || !stream->config.continuous) {
8595 IA_CSS_LEAVE_ERR(-EINVAL);
8599 if (!sh_css_sp_is_running()) {
8600 /* SP is not running. The queues are not valid */
8601 IA_CSS_LEAVE_ERR(-EBUSY);
8605 /* Create the tag descriptor from the parameters */
8606 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8607 /* Encode the tag descriptor into a 32-bit value */
8608 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8609 /* Enqueue the encoded tag to the host2sp queue.
8610 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8611 * on both host and the SP side.
8612 * It is mainly because it is enough to have only one tag_cmd queue */
8613 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8615 IA_CSS_LEAVE_ERR(err);
8620 * @brief Configure the continuous capture.
8621 * Refer to "sh_css_internal.h" for details.
8623 int ia_css_stream_capture(
8624 struct ia_css_stream *stream,
8628 struct sh_css_tag_descr tag_descr;
8629 unsigned int encoded_tag_descr;
8635 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8636 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8637 num_captures, skip, offset);
8639 /* Check if the tag descriptor is valid */
8640 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8641 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8642 "ia_css_stream_capture() leave: return_err=%d\n",
8647 /* Create the tag descriptor from the parameters */
8648 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8650 /* Encode the tag descriptor into a 32-bit value */
8651 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8653 if (!sh_css_sp_is_running()) {
8654 /* SP is not running. The queues are not valid */
8655 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8656 "ia_css_stream_capture() leaving:queues unavailable\n");
8660 /* Enqueue the encoded tag to the host2sp queue.
8661 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8662 * on both host and the SP side.
8663 * It is mainly because it is enough to have only one tag_cmd queue */
8664 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8666 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8667 "ia_css_stream_capture() leave: return_err=%d\n",
8673 void ia_css_stream_request_flash(struct ia_css_stream *stream)
8678 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8679 "ia_css_stream_request_flash() enter: void\n");
8682 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8684 if (sh_css_sp_is_running()) {
8685 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8686 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8687 ia_css_debug_dump_sp_sw_debug_info();
8688 ia_css_debug_dump_debug_info(NULL);
8691 IA_CSS_LOG("SP is not running!");
8694 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8695 "ia_css_stream_request_flash() leave: return_void\n");
8699 sh_css_init_host_sp_control_vars(void) {
8700 const struct ia_css_fw_info *fw;
8701 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8703 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8704 unsigned int HIVE_ADDR_sp_sleep_mode;
8705 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8707 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8709 unsigned int HIVE_ADDR_host_sp_com;
8710 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8713 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8717 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8718 "sh_css_init_host_sp_control_vars() enter: void\n");
8721 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8723 HIVE_ADDR_host_sp_queues_initialized =
8724 fw->info.sp.host_sp_queues_initialized;
8725 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8726 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8728 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8730 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8732 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8734 (void)HIVE_ADDR_sp_sleep_mode;
8735 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8737 (void)HIVE_ADDR_sp_stop_copy_preview;
8739 (void)HIVE_ADDR_host_sp_com;
8741 sp_dmem_store_uint32(SP0_ID,
8742 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8745 sp_dmem_store_uint32(SP0_ID,
8746 (unsigned int)sp_address_of(host_sp_queues_initialized),
8748 sp_dmem_store_uint32(SP0_ID,
8749 (unsigned int)sp_address_of(sp_sleep_mode),
8751 sp_dmem_store_uint32(SP0_ID,
8752 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8755 sp_dmem_store_uint32(SP0_ID,
8756 (unsigned int)sp_address_of(sp_stop_copy_preview),
8757 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8759 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8761 #if !defined(HAS_NO_INPUT_SYSTEM)
8762 for (i = 0; i < N_CSI_PORTS; i++) {
8763 sh_css_update_host2sp_num_mipi_frames
8764 (my_css.num_mipi_frames[i]);
8768 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8769 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8773 * create the internal structures and fill in the configuration data
8777 ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG;
8779 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8781 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8782 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config));
8786 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
8788 if (!extra_config) {
8789 IA_CSS_ERROR("NULL input parameter");
8793 extra_config->enable_raw_binning = false;
8794 extra_config->enable_yuv_ds = false;
8795 extra_config->enable_high_speed = false;
8796 extra_config->enable_dvs_6axis = false;
8797 extra_config->enable_reduced_pipe = false;
8798 extra_config->disable_vf_pp = false;
8799 extra_config->enable_fractional_ds = false;
8802 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8804 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8805 assert(stream_config);
8806 memset(stream_config, 0, sizeof(*stream_config));
8807 stream_config->online = true;
8808 stream_config->left_padding = -1;
8809 stream_config->pixels_per_clock = 1;
8810 /* temporary default value for backwards compatibility.
8811 * This field used to be hardcoded within CSS but this has now
8812 * been moved to the stream_config struct. */
8813 stream_config->source.port.rxcount = 0x04040404;
8817 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
8822 IA_CSS_ERROR("NULL input parameter");
8826 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8827 if (pipe->config.acc_num_execs == 0)
8828 pipe->config.acc_num_execs = 1;
8830 if (pipe->config.acc_extension)
8832 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8839 ia_css_pipe_create(const struct ia_css_pipe_config *config,
8840 struct ia_css_pipe **pipe) {
8846 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8850 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8860 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8864 return ia_css_pipe_create_extra(config, NULL, pipe);
8868 err = ia_css_pipe_create_extra(config, NULL, pipe);
8872 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8875 IA_CSS_LEAVE_ERR_PRIVATE(err);
8882 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8883 const struct ia_css_pipe_extra_config *extra_config,
8884 struct ia_css_pipe **pipe) {
8886 struct ia_css_pipe *internal_pipe = NULL;
8889 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8891 /* do not allow to create more than the maximum limit */
8892 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX)
8894 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
8898 if ((!pipe) || (!config))
8900 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8904 ia_css_debug_dump_pipe_config(config);
8905 ia_css_debug_dump_pipe_extra_config(extra_config);
8907 err = create_pipe(config->mode, &internal_pipe, false);
8910 IA_CSS_LEAVE_ERR_PRIVATE(err);
8914 /* now we have a pipe structure to fill */
8915 internal_pipe->config = *config;
8917 internal_pipe->extra_config = *extra_config;
8919 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8921 if (config->mode == IA_CSS_PIPE_MODE_ACC)
8923 /* Temporary hack to migrate acceleration to CSS 2.0.
8924 * In the future the code for all pipe types should be
8926 *pipe = internal_pipe;
8927 if (!internal_pipe->config.acc_extension &&
8928 internal_pipe->config.num_acc_stages ==
8929 0) { /* if no acc binary and no standalone stage */
8931 IA_CSS_LEAVE_ERR_PRIVATE(0);
8934 return ia_css_acc_pipe_create(internal_pipe);
8937 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8938 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8939 internal_pipe->dvs_frame_delay = 2;
8941 internal_pipe->dvs_frame_delay = 1;
8943 /* we still keep enable_raw_binning for backward compatibility, for any new
8944 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8945 specified, bayer_ds_out_res will take precedence.if none is specified, we
8946 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8947 sensor output) or use default decimation factor 1. */
8948 if (internal_pipe->extra_config.enable_raw_binning &&
8949 internal_pipe->config.bayer_ds_out_res.width)
8951 /* fill some code here, if no code is needed, please remove it during integration */
8954 /* YUV downscaling */
8955 if ((internal_pipe->config.vf_pp_in_res.width ||
8956 internal_pipe->config.capt_pp_in_res.width))
8958 enum ia_css_frame_format format;
8960 if (internal_pipe->config.vf_pp_in_res.width) {
8961 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8962 ia_css_frame_info_init(
8963 &internal_pipe->vf_yuv_ds_input_info,
8964 internal_pipe->config.vf_pp_in_res.width,
8965 internal_pipe->config.vf_pp_in_res.height,
8968 if (internal_pipe->config.capt_pp_in_res.width) {
8969 format = IA_CSS_FRAME_FORMAT_YUV420;
8970 ia_css_frame_info_init(
8971 &internal_pipe->out_yuv_ds_input_info,
8972 internal_pipe->config.capt_pp_in_res.width,
8973 internal_pipe->config.capt_pp_in_res.height,
8977 if (internal_pipe->config.vf_pp_in_res.width &&
8978 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
8980 ia_css_frame_info_init(
8981 &internal_pipe->vf_yuv_ds_input_info,
8982 internal_pipe->config.vf_pp_in_res.width,
8983 internal_pipe->config.vf_pp_in_res.height,
8984 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
8986 /* handle bayer downscaling output info */
8987 if (internal_pipe->config.bayer_ds_out_res.width)
8989 ia_css_frame_info_init(
8990 &internal_pipe->bds_output_info,
8991 internal_pipe->config.bayer_ds_out_res.width,
8992 internal_pipe->config.bayer_ds_out_res.height,
8993 IA_CSS_FRAME_FORMAT_RAW, 0);
8996 /* handle output info, assume always needed */
8997 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
8999 if (internal_pipe->config.output_info[i].res.width) {
9000 err = sh_css_pipe_configure_output(
9002 internal_pipe->config.output_info[i].res.width,
9003 internal_pipe->config.output_info[i].res.height,
9004 internal_pipe->config.output_info[i].padded_width,
9005 internal_pipe->config.output_info[i].format,
9008 IA_CSS_LEAVE_ERR_PRIVATE(err);
9009 kvfree(internal_pipe);
9010 internal_pipe = NULL;
9015 /* handle vf output info, when configured */
9016 internal_pipe->enable_viewfinder[i] =
9017 (internal_pipe->config.vf_output_info[i].res.width != 0);
9018 if (internal_pipe->config.vf_output_info[i].res.width) {
9019 err = sh_css_pipe_configure_viewfinder(
9021 internal_pipe->config.vf_output_info[i].res.width,
9022 internal_pipe->config.vf_output_info[i].res.height,
9023 internal_pipe->config.vf_output_info[i].padded_width,
9024 internal_pipe->config.vf_output_info[i].format,
9027 IA_CSS_LEAVE_ERR_PRIVATE(err);
9028 kvfree(internal_pipe);
9029 internal_pipe = NULL;
9034 if (internal_pipe->config.acc_extension)
9036 err = ia_css_pipe_load_extension(internal_pipe,
9037 internal_pipe->config.acc_extension);
9039 IA_CSS_LEAVE_ERR_PRIVATE(err);
9040 kvfree(internal_pipe);
9044 /* set all info to zeroes first */
9045 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9047 /* all went well, return the pipe */
9048 *pipe = internal_pipe;
9049 IA_CSS_LEAVE_ERR_PRIVATE(0);
9054 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9055 struct ia_css_pipe_info *pipe_info) {
9056 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9057 "ia_css_pipe_get_info()\n");
9061 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9062 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9065 if (!pipe || !pipe->stream)
9067 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9068 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
9071 /* we succeeded return the info */
9072 *pipe_info = pipe->info;
9073 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9077 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
9082 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9083 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9092 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9094 enum ia_css_frame_format new_format) {
9097 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9101 IA_CSS_ERROR("pipe is not set");
9103 IA_CSS_LEAVE_ERR_PRIVATE(err);
9106 if (0 != pin_index && 1 != pin_index)
9108 IA_CSS_ERROR("pin index is not valid");
9110 IA_CSS_LEAVE_ERR_PRIVATE(err);
9113 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY)
9115 IA_CSS_ERROR("new format is not valid");
9117 IA_CSS_LEAVE_ERR_PRIVATE(err);
9121 err = ia_css_pipe_check_format(pipe, new_format);
9123 if (pin_index == 0) {
9124 pipe->output_info[0].format = new_format;
9126 pipe->vf_output_info[0].format = new_format;
9130 IA_CSS_LEAVE_ERR_PRIVATE(err);
9134 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9135 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9137 ia_css_stream_configure_rx(struct ia_css_stream *stream) {
9138 struct ia_css_input_port *config;
9142 config = &stream->config.source.port;
9143 /* AM: this code is not reliable, especially for 2400 */
9144 if (config->num_lanes == 1)
9145 stream->csi_rx_config.mode = MONO_1L_1L_0L;
9146 else if (config->num_lanes == 2)
9147 stream->csi_rx_config.mode = MONO_2L_1L_0L;
9148 else if (config->num_lanes == 3)
9149 stream->csi_rx_config.mode = MONO_3L_1L_0L;
9150 else if (config->num_lanes == 4)
9151 stream->csi_rx_config.mode = MONO_4L_1L_0L;
9152 else if (config->num_lanes != 0)
9155 if (config->port > MIPI_PORT2_ID)
9157 stream->csi_rx_config.port =
9158 ia_css_isys_port_to_mipi_port(config->port);
9159 stream->csi_rx_config.timeout = config->timeout;
9160 stream->csi_rx_config.initcount = 0;
9161 stream->csi_rx_config.synccount = 0x28282828;
9162 stream->csi_rx_config.rxcount = config->rxcount;
9163 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9164 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9167 /* not implemented yet, requires extension of the rx_cfg_t
9171 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9172 stream->reconfigure_css_rx = true;
9177 static struct ia_css_pipe *
9178 find_pipe(struct ia_css_pipe *pipes[],
9179 unsigned int num_pipes,
9180 enum ia_css_pipe_mode mode,
9185 for (i = 0; i < num_pipes; i++) {
9187 if (pipes[i]->config.mode != mode)
9189 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9197 ia_css_acc_stream_create(struct ia_css_stream *stream) {
9202 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9206 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
9210 for (i = 0; i < stream->num_pipes; i++)
9212 struct ia_css_pipe *pipe = stream->pipes[i];
9216 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
9220 pipe->stream = stream;
9223 /* Map SP threads before doing anything. */
9224 err = map_sp_threads(stream, true);
9227 IA_CSS_LEAVE_ERR_PRIVATE(err);
9231 for (i = 0; i < stream->num_pipes; i++)
9233 struct ia_css_pipe *pipe = stream->pipes[i];
9236 ia_css_pipe_map_queue(pipe, true);
9239 err = create_host_pipeline_structure(stream);
9242 IA_CSS_LEAVE_ERR_PRIVATE(err);
9246 stream->started = false;
9248 IA_CSS_LEAVE_ERR_PRIVATE(0);
9254 metadata_info_init(const struct ia_css_metadata_config *mdc,
9255 struct ia_css_metadata_info *md) {
9256 /* Either both width and height should be set or neither */
9257 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9260 md->resolution = mdc->resolution;
9261 /* We round up the stride to a multiple of the width
9262 * of the port going to DDR, this is a HW requirements (DMA). */
9263 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9264 md->size = mdc->resolution.height * md->stride;
9269 static int check_pipe_resolutions(const struct ia_css_pipe *pipe)
9273 IA_CSS_ENTER_PRIVATE("");
9275 if (!pipe || !pipe->stream) {
9276 IA_CSS_ERROR("null arguments");
9281 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9282 pipe->config.input_effective_res.height) != 0) {
9283 IA_CSS_ERROR("effective resolution not supported");
9287 if (!ia_css_util_resolution_is_zero(
9288 pipe->stream->config.input_config.input_res)) {
9289 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9290 pipe->stream->config.input_config.input_res)) {
9291 IA_CSS_ERROR("effective resolution is larger than input resolution");
9296 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9297 IA_CSS_ERROR("output resolution must be even");
9301 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9302 IA_CSS_ERROR("VF resolution must be even");
9307 IA_CSS_LEAVE_ERR_PRIVATE(err);
9312 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9314 struct ia_css_pipe *pipes[],
9315 struct ia_css_stream **stream) {
9316 struct ia_css_pipe *curr_pipe;
9317 struct ia_css_stream *curr_stream = NULL;
9319 bool sensor_binning_changed;
9322 struct ia_css_metadata_info md_info;
9323 struct ia_css_resolution effective_res;
9324 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9325 bool aspect_ratio_crop_enabled = false;
9328 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9329 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9332 if (num_pipes == 0 ||
9337 IA_CSS_LEAVE_ERR(err);
9341 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9342 /* We don't support metadata for JPEG stream, since they both use str2mem */
9343 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9344 stream_config->metadata_config.resolution.height > 0)
9347 IA_CSS_LEAVE_ERR(err);
9352 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9353 if (stream_config->online && stream_config->pack_raw_pixels)
9355 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9357 IA_CSS_LEAVE_ERR(err);
9362 #if !defined(HAS_NO_INPUT_SYSTEM)
9363 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9365 /* check if mipi size specified */
9366 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9367 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9368 if (!stream_config->online)
9371 unsigned int port = (unsigned int)stream_config->source.port.port;
9373 if (port >= N_MIPI_PORT_ID) {
9375 IA_CSS_LEAVE_ERR(err);
9379 if (my_css.size_mem_words != 0) {
9380 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9381 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9382 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9384 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9385 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9386 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9388 IA_CSS_LEAVE_ERR(err);
9392 if (my_css.size_mem_words != 0) {
9393 my_css.num_mipi_frames[port] =
9394 2; /* Temp change: Default for backwards compatibility. */
9395 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9396 my_css.num_mipi_frames[port] =
9397 stream_config->mipi_buffer_config.nof_mipi_buffers;
9399 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9400 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9401 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9403 IA_CSS_LEAVE_ERR(err);
9409 /* Currently we only supported metadata up to a certain size. */
9410 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9413 IA_CSS_LEAVE_ERR(err);
9417 /* allocate the stream instance */
9418 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9422 IA_CSS_LEAVE_ERR(err);
9425 /* default all to 0 */
9426 curr_stream->info.metadata_info = md_info;
9428 /* allocate pipes */
9429 curr_stream->num_pipes = num_pipes;
9430 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
9431 if (!curr_stream->pipes)
9433 curr_stream->num_pipes = 0;
9437 IA_CSS_LEAVE_ERR(err);
9441 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9442 for (i = 0; i < num_pipes; i++)
9443 curr_stream->pipes[i] = pipes[i];
9444 curr_stream->last_pipe = curr_stream->pipes[0];
9445 /* take over stream config */
9446 curr_stream->config = *stream_config;
9448 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9449 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9450 stream_config->online)
9451 curr_stream->config.online = false;
9454 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9455 if (curr_stream->config.online)
9457 curr_stream->config.source.port.num_lanes =
9458 stream_config->source.port.num_lanes;
9459 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9462 /* in case driver doesn't configure init number of raw buffers, configure it here */
9463 if (curr_stream->config.target_num_cont_raw_buf == 0)
9464 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9465 if (curr_stream->config.init_num_cont_raw_buf == 0)
9466 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9468 /* Enable locking & unlocking of buffers in RAW buffer pool */
9469 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9470 sh_css_sp_configure_enable_raw_pool_locking(
9471 curr_stream->config.lock_all);
9473 /* copy mode specific stuff */
9474 switch (curr_stream->config.mode)
9476 case IA_CSS_INPUT_MODE_SENSOR:
9477 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9478 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9479 ia_css_stream_configure_rx(curr_stream);
9482 case IA_CSS_INPUT_MODE_TPG:
9483 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9484 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9485 curr_stream->config.source.tpg.x_mask,
9486 curr_stream->config.source.tpg.y_mask,
9487 curr_stream->config.source.tpg.x_delta,
9488 curr_stream->config.source.tpg.y_delta,
9489 curr_stream->config.source.tpg.xy_mask);
9491 sh_css_sp_configure_tpg(
9492 curr_stream->config.source.tpg.x_mask,
9493 curr_stream->config.source.tpg.y_mask,
9494 curr_stream->config.source.tpg.x_delta,
9495 curr_stream->config.source.tpg.y_delta,
9496 curr_stream->config.source.tpg.xy_mask);
9499 case IA_CSS_INPUT_MODE_PRBS:
9500 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9501 IA_CSS_LOG("mode prbs");
9502 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9505 case IA_CSS_INPUT_MODE_MEMORY:
9506 IA_CSS_LOG("mode memory");
9507 curr_stream->reconfigure_css_rx = false;
9510 IA_CSS_LOG("mode sensor/default");
9513 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9514 err = aspect_ratio_crop_init(curr_stream,
9516 &aspect_ratio_crop_enabled);
9519 IA_CSS_LEAVE_ERR(err);
9523 for (i = 0; i < num_pipes; i++)
9525 struct ia_css_resolution effective_res;
9527 curr_pipe = pipes[i];
9528 /* set current stream */
9529 curr_pipe->stream = curr_stream;
9530 /* take over effective info */
9532 effective_res = curr_pipe->config.input_effective_res;
9533 if (effective_res.height == 0 || effective_res.width == 0) {
9534 effective_res = curr_pipe->stream->config.input_config.effective_res;
9536 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9537 /* The aspect ratio cropping is currently only
9538 * supported on the new input system. */
9539 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9540 struct ia_css_resolution crop_res;
9542 err = aspect_ratio_crop(curr_pipe, &crop_res);
9544 effective_res = crop_res;
9546 /* in case of error fallback to default
9547 * effective resolution from driver. */
9548 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9552 curr_pipe->config.input_effective_res = effective_res;
9554 IA_CSS_LOG("effective_res=%dx%d",
9555 effective_res.width,
9556 effective_res.height);
9560 for (i = 0; i < num_pipes; i++) {
9561 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9562 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9563 err = check_pipe_resolutions(pipes[i]);
9571 err = ia_css_stream_isp_parameters_init(curr_stream);
9574 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9576 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC)
9578 *stream = curr_stream;
9579 err = ia_css_acc_stream_create(curr_stream);
9582 /* sensor binning */
9585 sensor_binning_changed =
9586 sh_css_params_set_binning_factor(curr_stream,
9587 curr_stream->config.sensor_binning_factor);
9590 sensor_binning_changed = false;
9593 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9594 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9595 /* loop over pipes */
9596 IA_CSS_LOG("num_pipes=%d", num_pipes);
9597 curr_stream->cont_capt = false;
9598 /* Temporary hack: we give the preview pipe a reference to the capture
9599 * pipe in continuous capture mode. */
9600 if (curr_stream->config.continuous)
9602 /* Search for the preview pipe and create the copy pipe */
9603 struct ia_css_pipe *preview_pipe;
9604 struct ia_css_pipe *video_pipe;
9605 struct ia_css_pipe *acc_pipe;
9606 struct ia_css_pipe *capture_pipe = NULL;
9607 struct ia_css_pipe *copy_pipe = NULL;
9609 if (num_pipes >= 2) {
9610 curr_stream->cont_capt = true;
9611 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9614 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9617 /* Create copy pipe here, since it may not be exposed to the driver */
9618 preview_pipe = find_pipe(pipes, num_pipes,
9619 IA_CSS_PIPE_MODE_PREVIEW, false);
9620 video_pipe = find_pipe(pipes, num_pipes,
9621 IA_CSS_PIPE_MODE_VIDEO, false);
9622 acc_pipe = find_pipe(pipes, num_pipes,
9623 IA_CSS_PIPE_MODE_ACC, false);
9624 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9625 curr_stream->cont_capt =
9626 false; /* preview + QoS case will not need cont_capt switch */
9627 if (curr_stream->cont_capt == true) {
9628 capture_pipe = find_pipe(pipes, num_pipes,
9629 IA_CSS_PIPE_MODE_CAPTURE, false);
9630 if (!capture_pipe) {
9635 /* We do not support preview and video pipe at the same time */
9636 if (preview_pipe && video_pipe) {
9641 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9642 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9645 ia_css_pipe_config_defaults(©_pipe->config);
9646 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9647 copy_pipe->stream = curr_stream;
9649 if (preview_pipe && (curr_stream->cont_capt == true)) {
9650 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9652 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9653 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9656 ia_css_pipe_config_defaults(©_pipe->config);
9657 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9658 copy_pipe->stream = curr_stream;
9660 if (video_pipe && (curr_stream->cont_capt == true)) {
9661 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9663 if (preview_pipe && acc_pipe) {
9664 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9667 for (i = 0; i < num_pipes; i++)
9669 curr_pipe = pipes[i];
9670 /* set current stream */
9671 curr_pipe->stream = curr_stream;
9674 /* take over effective info */
9676 effective_res = curr_pipe->config.input_effective_res;
9677 err = ia_css_util_check_res(
9678 effective_res.width,
9679 effective_res.height);
9683 /* sensor binning per pipe */
9684 if (sensor_binning_changed)
9685 sh_css_pipe_free_shading_table(curr_pipe);
9688 /* now pipes have been configured, info should be available */
9689 for (i = 0; i < num_pipes; i++)
9691 struct ia_css_pipe_info *pipe_info = NULL;
9693 curr_pipe = pipes[i];
9695 err = sh_css_pipe_load_binaries(curr_pipe);
9699 /* handle each pipe */
9700 pipe_info = &curr_pipe->info;
9701 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9702 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9703 &pipe_info->output_info[j], j);
9709 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9713 err = sh_css_pipe_get_shading_info(curr_pipe,
9714 &pipe_info->shading_info, NULL);
9716 err = sh_css_pipe_get_shading_info(curr_pipe,
9717 &pipe_info->shading_info, &curr_pipe->config);
9721 err = sh_css_pipe_get_grid_info(curr_pipe,
9722 &pipe_info->grid_info);
9725 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9726 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9727 &pipe_info->vf_output_info[j], j);
9733 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9736 curr_stream->started = false;
9738 /* Map SP threads before doing anything. */
9739 err = map_sp_threads(curr_stream, true);
9742 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9746 for (i = 0; i < num_pipes; i++)
9748 curr_pipe = pipes[i];
9749 ia_css_pipe_map_queue(curr_pipe, true);
9752 /* Create host side pipeline objects without stages */
9753 err = create_host_pipeline_structure(curr_stream);
9756 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9760 /* assign curr_stream */
9761 *stream = curr_stream;
9765 /* working mode: enter into the seed list */
9766 if (my_css_save.mode == sh_css_mode_working) {
9767 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9768 if (!my_css_save.stream_seeds[i].stream) {
9769 IA_CSS_LOG("entered stream into loc=%d", i);
9770 my_css_save.stream_seeds[i].orig_stream = stream;
9771 my_css_save.stream_seeds[i].stream = curr_stream;
9772 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9773 my_css_save.stream_seeds[i].stream_config = *stream_config;
9774 for (j = 0; j < num_pipes; j++) {
9775 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9776 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9777 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9783 ia_css_stream_destroy(curr_stream);
9786 ia_css_stream_destroy(curr_stream);
9788 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9793 ia_css_stream_destroy(struct ia_css_stream *stream) {
9797 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9801 IA_CSS_LEAVE_ERR_PRIVATE(err);
9805 ia_css_stream_isp_parameters_uninit(stream);
9807 if ((stream->last_pipe) &&
9808 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num))
9810 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9813 for (i = 0; i < stream->num_pipes; i++) {
9814 struct ia_css_pipe *entry = stream->pipes[i];
9815 unsigned int sp_thread_id;
9816 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9820 /* get the SP thread id */
9821 if (ia_css_pipeline_get_sp_thread_id(
9822 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9824 /* get the target input terminal */
9825 sp_pipeline_input_terminal =
9826 &sh_css_sp_group.pipe_io[sp_thread_id].input;
9828 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9829 ia_css_isys_stream_h isys_stream =
9830 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9831 if (stream->config.isys_config[i].valid && isys_stream->valid)
9832 ia_css_isys_stream_destroy(isys_stream);
9836 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9838 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG;
9839 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS;
9843 for (i = 0; i < stream->num_pipes; i++) {
9844 struct ia_css_pipe *entry = stream->pipes[i];
9845 /* free any mipi frames that are remaining:
9846 * some test stream create-destroy cycles do not generate output frames
9847 * and the mipi buffer is not freed in the deque function
9850 free_mipi_frames(entry);
9853 stream_unregister_with_csi_rx(stream);
9856 for (i = 0; i < stream->num_pipes; i++) {
9857 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9860 ia_css_pipe_map_queue(curr_pipe, false);
9863 err = map_sp_threads(stream, false);
9865 IA_CSS_LEAVE_ERR_PRIVATE(err);
9870 /* remove references from pipes to stream */
9871 for (i = 0; i < stream->num_pipes; i++)
9873 struct ia_css_pipe *entry = stream->pipes[i];
9877 /* clear reference to stream */
9878 entry->stream = NULL;
9879 /* check internal copy pipe */
9880 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9881 entry->pipe_settings.preview.copy_pipe) {
9882 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9883 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9885 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9886 entry->pipe_settings.video.copy_pipe) {
9887 IA_CSS_LOG("clearing stream on internal video copy pipe");
9888 entry->pipe_settings.video.copy_pipe->stream = NULL;
9890 err = sh_css_pipe_unload_binaries(entry);
9893 /* free associated memory of stream struct */
9894 kfree(stream->pipes);
9895 stream->pipes = NULL;
9896 stream->num_pipes = 0;
9898 /* working mode: take out of the seed list */
9899 if (my_css_save.mode == sh_css_mode_working) {
9900 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9901 if (my_css_save.stream_seeds[i].stream == stream)
9903 IA_CSS_LOG("took out stream %d", i);
9904 my_css_save.stream_seeds[i].stream = NULL;
9911 IA_CSS_LEAVE_ERR(err);
9917 ia_css_stream_get_info(const struct ia_css_stream *stream,
9918 struct ia_css_stream_info *stream_info) {
9919 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9921 assert(stream_info);
9923 *stream_info = stream->info;
9928 * Rebuild a stream, including allocating structs, setting configuration and
9929 * building the required pipes.
9930 * The data is taken from the css_save struct updated upon stream creation.
9931 * The stream handle is used to identify the correct entry in the css_save struct
9934 ia_css_stream_load(struct ia_css_stream *stream) {
9940 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
9941 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9943 if (my_css_save.stream_seeds[i].stream == stream) {
9946 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9947 if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
9948 &my_css_save.stream_seeds[i].pipes[j])) != 0) {
9952 for (k = 0; k < j; k++)
9953 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9958 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
9959 my_css_save.stream_seeds[i].num_pipes,
9960 my_css_save.stream_seeds[i].pipes,
9961 &my_css_save.stream_seeds[i].stream);
9963 ia_css_stream_destroy(stream);
9964 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9965 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
9974 /* TODO remove function - DEPRECATED */
9981 ia_css_stream_start(struct ia_css_stream *stream) {
9984 IA_CSS_ENTER("stream = %p", stream);
9985 if ((!stream) || (!stream->last_pipe))
9987 IA_CSS_LEAVE_ERR(-EINVAL);
9990 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
9992 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
9994 /* Create host side pipeline. */
9995 err = create_host_pipeline(stream);
9998 IA_CSS_LEAVE_ERR(err);
10002 #if !defined(HAS_NO_INPUT_SYSTEM)
10003 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10004 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10005 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10006 stream_register_with_csi_rx(stream);
10010 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10011 /* Initialize mipi size checks */
10012 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10015 unsigned int port = (unsigned int)(stream->config.source.port.port);
10017 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10018 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
10019 sh_css_get_mipi_sizes_for_check(port, idx);
10024 #if !defined(HAS_NO_INPUT_SYSTEM)
10025 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)
10027 err = sh_css_config_input_network(stream);
10031 #endif /* !HAS_NO_INPUT_SYSTEM */
10033 err = sh_css_pipe_start(stream);
10034 IA_CSS_LEAVE_ERR(err);
10039 ia_css_stream_stop(struct ia_css_stream *stream) {
10042 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10044 assert(stream->last_pipe);
10045 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10046 stream->last_pipe->mode);
10048 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10049 /* De-initialize mipi size checks */
10050 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10053 unsigned int port = (unsigned int)(stream->config.source.port.port);
10055 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10056 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10062 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10064 err = sh_css_pipes_stop(stream);
10070 /* Ideally, unmapping should happen after pipeline_stop, but current
10071 * semantics do not allow that. */
10072 /* err = map_sp_threads(stream, false); */
10078 ia_css_stream_has_stopped(struct ia_css_stream *stream) {
10084 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10086 stopped = sh_css_pipes_have_stopped(stream);
10094 * Destroy the stream and all the pipes related to it.
10095 * The stream handle is used to identify the correct entry in the css_save struct
10098 ia_css_stream_unload(struct ia_css_stream *stream) {
10102 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
10105 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
10106 if (my_css_save.stream_seeds[i].stream == stream)
10110 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10111 "ia_css_stream_unload(): unloading %d (%p)\n", i,
10112 my_css_save.stream_seeds[i].stream);
10113 ia_css_stream_destroy(stream);
10114 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
10115 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10116 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10117 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
10118 my_css_save.stream_seeds[i].stream);
10121 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
10126 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
10127 enum ia_css_pipe_id *pipe_id) {
10128 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10130 *pipe_id = pipe->mode;
10132 *pipe_id = IA_CSS_PIPE_ID_COPY;
10137 enum atomisp_input_format
10138 ia_css_stream_get_format(const struct ia_css_stream *stream) {
10139 return stream->config.input_config.format;
10143 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) {
10144 return (stream->config.pixels_per_clock == 2);
10147 struct ia_css_binary *
10148 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
10150 struct ia_css_pipe *pipe;
10154 pipe = stream->pipes[0];
10156 if (stream->num_pipes == 2) {
10157 assert(stream->pipes[1]);
10158 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10159 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10160 pipe = stream->pipes[1];
10163 return ia_css_pipe_get_shading_correction_binary(pipe);
10166 struct ia_css_binary *
10167 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
10169 struct ia_css_pipe *video_pipe = NULL;
10171 /* First we find the video pipe */
10172 for (i = 0; i < stream->num_pipes; i++) {
10173 struct ia_css_pipe *pipe = stream->pipes[i];
10175 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10181 return &video_pipe->pipe_settings.video.video_binary;
10185 struct ia_css_binary *
10186 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
10187 struct ia_css_pipe *pipe;
10188 struct ia_css_binary *s3a_binary = NULL;
10192 pipe = stream->pipes[0];
10194 if (stream->num_pipes == 2) {
10195 assert(stream->pipes[1]);
10196 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10197 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10198 pipe = stream->pipes[1];
10201 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10207 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
10208 unsigned int output_padded_width) {
10209 struct ia_css_pipe *pipe;
10213 pipe = stream->last_pipe;
10217 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10218 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10219 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10224 static struct ia_css_binary *
10225 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
10226 struct ia_css_binary *binary = NULL;
10230 switch (pipe->config.mode) {
10231 case IA_CSS_PIPE_MODE_PREVIEW:
10232 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10234 case IA_CSS_PIPE_MODE_VIDEO:
10235 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10237 case IA_CSS_PIPE_MODE_CAPTURE:
10238 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10241 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10242 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10243 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10247 } else if (pipe->config.default_capture_config.mode ==
10248 IA_CSS_CAPTURE_MODE_BAYER)
10249 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10250 else if (pipe->config.default_capture_config.mode ==
10251 IA_CSS_CAPTURE_MODE_ADVANCED ||
10252 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10253 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10254 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10255 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10256 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10263 if (binary && binary->info->sp.enable.sc)
10269 static struct ia_css_binary *
10270 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
10271 struct ia_css_binary *binary = NULL;
10275 switch (pipe->config.mode) {
10276 case IA_CSS_PIPE_MODE_PREVIEW:
10277 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10279 case IA_CSS_PIPE_MODE_VIDEO:
10280 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10282 case IA_CSS_PIPE_MODE_CAPTURE:
10283 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10286 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10287 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10288 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10292 } else if (pipe->config.default_capture_config.mode ==
10293 IA_CSS_CAPTURE_MODE_BAYER)
10294 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10295 else if (pipe->config.default_capture_config.mode ==
10296 IA_CSS_CAPTURE_MODE_ADVANCED ||
10297 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10298 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10299 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10300 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10301 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10310 if (binary && !binary->info->sp.enable.s3a)
10316 static struct ia_css_binary *
10317 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
10318 struct ia_css_binary *binary = NULL;
10322 switch (pipe->config.mode) {
10323 case IA_CSS_PIPE_MODE_VIDEO:
10324 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10330 if (binary && !binary->info->sp.enable.dis)
10336 struct ia_css_pipeline *
10337 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) {
10340 return (struct ia_css_pipeline *)&pipe->pipeline;
10344 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
10347 /* KW was not sure this function was not returning a value
10348 that was out of range; so added an assert, and, for the
10349 case when asserts are not enabled, clip to the largest
10350 value; pipe_num is unsigned so the value cannot be too small
10352 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10354 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10355 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10357 return pipe->pipe_num;
10361 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
10364 return (unsigned int)pipe->config.isp_pipe_version;
10367 #define SP_START_TIMEOUT_US 30000000
10370 ia_css_start_sp(void) {
10371 unsigned long timeout;
10375 sh_css_sp_start_isp();
10377 /* waiting for the SP is completely started */
10378 timeout = SP_START_TIMEOUT_US;
10379 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout)
10386 IA_CSS_ERROR("timeout during SP initialization");
10390 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10391 /* TODO: Fix this. */
10393 sh_css_init_host_sp_control_vars();
10395 /* buffers should be initialized only when sp is started */
10396 /* AM: At the moment it will be done only when there is no stream active. */
10398 sh_css_setup_queues();
10399 ia_css_bufq_dump_queue_info();
10401 IA_CSS_LEAVE_ERR(err);
10406 * Time to wait SP for termincate. Only condition when this can happen
10407 * is a fatal hw failure, but we must be able to detect this and emit
10408 * a proper error trace.
10410 #define SP_SHUTDOWN_TIMEOUT_US 200000
10413 ia_css_stop_sp(void) {
10414 unsigned long timeout;
10417 IA_CSS_ENTER("void");
10419 if (!sh_css_sp_is_running())
10422 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10424 /* Return an error - stop SP should not have been called by driver */
10428 /* For now, stop whole SP */
10430 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10432 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate))
10434 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10435 ia_css_debug_dump_sp_sw_debug_info();
10436 ia_css_debug_dump_debug_info(NULL);
10440 sh_css_sp_set_sp_running(false);
10442 timeout = SP_SHUTDOWN_TIMEOUT_US;
10443 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout)
10448 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10449 IA_CSS_WARNING("SP has not terminated (SW)");
10453 IA_CSS_WARNING("SP is not idle");
10454 ia_css_debug_dump_sp_sw_debug_info();
10456 timeout = SP_SHUTDOWN_TIMEOUT_US;
10457 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout)
10464 IA_CSS_WARNING("ISP is not idle");
10465 ia_css_debug_dump_sp_sw_debug_info();
10468 sh_css_hmm_buffer_record_uninit();
10470 /* clear pending param sets from refcount */
10471 sh_css_param_clear_param_sets();
10473 IA_CSS_LEAVE_ERR(err);
10478 ia_css_update_continuous_frames(struct ia_css_stream *stream) {
10479 struct ia_css_pipe *pipe;
10482 ia_css_debug_dtrace(
10483 IA_CSS_DEBUG_TRACE,
10484 "sh_css_update_continuous_frames() enter:\n");
10488 ia_css_debug_dtrace(
10489 IA_CSS_DEBUG_TRACE,
10490 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10494 pipe = stream->continuous_pipe;
10496 for (i = stream->config.init_num_cont_raw_buf;
10497 i < stream->config.target_num_cont_raw_buf; i++)
10499 sh_css_update_host2sp_offline_frame(i,
10500 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10502 sh_css_update_host2sp_cont_num_raw_frames
10503 (stream->config.target_num_cont_raw_buf, true);
10504 ia_css_debug_dtrace(
10505 IA_CSS_DEBUG_TRACE,
10506 "sh_css_update_continuous_frames() leave: return_void\n");
10511 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10513 unsigned int thread_id;
10514 enum ia_css_pipe_id pipe_id;
10515 unsigned int pipe_num;
10516 bool need_input_queue;
10521 pipe_id = pipe->mode;
10522 pipe_num = pipe->pipe_num;
10524 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10526 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10527 need_input_queue = true;
10529 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10532 /* map required buffer queues to resources */
10533 /* TODO: to be improved */
10534 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10535 if (need_input_queue)
10536 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10537 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10538 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10539 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10540 #if defined SH_CSS_ENABLE_METADATA
10541 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10543 if (pipe->pipe_settings.preview.preview_binary.info &&
10544 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10545 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10546 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10549 if (need_input_queue)
10550 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10551 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10552 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10553 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10554 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10555 #if defined SH_CSS_ENABLE_METADATA
10556 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10558 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10559 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10560 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10561 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10562 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10566 } else if (pipe->config.default_capture_config.mode ==
10567 IA_CSS_CAPTURE_MODE_ADVANCED ||
10568 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10569 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10570 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10571 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10572 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10574 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10575 if (need_input_queue)
10576 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10577 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10578 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10579 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10580 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10581 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10582 #if defined SH_CSS_ENABLE_METADATA
10583 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10585 if (pipe->pipe_settings.video.video_binary.info &&
10586 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10587 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10588 if (pipe->pipe_settings.video.video_binary.info &&
10589 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10591 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10592 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10593 if (need_input_queue)
10594 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10595 if (!pipe->stream->config.continuous)
10596 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10597 #if defined SH_CSS_ENABLE_METADATA
10598 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10600 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10601 if (need_input_queue)
10602 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10603 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10604 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10605 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10606 #if defined SH_CSS_ENABLE_METADATA
10607 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10609 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10612 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10613 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10614 if (pipe->enable_viewfinder[idx])
10615 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
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_PARAMETER_SET, map);
10620 #if defined SH_CSS_ENABLE_METADATA
10621 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10627 #if CONFIG_ON_FRAME_ENQUEUE()
10628 static int set_config_on_frame_enqueue(struct ia_css_frame_info
10629 *info, struct frame_data_wrapper *frame) {
10630 frame->config_on_frame_enqueue.padded_width = 0;
10632 /* currently we support configuration on frame enqueue only on YUV formats */
10633 /* on other formats the padded_width is zeroed for no configuration override */
10634 switch (info->format) {
10635 case IA_CSS_FRAME_FORMAT_YUV420:
10636 case IA_CSS_FRAME_FORMAT_NV12:
10637 if (info->padded_width > info->res.width) {
10638 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10639 } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) {
10642 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10653 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
10658 /* Only continuous streams have a tagger to which we can send the
10659 * unlock message. */
10660 if (!stream || !stream->config.continuous)
10662 IA_CSS_ERROR("invalid stream pointer");
10666 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10667 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID)
10669 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
10673 /* Send the event. Since we verified that the exp_id is valid,
10674 * we can safely assign it to an 8-bit argument here. */
10675 ret = ia_css_bufq_enqueue_psys_event(
10676 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10678 IA_CSS_LEAVE_ERR(ret);
10682 /* @brief Set the state (Enable or Disable) of the Extension stage in the
10686 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10688 unsigned int thread_id;
10689 struct ia_css_pipeline_stage *stage;
10694 /* Parameter Check */
10695 if (!pipe || !pipe->stream)
10697 IA_CSS_ERROR("Invalid Pipe.");
10699 } else if (!(pipe->config.acc_extension))
10701 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10703 } else if (!sh_css_sp_is_running())
10705 IA_CSS_ERROR("Leaving: queue unavailable.");
10709 /* Query the threadid and stage_num for the Extension firmware*/
10710 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10711 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10713 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10714 err = ia_css_bufq_enqueue_psys_event(
10715 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10716 (uint8_t)thread_id,
10717 (uint8_t)stage->stage_num,
10721 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10723 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10727 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10731 /* @brief Get the state (Enable or Disable) of the Extension stage in the
10735 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10737 struct ia_css_pipeline_stage *stage;
10738 unsigned int thread_id;
10743 /* Parameter Check */
10744 if (!pipe || !pipe->stream)
10746 IA_CSS_ERROR("Invalid Pipe.");
10748 } else if (!(pipe->config.acc_extension))
10750 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10752 } else if (!sh_css_sp_is_running())
10754 IA_CSS_ERROR("Leaving: queue unavailable.");
10758 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10759 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10760 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10763 /* Get the Extension State */
10764 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10765 stage->stage_num)) ? true : false;
10768 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10774 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
10776 struct ia_css_isp_param_css_segments *css_seg,
10777 struct ia_css_isp_param_isp_segments *isp_seg) {
10778 unsigned int HIVE_ADDR_sp_group;
10779 static struct sh_css_sp_group sp_group;
10780 static struct sh_css_sp_stage sp_stage;
10781 static struct sh_css_isp_stage isp_stage;
10782 const struct ia_css_fw_info *fw;
10783 unsigned int thread_id;
10784 struct ia_css_pipeline_stage *stage;
10787 enum ia_css_isp_memories mem;
10792 fw = &sh_css_sp_fw;
10794 /* Parameter Check */
10795 if (!pipe || !pipe->stream)
10797 IA_CSS_ERROR("Invalid Pipe.");
10799 } else if (!(pipe->config.acc_extension))
10801 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10803 } else if (!sh_css_sp_is_running())
10805 IA_CSS_ERROR("Leaving: queue unavailable.");
10809 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10810 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10811 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10813 /* Get the Extension State */
10814 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10815 stage->stage_num)) ? true : false;
10816 /* Update mapped arg only when extension stage is not enabled */
10818 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10821 stage_num = stage->stage_num;
10823 HIVE_ADDR_sp_group = fw->info.sp.group;
10824 sp_dmem_load(SP0_ID,
10825 (unsigned int)sp_address_of(sp_group),
10826 &sp_group, sizeof(struct sh_css_sp_group));
10827 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10828 &sp_stage, sizeof(struct sh_css_sp_stage));
10830 hmm_load(sp_stage.isp_stage_addr,
10831 &isp_stage, sizeof(struct sh_css_isp_stage));
10833 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10834 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10835 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10836 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10837 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10838 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address
10840 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10841 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 hmm_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
10857 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10858 struct ia_css_pipe *pipes[],
10859 bool *do_crop_status) {
10862 struct ia_css_pipe *curr_pipe;
10865 if ((!curr_stream) ||
10866 (curr_stream->num_pipes == 0) ||
10871 IA_CSS_LEAVE_ERR(err);
10875 for (i = 0; i < curr_stream->num_pipes; i++)
10877 curr_pipe = pipes[i];
10878 pipe_mask |= (1 << curr_pipe->config.mode);
10882 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10883 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10884 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10885 curr_stream->config.continuous);
10890 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
10891 bool status = false;
10893 if ((curr_pipe) && 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))
10904 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10905 struct ia_css_resolution *effective_res) {
10907 struct ia_css_resolution crop_res;
10908 struct ia_css_resolution *in_res = NULL;
10909 struct ia_css_resolution *out_res = NULL;
10910 bool use_bds_output_info = false;
10911 bool use_vf_pp_in_res = false;
10912 bool use_capt_pp_in_res = false;
10914 if ((!curr_pipe) ||
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))
10927 IA_CSS_LEAVE_ERR(err);
10931 use_bds_output_info =
10932 ((curr_pipe->bds_output_info.res.width != 0) &&
10933 (curr_pipe->bds_output_info.res.height != 0));
10936 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10937 (curr_pipe->config.vf_pp_in_res.height != 0));
10939 use_capt_pp_in_res =
10940 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10941 (curr_pipe->config.capt_pp_in_res.height != 0));
10943 in_res = &curr_pipe->stream->config.input_config.effective_res;
10944 out_res = &curr_pipe->output_info[0].res;
10946 switch (curr_pipe->config.mode)
10948 case IA_CSS_PIPE_MODE_PREVIEW:
10949 if (use_bds_output_info)
10950 out_res = &curr_pipe->bds_output_info.res;
10951 else if (use_vf_pp_in_res)
10952 out_res = &curr_pipe->config.vf_pp_in_res;
10954 case IA_CSS_PIPE_MODE_VIDEO:
10955 if (use_bds_output_info)
10956 out_res = &curr_pipe->bds_output_info.res;
10958 case IA_CSS_PIPE_MODE_CAPTURE:
10959 if (use_capt_pp_in_res)
10960 out_res = &curr_pipe->config.capt_pp_in_res;
10962 case IA_CSS_PIPE_MODE_ACC:
10963 case IA_CSS_PIPE_MODE_COPY:
10964 case IA_CSS_PIPE_MODE_YUVPP:
10966 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10967 curr_pipe->config.mode);
10972 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10975 *effective_res = crop_res;
10978 /* in case of error fallback to default
10979 * effective resolution from driver. */
10980 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10987 sh_css_hmm_buffer_record_init(void) {
10990 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
10991 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
10995 sh_css_hmm_buffer_record_uninit(void) {
10997 struct sh_css_hmm_buffer_record *buffer_record = NULL;
10999 buffer_record = &hmm_buffer_record[0];
11000 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11001 if (buffer_record->in_use) {
11002 if (buffer_record->h_vbuf)
11003 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11004 sh_css_hmm_buffer_record_reset(buffer_record);
11011 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
11012 assert(buffer_record);
11013 buffer_record->in_use = false;
11014 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11015 buffer_record->h_vbuf = NULL;
11016 buffer_record->kernel_ptr = 0;
11019 static struct sh_css_hmm_buffer_record
11020 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11021 enum ia_css_buffer_type type,
11022 hrt_address kernel_ptr) {
11024 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11025 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11028 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
11029 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11030 assert(kernel_ptr != 0);
11032 buffer_record = &hmm_buffer_record[0];
11033 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11034 if (!buffer_record->in_use) {
11035 buffer_record->in_use = true;
11036 buffer_record->type = type;
11037 buffer_record->h_vbuf = h_vbuf;
11038 buffer_record->kernel_ptr = kernel_ptr;
11039 out_buffer_record = buffer_record;
11045 return out_buffer_record;
11048 static struct sh_css_hmm_buffer_record
11049 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
11050 enum ia_css_buffer_type type) {
11052 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11053 bool found_record = false;
11055 buffer_record = &hmm_buffer_record[0];
11056 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11057 if ((buffer_record->in_use) &&
11058 (buffer_record->type == type) &&
11059 (buffer_record->h_vbuf) &&
11060 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11061 found_record = true;
11068 return buffer_record;