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 "ia_css_inputfifo.h"
80 #define WITH_PC_MONITORING 0
82 #define SH_CSS_VIDEO_BUFFER_ALIGNMENT 0
84 #if WITH_PC_MONITORING
85 #define MULTIPLE_SAMPLES 1
86 #define NOF_SAMPLES 60
87 #include "linux/kthread.h"
88 #include "linux/sched.h"
89 #include "linux/delay.h"
90 #include "sh_css_metrics.h"
91 static int thread_alive;
92 #endif /* WITH_PC_MONITORING */
94 #include "ia_css_spctrl.h"
95 #include "ia_css_version_data.h"
96 #include "sh_css_struct.h"
97 #include "ia_css_bufq.h"
98 #include "ia_css_timer.h" /* clock_value_t */
100 #include "isp/modes/interface/input_buf.isp.h"
102 /* Name of the sp program: should not be built-in */
103 #define SP_PROG_NAME "sp"
104 /* Size of Refcount List */
105 #define REFCOUNT_SIZE 1000
107 /* for JPEG, we don't know the length of the image upfront,
108 * but since we support sensor upto 16MP, we take this as
111 #define JPEG_BYTES (16 * 1024 * 1024)
113 #define STATS_ENABLED(stage) (stage && stage->binary && stage->binary->info && \
114 (stage->binary->info->sp.enable.s3a || stage->binary->info->sp.enable.dis))
116 struct sh_css my_css;
118 int (*sh_css_printf)(const char *fmt, va_list args) = NULL;
120 /* modes of work: stream_create and stream_destroy will update the save/restore data
121 only when in working mode, not suspend/resume
123 enum ia_sh_css_modes {
124 sh_css_mode_none = 0,
130 /* a stream seed, to save and restore the stream data.
131 the stream seed contains all the data required to "grow" the seed again after it was closed.
133 struct sh_css_stream_seed {
135 **orig_stream; /* pointer to restore the original handle */
136 struct ia_css_stream *stream; /* handle, used as ID too.*/
137 struct ia_css_stream_config stream_config; /* stream config struct */
139 struct ia_css_pipe *pipes[IA_CSS_PIPE_ID_NUM]; /* pipe handles */
141 **orig_pipes[IA_CSS_PIPE_ID_NUM]; /* pointer to restore original handle */
142 struct ia_css_pipe_config
143 pipe_config[IA_CSS_PIPE_ID_NUM]; /* pipe config structs */
146 #define MAX_ACTIVE_STREAMS 5
147 /* A global struct for save/restore to hold all the data that should sustain power-down:
148 MMU base, IRQ type, env for routines, binary loaded FW and the stream seeds.
151 enum ia_sh_css_modes mode;
152 u32 mmu_base; /* the last mmu_base */
153 enum ia_css_irq_type irq_type;
154 struct sh_css_stream_seed stream_seeds[MAX_ACTIVE_STREAMS];
155 struct ia_css_fw *loaded_fw; /* fw struct previously loaded */
156 struct ia_css_env driver_env; /* driver-supplied env copy */
159 static bool my_css_save_initialized; /* if my_css_save was initialized */
160 static struct sh_css_save my_css_save;
162 /* pqiao NOTICE: this is for css internal buffer recycling when stopping pipeline,
163 this array is temporary and will be replaced by resource manager*/
164 /* Taking the biggest Size for number of Elements */
165 #define MAX_HMM_BUFFER_NUM \
166 (SH_CSS_MAX_NUM_QUEUES * (IA_CSS_NUM_ELEMS_SP2HOST_BUFFER_QUEUE + 2))
168 struct sh_css_hmm_buffer_record {
170 enum ia_css_buffer_type type;
171 struct ia_css_rmgr_vbuf_handle *h_vbuf;
172 hrt_address kernel_ptr;
175 static struct sh_css_hmm_buffer_record hmm_buffer_record[MAX_HMM_BUFFER_NUM];
177 #define GPIO_FLASH_PIN_MASK BIT(HIVE_GPIO_STROBE_TRIGGER_PIN)
179 static bool fw_explicitly_loaded;
186 allocate_delay_frames(struct ia_css_pipe *pipe);
189 sh_css_pipe_start(struct ia_css_stream *stream);
193 * @brief Stop all "ia_css_pipe" instances in the target
194 * "ia_css_stream" instance.
196 * @param[in] stream Point to the target "ia_css_stream" instance.
199 * - 0, if the "stop" requests have been successfully sent out.
200 * - CSS error code, otherwise.
204 * This API sends the "stop" requests to the "ia_css_pipe"
205 * instances in the same "ia_css_stream" instance. It will
206 * return without waiting for all "ia_css_pipe" instatnces
210 sh_css_pipes_stop(struct ia_css_stream *stream);
213 * @brief Check if all "ia_css_pipe" instances in the target
214 * "ia_css_stream" instance have stopped.
216 * @param[in] stream Point to the target "ia_css_stream" instance.
219 * - true, if all "ia_css_pipe" instances in the target "ia_css_stream"
220 * instance have ben stopped.
221 * - false, otherwise.
225 sh_css_pipes_have_stopped(struct ia_css_stream *stream);
229 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
230 enum ia_css_frame_format format);
234 check_pipe_resolutions(const struct ia_css_pipe *pipe);
237 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
238 struct ia_css_fw_info *firmware);
241 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
242 struct ia_css_fw_info *firmware);
244 ia_css_reset_defaults(struct sh_css *css);
247 sh_css_init_host_sp_control_vars(void);
249 static int set_num_primary_stages(unsigned int *num,
250 enum ia_css_pipe_version version);
253 need_capture_pp(const struct ia_css_pipe *pipe);
256 need_yuv_scaler_stage(const struct ia_css_pipe *pipe);
258 static int ia_css_pipe_create_cas_scaler_desc_single_output(
259 struct ia_css_frame_info *cas_scaler_in_info,
260 struct ia_css_frame_info *cas_scaler_out_info,
261 struct ia_css_frame_info *cas_scaler_vf_info,
262 struct ia_css_cas_binary_descr *descr);
264 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
268 need_downscaling(const struct ia_css_resolution in_res,
269 const struct ia_css_resolution out_res);
271 static bool need_capt_ldc(const struct ia_css_pipe *pipe);
274 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
277 int sh_css_pipe_get_viewfinder_frame_info(
278 struct ia_css_pipe *pipe,
279 struct ia_css_frame_info *info,
283 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
284 struct ia_css_frame_info *info,
288 capture_start(struct ia_css_pipe *pipe);
291 video_start(struct ia_css_pipe *pipe);
294 preview_start(struct ia_css_pipe *pipe);
297 yuvpp_start(struct ia_css_pipe *pipe);
299 static bool copy_on_sp(struct ia_css_pipe *pipe);
302 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
303 struct ia_css_frame *vf_frame, unsigned int idx);
306 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
307 struct ia_css_frame *frame, enum ia_css_frame_format format);
310 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
311 struct ia_css_frame *out_frame, unsigned int idx);
314 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
318 alloc_continuous_frames(
319 struct ia_css_pipe *pipe, bool init_time);
322 pipe_global_init(void);
325 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
326 unsigned int *pipe_number);
329 pipe_release_pipe_num(unsigned int pipe_num);
332 create_host_pipeline_structure(struct ia_css_stream *stream);
335 create_host_pipeline(struct ia_css_stream *stream);
338 create_host_preview_pipeline(struct ia_css_pipe *pipe);
341 create_host_video_pipeline(struct ia_css_pipe *pipe);
344 create_host_copy_pipeline(struct ia_css_pipe *pipe,
345 unsigned int max_input_width,
346 struct ia_css_frame *out_frame);
349 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
352 create_host_capture_pipeline(struct ia_css_pipe *pipe);
355 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
358 create_host_acc_pipeline(struct ia_css_pipe *pipe);
361 sh_css_get_sw_interrupt_value(unsigned int irq);
363 static struct ia_css_binary *ia_css_pipe_get_shading_correction_binary(
364 const struct ia_css_pipe *pipe);
366 static struct ia_css_binary *
367 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe);
369 static struct ia_css_binary *
370 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe);
373 sh_css_hmm_buffer_record_init(void);
376 sh_css_hmm_buffer_record_uninit(void);
379 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record);
381 static struct sh_css_hmm_buffer_record
382 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
383 enum ia_css_buffer_type type,
384 hrt_address kernel_ptr);
386 static struct sh_css_hmm_buffer_record
387 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
388 enum ia_css_buffer_type type);
391 ia_css_get_acc_configs(
392 struct ia_css_pipe *pipe,
393 struct ia_css_isp_config *config);
395 #if CONFIG_ON_FRAME_ENQUEUE()
396 static int set_config_on_frame_enqueue(struct ia_css_frame_info
397 *info, struct frame_data_wrapper *frame);
400 #ifdef USE_INPUT_SYSTEM_VERSION_2401
401 static unsigned int get_crop_lines_for_bayer_order(const struct
402 ia_css_stream_config *config);
403 static unsigned int get_crop_columns_for_bayer_order(const struct
404 ia_css_stream_config *config);
405 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
406 unsigned int *extra_row, unsigned int *extra_column);
408 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
409 struct ia_css_pipe *pipes[],
410 bool *do_crop_status);
413 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe);
416 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
417 struct ia_css_resolution *effective_res);
421 sh_css_pipe_free_shading_table(struct ia_css_pipe *pipe)
425 IA_CSS_ERROR("NULL input parameter");
429 if (pipe->shading_table)
430 ia_css_shading_table_free(pipe->shading_table);
431 pipe->shading_table = NULL;
434 static enum ia_css_frame_format yuv420_copy_formats[] = {
435 IA_CSS_FRAME_FORMAT_NV12,
436 IA_CSS_FRAME_FORMAT_NV21,
437 IA_CSS_FRAME_FORMAT_YV12,
438 IA_CSS_FRAME_FORMAT_YUV420,
439 IA_CSS_FRAME_FORMAT_YUV420_16,
440 IA_CSS_FRAME_FORMAT_CSI_MIPI_YUV420_8,
441 IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8
444 static enum ia_css_frame_format yuv422_copy_formats[] = {
445 IA_CSS_FRAME_FORMAT_NV12,
446 IA_CSS_FRAME_FORMAT_NV16,
447 IA_CSS_FRAME_FORMAT_NV21,
448 IA_CSS_FRAME_FORMAT_NV61,
449 IA_CSS_FRAME_FORMAT_YV12,
450 IA_CSS_FRAME_FORMAT_YV16,
451 IA_CSS_FRAME_FORMAT_YUV420,
452 IA_CSS_FRAME_FORMAT_YUV420_16,
453 IA_CSS_FRAME_FORMAT_YUV422,
454 IA_CSS_FRAME_FORMAT_YUV422_16,
455 IA_CSS_FRAME_FORMAT_UYVY,
456 IA_CSS_FRAME_FORMAT_YUYV
459 /* Verify whether the selected output format is can be produced
460 * by the copy binary given the stream format.
463 verify_copy_out_frame_format(struct ia_css_pipe *pipe) {
464 enum ia_css_frame_format out_fmt = pipe->output_info[0].format;
465 unsigned int i, found = 0;
468 assert(pipe->stream);
470 switch (pipe->stream->config.input_config.format)
472 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
473 case ATOMISP_INPUT_FORMAT_YUV420_8:
474 for (i = 0; i < ARRAY_SIZE(yuv420_copy_formats) && !found; i++)
475 found = (out_fmt == yuv420_copy_formats[i]);
477 case ATOMISP_INPUT_FORMAT_YUV420_10:
478 case ATOMISP_INPUT_FORMAT_YUV420_16:
479 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
481 case ATOMISP_INPUT_FORMAT_YUV422_8:
482 for (i = 0; i < ARRAY_SIZE(yuv422_copy_formats) && !found; i++)
483 found = (out_fmt == yuv422_copy_formats[i]);
485 case ATOMISP_INPUT_FORMAT_YUV422_10:
486 case ATOMISP_INPUT_FORMAT_YUV422_16:
487 found = (out_fmt == IA_CSS_FRAME_FORMAT_YUV422_16 ||
488 out_fmt == IA_CSS_FRAME_FORMAT_YUV420_16);
490 case ATOMISP_INPUT_FORMAT_RGB_444:
491 case ATOMISP_INPUT_FORMAT_RGB_555:
492 case ATOMISP_INPUT_FORMAT_RGB_565:
493 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
494 out_fmt == IA_CSS_FRAME_FORMAT_RGB565);
496 case ATOMISP_INPUT_FORMAT_RGB_666:
497 case ATOMISP_INPUT_FORMAT_RGB_888:
498 found = (out_fmt == IA_CSS_FRAME_FORMAT_RGBA888 ||
499 out_fmt == IA_CSS_FRAME_FORMAT_YUV420);
501 case ATOMISP_INPUT_FORMAT_RAW_6:
502 case ATOMISP_INPUT_FORMAT_RAW_7:
503 case ATOMISP_INPUT_FORMAT_RAW_8:
504 case ATOMISP_INPUT_FORMAT_RAW_10:
505 case ATOMISP_INPUT_FORMAT_RAW_12:
506 case ATOMISP_INPUT_FORMAT_RAW_14:
507 case ATOMISP_INPUT_FORMAT_RAW_16:
508 found = (out_fmt == IA_CSS_FRAME_FORMAT_RAW) ||
509 (out_fmt == IA_CSS_FRAME_FORMAT_RAW_PACKED);
511 case ATOMISP_INPUT_FORMAT_BINARY_8:
512 found = (out_fmt == IA_CSS_FRAME_FORMAT_BINARY_8);
523 ia_css_stream_input_format_bits_per_pixel(struct ia_css_stream *stream)
528 bpp = ia_css_util_input_format_bpp(stream->config.input_config.format,
529 stream->config.pixels_per_clock == 2);
534 #define GP_ISEL_TPG_MODE 0x90058
536 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
538 sh_css_config_input_network(struct ia_css_stream *stream) {
539 unsigned int fmt_type;
540 struct ia_css_pipe *pipe = stream->last_pipe;
541 struct ia_css_binary *binary = NULL;
547 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
548 "sh_css_config_input_network() enter:\n");
550 if (pipe->pipeline.stages)
551 binary = pipe->pipeline.stages->binary;
553 err = ia_css_isys_convert_stream_format_to_mipi_format(
554 stream->config.input_config.format,
555 stream->csi_rx_config.comp,
559 sh_css_sp_program_input_circuit(fmt_type,
560 stream->config.channel_id,
561 stream->config.mode);
563 if ((binary && (binary->online || stream->config.continuous)) ||
564 pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
566 err = ia_css_ifmtr_configure(&stream->config,
572 if (stream->config.mode == IA_CSS_INPUT_MODE_TPG ||
573 stream->config.mode == IA_CSS_INPUT_MODE_PRBS)
575 unsigned int hblank_cycles = 100,
580 width = (stream->config.input_config.input_res.width) / (1 +
581 (stream->config.pixels_per_clock == 2));
582 height = stream->config.input_config.input_res.height;
583 vblank_cycles = vblank_lines * (width + hblank_cycles);
584 sh_css_sp_configure_sync_gen(width, height, hblank_cycles,
587 if (pipe->stream->config.mode == IA_CSS_INPUT_MODE_TPG) {
588 /* TODO: move define to proper file in tools */
589 ia_css_device_store_uint32(GP_ISEL_TPG_MODE, 0);
593 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
594 "sh_css_config_input_network() leave:\n");
597 #elif !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
598 static unsigned int csi2_protocol_calculate_max_subpixels_per_line(
599 enum atomisp_input_format format,
600 unsigned int pixels_per_line)
605 case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY:
607 * The frame format layout is shown below.
609 * Line 0: UYY0 UYY0 ... UYY0
610 * Line 1: VYY0 VYY0 ... VYY0
611 * Line 2: UYY0 UYY0 ... UYY0
612 * Line 3: VYY0 VYY0 ... VYY0
614 * Line (n-2): UYY0 UYY0 ... UYY0
615 * Line (n-1): VYY0 VYY0 ... VYY0
617 * In this frame format, the even-line is
618 * as wide as the odd-line.
619 * The 0 is introduced by the input system
622 rval = pixels_per_line * 2;
624 case ATOMISP_INPUT_FORMAT_YUV420_8:
625 case ATOMISP_INPUT_FORMAT_YUV420_10:
626 case ATOMISP_INPUT_FORMAT_YUV420_16:
628 * The frame format layout is shown below.
630 * Line 0: YYYY YYYY ... YYYY
631 * Line 1: UYVY UYVY ... UYVY UYVY
632 * Line 2: YYYY YYYY ... YYYY
633 * Line 3: UYVY UYVY ... UYVY UYVY
635 * Line (n-2): YYYY YYYY ... YYYY
636 * Line (n-1): UYVY UYVY ... UYVY UYVY
638 * In this frame format, the odd-line is twice
639 * wider than the even-line.
641 rval = pixels_per_line * 2;
643 case ATOMISP_INPUT_FORMAT_YUV422_8:
644 case ATOMISP_INPUT_FORMAT_YUV422_10:
645 case ATOMISP_INPUT_FORMAT_YUV422_16:
647 * The frame format layout is shown below.
649 * Line 0: UYVY UYVY ... UYVY
650 * Line 1: UYVY UYVY ... UYVY
651 * Line 2: UYVY UYVY ... UYVY
652 * Line 3: UYVY UYVY ... UYVY
654 * Line (n-2): UYVY UYVY ... UYVY
655 * Line (n-1): UYVY UYVY ... UYVY
657 * In this frame format, the even-line is
658 * as wide as the odd-line.
660 rval = pixels_per_line * 2;
662 case ATOMISP_INPUT_FORMAT_RGB_444:
663 case ATOMISP_INPUT_FORMAT_RGB_555:
664 case ATOMISP_INPUT_FORMAT_RGB_565:
665 case ATOMISP_INPUT_FORMAT_RGB_666:
666 case ATOMISP_INPUT_FORMAT_RGB_888:
668 * The frame format layout is shown below.
670 * Line 0: ABGR ABGR ... ABGR
671 * Line 1: ABGR ABGR ... ABGR
672 * Line 2: ABGR ABGR ... ABGR
673 * Line 3: ABGR ABGR ... ABGR
675 * Line (n-2): ABGR ABGR ... ABGR
676 * Line (n-1): ABGR ABGR ... ABGR
678 * In this frame format, the even-line is
679 * as wide as the odd-line.
681 rval = pixels_per_line * 4;
683 case ATOMISP_INPUT_FORMAT_RAW_6:
684 case ATOMISP_INPUT_FORMAT_RAW_7:
685 case ATOMISP_INPUT_FORMAT_RAW_8:
686 case ATOMISP_INPUT_FORMAT_RAW_10:
687 case ATOMISP_INPUT_FORMAT_RAW_12:
688 case ATOMISP_INPUT_FORMAT_RAW_14:
689 case ATOMISP_INPUT_FORMAT_RAW_16:
690 case ATOMISP_INPUT_FORMAT_BINARY_8:
691 case ATOMISP_INPUT_FORMAT_USER_DEF1:
692 case ATOMISP_INPUT_FORMAT_USER_DEF2:
693 case ATOMISP_INPUT_FORMAT_USER_DEF3:
694 case ATOMISP_INPUT_FORMAT_USER_DEF4:
695 case ATOMISP_INPUT_FORMAT_USER_DEF5:
696 case ATOMISP_INPUT_FORMAT_USER_DEF6:
697 case ATOMISP_INPUT_FORMAT_USER_DEF7:
698 case ATOMISP_INPUT_FORMAT_USER_DEF8:
700 * The frame format layout is shown below.
702 * Line 0: Pixel Pixel ... Pixel
703 * Line 1: Pixel Pixel ... Pixel
704 * Line 2: Pixel Pixel ... Pixel
705 * Line 3: Pixel Pixel ... Pixel
707 * Line (n-2): Pixel Pixel ... Pixel
708 * Line (n-1): Pixel Pixel ... Pixel
710 * In this frame format, the even-line is
711 * as wide as the odd-line.
713 rval = pixels_per_line;
723 static bool sh_css_translate_stream_cfg_to_input_system_input_port_id(
724 struct ia_css_stream_config *stream_cfg,
725 ia_css_isys_descr_t *isys_stream_descr)
730 switch (stream_cfg->mode) {
731 case IA_CSS_INPUT_MODE_TPG:
733 if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID0) {
734 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
735 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID1) {
736 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
737 } else if (stream_cfg->source.tpg.id == IA_CSS_TPG_ID2) {
738 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
742 case IA_CSS_INPUT_MODE_PRBS:
744 if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID0) {
745 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT0_ID;
746 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID1) {
747 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT1_ID;
748 } else if (stream_cfg->source.prbs.id == IA_CSS_PRBS_ID2) {
749 isys_stream_descr->input_port_id = INPUT_SYSTEM_PIXELGEN_PORT2_ID;
753 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
755 if (stream_cfg->source.port.port == MIPI_PORT0_ID) {
756 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT0_ID;
757 } else if (stream_cfg->source.port.port == MIPI_PORT1_ID) {
758 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT1_ID;
759 } else if (stream_cfg->source.port.port == MIPI_PORT2_ID) {
760 isys_stream_descr->input_port_id = INPUT_SYSTEM_CSI_PORT2_ID;
772 static bool sh_css_translate_stream_cfg_to_input_system_input_port_type(
773 struct ia_css_stream_config *stream_cfg,
774 ia_css_isys_descr_t *isys_stream_descr)
779 switch (stream_cfg->mode) {
780 case IA_CSS_INPUT_MODE_TPG:
782 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_TPG;
785 case IA_CSS_INPUT_MODE_PRBS:
787 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_PRBS;
790 case IA_CSS_INPUT_MODE_SENSOR:
791 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
793 isys_stream_descr->mode = INPUT_SYSTEM_SOURCE_TYPE_SENSOR;
804 static bool sh_css_translate_stream_cfg_to_input_system_input_port_attr(
805 struct ia_css_stream_config *stream_cfg,
806 ia_css_isys_descr_t *isys_stream_descr,
812 switch (stream_cfg->mode) {
813 case IA_CSS_INPUT_MODE_TPG:
814 if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_RAMP) {
815 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_RAMP;
816 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_CHECKERBOARD) {
817 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_CHBO;
818 } else if (stream_cfg->source.tpg.mode == IA_CSS_TPG_MODE_MONO) {
819 isys_stream_descr->tpg_port_attr.mode = PIXELGEN_TPG_MODE_MONO;
826 * - Make "color_cfg" as part of "ia_css_tpg_config".
828 isys_stream_descr->tpg_port_attr.color_cfg.R1 = 51;
829 isys_stream_descr->tpg_port_attr.color_cfg.G1 = 102;
830 isys_stream_descr->tpg_port_attr.color_cfg.B1 = 255;
831 isys_stream_descr->tpg_port_attr.color_cfg.R2 = 0;
832 isys_stream_descr->tpg_port_attr.color_cfg.G2 = 100;
833 isys_stream_descr->tpg_port_attr.color_cfg.B2 = 160;
835 isys_stream_descr->tpg_port_attr.mask_cfg.h_mask =
836 stream_cfg->source.tpg.x_mask;
837 isys_stream_descr->tpg_port_attr.mask_cfg.v_mask =
838 stream_cfg->source.tpg.y_mask;
839 isys_stream_descr->tpg_port_attr.mask_cfg.hv_mask =
840 stream_cfg->source.tpg.xy_mask;
842 isys_stream_descr->tpg_port_attr.delta_cfg.h_delta =
843 stream_cfg->source.tpg.x_delta;
844 isys_stream_descr->tpg_port_attr.delta_cfg.v_delta =
845 stream_cfg->source.tpg.y_delta;
849 * - Make "sync_gen_cfg" as part of "ia_css_tpg_config".
851 isys_stream_descr->tpg_port_attr.sync_gen_cfg.hblank_cycles = 100;
852 isys_stream_descr->tpg_port_attr.sync_gen_cfg.vblank_cycles = 100;
853 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_clock =
854 stream_cfg->pixels_per_clock;
855 isys_stream_descr->tpg_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
856 isys_stream_descr->tpg_port_attr.sync_gen_cfg.pixels_per_line =
857 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
858 isys_stream_descr->tpg_port_attr.sync_gen_cfg.lines_per_frame =
859 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
862 case IA_CSS_INPUT_MODE_PRBS:
864 isys_stream_descr->prbs_port_attr.seed0 = stream_cfg->source.prbs.seed;
865 isys_stream_descr->prbs_port_attr.seed1 = stream_cfg->source.prbs.seed1;
869 * - Make "sync_gen_cfg" as part of "ia_css_prbs_config".
871 isys_stream_descr->prbs_port_attr.sync_gen_cfg.hblank_cycles = 100;
872 isys_stream_descr->prbs_port_attr.sync_gen_cfg.vblank_cycles = 100;
873 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_clock =
874 stream_cfg->pixels_per_clock;
875 isys_stream_descr->prbs_port_attr.sync_gen_cfg.nr_of_frames = (uint32_t)~(0x0);
876 isys_stream_descr->prbs_port_attr.sync_gen_cfg.pixels_per_line =
877 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.width;
878 isys_stream_descr->prbs_port_attr.sync_gen_cfg.lines_per_frame =
879 stream_cfg->isys_config[IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX].input_res.height;
882 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR: {
884 unsigned int fmt_type;
886 err = ia_css_isys_convert_stream_format_to_mipi_format(
887 stream_cfg->isys_config[isys_stream_idx].format,
893 isys_stream_descr->csi_port_attr.active_lanes =
894 stream_cfg->source.port.num_lanes;
895 isys_stream_descr->csi_port_attr.fmt_type = fmt_type;
896 isys_stream_descr->csi_port_attr.ch_id = stream_cfg->channel_id;
897 #ifdef USE_INPUT_SYSTEM_VERSION_2401
898 isys_stream_descr->online = stream_cfg->online;
900 err |= ia_css_isys_convert_compressed_format(
901 &stream_cfg->source.port.compression,
907 isys_stream_descr->metadata.enable = false;
908 if (stream_cfg->metadata_config.resolution.height > 0) {
909 err = ia_css_isys_convert_stream_format_to_mipi_format(
910 stream_cfg->metadata_config.data_type,
915 isys_stream_descr->metadata.fmt_type = fmt_type;
916 isys_stream_descr->metadata.bits_per_pixel =
917 ia_css_util_input_format_bpp(stream_cfg->metadata_config.data_type, true);
918 isys_stream_descr->metadata.pixels_per_line =
919 stream_cfg->metadata_config.resolution.width;
920 isys_stream_descr->metadata.lines_per_frame =
921 stream_cfg->metadata_config.resolution.height;
922 #ifdef USE_INPUT_SYSTEM_VERSION_2401
923 /* For new input system, number of str2mmio requests must be even.
924 * So we round up number of metadata lines to be even. */
925 if (isys_stream_descr->metadata.lines_per_frame > 0)
926 isys_stream_descr->metadata.lines_per_frame +=
927 (isys_stream_descr->metadata.lines_per_frame & 1);
929 isys_stream_descr->metadata.align_req_in_bytes =
930 ia_css_csi2_calculate_input_system_alignment(
931 stream_cfg->metadata_config.data_type);
932 isys_stream_descr->metadata.enable = true;
945 static bool sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
946 struct ia_css_stream_config *stream_cfg,
947 ia_css_isys_descr_t *isys_stream_descr,
950 unsigned int bits_per_subpixel;
951 unsigned int max_subpixels_per_line;
952 unsigned int lines_per_frame;
953 unsigned int align_req_in_bytes;
954 enum atomisp_input_format fmt_type;
956 fmt_type = stream_cfg->isys_config[isys_stream_idx].format;
957 if ((stream_cfg->mode == IA_CSS_INPUT_MODE_SENSOR ||
958 stream_cfg->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) &&
959 stream_cfg->source.port.compression.type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) {
960 if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
961 UNCOMPRESSED_BITS_PER_PIXEL_10) {
962 fmt_type = ATOMISP_INPUT_FORMAT_RAW_10;
963 } else if (stream_cfg->source.port.compression.uncompressed_bits_per_pixel ==
964 UNCOMPRESSED_BITS_PER_PIXEL_12) {
965 fmt_type = ATOMISP_INPUT_FORMAT_RAW_12;
971 sh_css_stream_format_2_bits_per_subpixel(fmt_type);
972 if (bits_per_subpixel == 0)
975 max_subpixels_per_line =
976 csi2_protocol_calculate_max_subpixels_per_line(fmt_type,
977 stream_cfg->isys_config[isys_stream_idx].input_res.width);
978 if (max_subpixels_per_line == 0)
981 lines_per_frame = stream_cfg->isys_config[isys_stream_idx].input_res.height;
982 if (lines_per_frame == 0)
985 align_req_in_bytes = ia_css_csi2_calculate_input_system_alignment(fmt_type);
987 /* HW needs subpixel info for their settings */
988 isys_stream_descr->input_port_resolution.bits_per_pixel = bits_per_subpixel;
989 isys_stream_descr->input_port_resolution.pixels_per_line =
990 max_subpixels_per_line;
991 isys_stream_descr->input_port_resolution.lines_per_frame = lines_per_frame;
992 isys_stream_descr->input_port_resolution.align_req_in_bytes =
998 static bool sh_css_translate_stream_cfg_to_isys_stream_descr(
999 struct ia_css_stream_config *stream_cfg,
1001 ia_css_isys_descr_t *isys_stream_descr,
1002 int isys_stream_idx)
1006 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1007 "sh_css_translate_stream_cfg_to_isys_stream_descr() enter:\n");
1008 rc = sh_css_translate_stream_cfg_to_input_system_input_port_id(stream_cfg,
1010 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_type(stream_cfg,
1012 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_attr(stream_cfg,
1013 isys_stream_descr, isys_stream_idx);
1014 rc &= sh_css_translate_stream_cfg_to_input_system_input_port_resolution(
1015 stream_cfg, isys_stream_descr, isys_stream_idx);
1017 isys_stream_descr->raw_packed = stream_cfg->pack_raw_pixels;
1018 isys_stream_descr->linked_isys_stream_id = (int8_t)
1019 stream_cfg->isys_config[isys_stream_idx].linked_isys_stream_id;
1021 * Early polling is required for timestamp accuracy in certain case.
1022 * The ISYS HW polling is started on
1023 * ia_css_isys_stream_capture_indication() instead of
1024 * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of
1025 * capture takes longer than getting an ISYS frame
1027 * Only 2401 relevant ??
1029 #if 0 // FIXME: NOT USED on Yocto Aero
1030 isys_stream_descr->polling_mode
1031 = early_polling ? INPUT_SYSTEM_POLL_ON_CAPTURE_REQUEST
1032 : INPUT_SYSTEM_POLL_ON_WAIT_FOR_FRAME;
1033 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1034 "sh_css_translate_stream_cfg_to_isys_stream_descr() leave:\n");
1040 static bool sh_css_translate_binary_info_to_input_system_output_port_attr(
1041 struct ia_css_binary *binary,
1042 ia_css_isys_descr_t *isys_stream_descr)
1047 isys_stream_descr->output_port_attr.left_padding = binary->left_padding;
1048 isys_stream_descr->output_port_attr.max_isp_input_width =
1049 binary->info->sp.input.max_width;
1055 sh_css_config_input_network(struct ia_css_stream *stream) {
1057 ia_css_isys_descr_t isys_stream_descr;
1058 unsigned int sp_thread_id;
1059 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
1060 struct ia_css_pipe *pipe = NULL;
1061 struct ia_css_binary *binary = NULL;
1064 bool early_polling = false;
1067 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1068 "sh_css_config_input_network() enter 0x%p:\n", stream);
1070 if (stream->config.continuous == true)
1072 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1073 pipe = stream->last_pipe;
1074 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_YUVPP) {
1075 pipe = stream->last_pipe;
1076 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) {
1077 pipe = stream->last_pipe->pipe_settings.preview.copy_pipe;
1078 } else if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
1079 pipe = stream->last_pipe->pipe_settings.video.copy_pipe;
1083 pipe = stream->last_pipe;
1084 if (stream->last_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
1086 * We need to poll the ISYS HW in capture_indication itself
1087 * for "non-continuous" capture usecase for getting accurate
1088 * isys frame capture timestamps.
1089 * This is because the capturepipe propcessing takes longer
1090 * to execute than the input system frame capture.
1093 early_polling = true;
1101 if (pipe->pipeline.stages)
1102 if (pipe->pipeline.stages->binary)
1103 binary = pipe->pipeline.stages->binary;
1107 /* this was being done in ifmtr in 2400.
1108 * online and cont bypass the init_in_frameinfo_memory_defaults
1109 * so need to do it here
1111 ia_css_get_crop_offsets(pipe, &binary->in_frame_info);
1114 /* get the SP thread id */
1115 rc = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &sp_thread_id);
1118 /* get the target input terminal */
1119 sp_pipeline_input_terminal = &sh_css_sp_group.pipe_io[sp_thread_id].input;
1121 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1123 /* initialization */
1124 memset((void *)(&isys_stream_descr), 0, sizeof(ia_css_isys_descr_t));
1125 sp_pipeline_input_terminal->context.virtual_input_system_stream[i].valid = 0;
1126 sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i].valid = 0;
1128 if (!stream->config.isys_config[i].valid)
1131 /* translate the stream configuration to the Input System (2401) configuration */
1132 rc = sh_css_translate_stream_cfg_to_isys_stream_descr(
1135 &(isys_stream_descr), i);
1137 if (stream->config.online) {
1138 rc &= sh_css_translate_binary_info_to_input_system_output_port_attr(
1140 &(isys_stream_descr));
1146 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, i);
1148 /* create the virtual Input System (2401) */
1149 rc = ia_css_isys_stream_create(
1150 &(isys_stream_descr),
1151 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1156 /* calculate the configuration of the virtual Input System (2401) */
1157 rc = ia_css_isys_stream_calculate_cfg(
1158 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i],
1159 &(isys_stream_descr),
1160 &sp_pipeline_input_terminal->ctrl.virtual_input_system_stream_cfg[i]);
1162 ia_css_isys_stream_destroy(
1163 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i]);
1168 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1169 "sh_css_config_input_network() leave:\n");
1174 static inline struct ia_css_pipe *stream_get_last_pipe(
1175 struct ia_css_stream *stream)
1177 struct ia_css_pipe *last_pipe = NULL;
1180 last_pipe = stream->last_pipe;
1185 static inline struct ia_css_pipe *stream_get_copy_pipe(
1186 struct ia_css_stream *stream)
1188 struct ia_css_pipe *copy_pipe = NULL;
1189 struct ia_css_pipe *last_pipe = NULL;
1190 enum ia_css_pipe_id pipe_id;
1192 last_pipe = stream_get_last_pipe(stream);
1196 (stream->config.continuous)) {
1197 pipe_id = last_pipe->mode;
1199 case IA_CSS_PIPE_ID_PREVIEW:
1200 copy_pipe = last_pipe->pipe_settings.preview.copy_pipe;
1202 case IA_CSS_PIPE_ID_VIDEO:
1203 copy_pipe = last_pipe->pipe_settings.video.copy_pipe;
1214 static inline struct ia_css_pipe *stream_get_target_pipe(
1215 struct ia_css_stream *stream)
1217 struct ia_css_pipe *target_pipe;
1219 /* get the pipe that consumes the stream */
1220 if (stream->config.continuous) {
1221 target_pipe = stream_get_copy_pipe(stream);
1223 target_pipe = stream_get_last_pipe(stream);
1229 static int stream_csi_rx_helper(
1230 struct ia_css_stream *stream,
1231 int (*func)(enum mipi_port_id, uint32_t))
1233 int retval = -EINVAL;
1234 u32 sp_thread_id, stream_id;
1236 struct ia_css_pipe *target_pipe = NULL;
1238 if ((!stream) || (stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
1241 target_pipe = stream_get_target_pipe(stream);
1246 rc = ia_css_pipeline_get_sp_thread_id(
1247 ia_css_pipe_get_pipe_num(target_pipe),
1253 /* (un)register all valid "virtual isys streams" within the ia_css_stream */
1256 if (stream->config.isys_config[stream_id].valid) {
1257 u32 isys_stream_id = ia_css_isys_generate_stream_id(sp_thread_id, stream_id);
1259 retval = func(stream->config.source.port.port, isys_stream_id);
1262 } while ((retval == 0) &&
1263 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1269 static inline int stream_register_with_csi_rx(
1270 struct ia_css_stream *stream)
1272 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_register_stream);
1275 static inline int stream_unregister_with_csi_rx(
1276 struct ia_css_stream *stream)
1278 return stream_csi_rx_helper(stream, ia_css_isys_csi_rx_unregister_stream);
1282 #if WITH_PC_MONITORING
1283 static struct task_struct *my_kthread; /* Handle for the monitoring thread */
1284 static int sh_binary_running; /* Enable sampling in the thread */
1286 static void print_pc_histo(char *core_name, struct sh_css_pc_histogram *hist)
1289 unsigned int cnt_run = 0;
1290 unsigned int cnt_stall = 0;
1295 sh_css_print("%s histogram length = %d\n", core_name, hist->length);
1296 sh_css_print("%s PC\turn\tstall\n", core_name);
1298 for (i = 0; i < hist->length; i++) {
1299 if ((hist->run[i] == 0) && (hist->run[i] == hist->stall[i]))
1301 sh_css_print("%s %d\t%d\t%d\n",
1302 core_name, i, hist->run[i], hist->stall[i]);
1303 cnt_run += hist->run[i];
1304 cnt_stall += hist->stall[i];
1307 sh_css_print(" Statistics for %s, cnt_run = %d, cnt_stall = %d, hist->length = %d\n",
1308 core_name, cnt_run, cnt_stall, hist->length);
1311 static void print_pc_histogram(void)
1313 struct ia_css_binary_metrics *metrics;
1315 for (metrics = sh_css_metrics.binary_metrics;
1317 metrics = metrics->next) {
1318 if (metrics->mode == IA_CSS_BINARY_MODE_PREVIEW ||
1319 metrics->mode == IA_CSS_BINARY_MODE_VF_PP) {
1320 sh_css_print("pc_histogram for binary %d is SKIPPED\n",
1325 sh_css_print(" pc_histogram for binary %d\n", metrics->id);
1326 print_pc_histo(" ISP", &metrics->isp_histogram);
1327 print_pc_histo(" SP", &metrics->sp_histogram);
1328 sh_css_print("print_pc_histogram() done for binary->id = %d, done.\n",
1332 sh_css_print("PC_MONITORING:print_pc_histogram() -- DONE\n");
1335 static int pc_monitoring(void *data)
1341 if (sh_binary_running) {
1342 sh_css_metrics_sample_pcs();
1343 #if MULTIPLE_SAMPLES
1344 for (i = 0; i < NOF_SAMPLES; i++)
1345 sh_css_metrics_sample_pcs();
1348 usleep_range(10, 50);
1353 static void spying_thread_create(void)
1355 my_kthread = kthread_run(pc_monitoring, NULL, "sh_pc_monitor");
1356 sh_css_metrics_enable_pc_histogram(1);
1359 static void input_frame_info(struct ia_css_frame_info frame_info)
1361 sh_css_print("SH_CSS:input_frame_info() -- frame->info.res.width = %d, frame->info.res.height = %d, format = %d\n",
1362 frame_info.res.width, frame_info.res.height, frame_info.format);
1364 #endif /* WITH_PC_MONITORING */
1367 start_binary(struct ia_css_pipe *pipe,
1368 struct ia_css_binary *binary)
1370 struct ia_css_stream *stream;
1373 /* Acceleration uses firmware, the binary thus can be NULL */
1374 /* assert(binary != NULL); */
1378 #if !defined(HAS_NO_INPUT_SYSTEM)
1379 stream = pipe->stream;
1386 sh_css_metrics_start_binary(&binary->metrics);
1388 #if WITH_PC_MONITORING
1389 sh_css_print("PC_MONITORING: %s() -- binary id = %d , enable_dvs_envelope = %d\n",
1390 __func__, binary->info->sp.id,
1391 binary->info->sp.enable.dvs_envelope);
1392 input_frame_info(binary->in_frame_info);
1394 if (binary && binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_VIDEO)
1395 sh_binary_running = true;
1398 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1399 if (stream->reconfigure_css_rx) {
1400 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1401 pipe->stream->config.mode);
1402 stream->reconfigure_css_rx = false;
1407 /* start the copy function on the SP */
1409 start_copy_on_sp(struct ia_css_pipe *pipe,
1410 struct ia_css_frame *out_frame) {
1413 assert(pipe->stream);
1415 if ((!pipe) || (!pipe->stream))
1418 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1419 if (pipe->stream->reconfigure_css_rx)
1420 ia_css_isys_rx_disable();
1423 if (pipe->stream->config.input_config.format != ATOMISP_INPUT_FORMAT_BINARY_8)
1425 sh_css_sp_start_binary_copy(ia_css_pipe_get_pipe_num(pipe), out_frame, pipe->stream->config.pixels_per_clock == 2);
1427 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
1428 if (pipe->stream->reconfigure_css_rx)
1430 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
1431 pipe->stream->config.mode);
1432 pipe->stream->reconfigure_css_rx = false;
1439 void sh_css_binary_args_reset(struct sh_css_binary_args *args)
1443 for (i = 0; i < NUM_TNR_FRAMES; i++)
1444 args->tnr_frames[i] = NULL;
1445 for (i = 0; i < MAX_NUM_VIDEO_DELAY_FRAMES; i++)
1446 args->delay_frames[i] = NULL;
1447 args->in_frame = NULL;
1448 for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++)
1449 args->out_frame[i] = NULL;
1450 args->out_vf_frame = NULL;
1451 args->copy_vf = false;
1452 args->copy_output = true;
1453 args->vf_downscale_log2 = 0;
1456 static void start_pipe(
1457 struct ia_css_pipe *me,
1458 enum sh_css_pipe_config_override copy_ovrd,
1459 enum ia_css_input_mode input_mode)
1461 const struct ia_css_coordinate *coord = NULL;
1462 const struct ia_css_isp_parameters *params = NULL;
1464 #if defined(HAS_NO_INPUT_SYSTEM)
1468 IA_CSS_ENTER_PRIVATE("me = %p, copy_ovrd = %d, input_mode = %d",
1469 me, copy_ovrd, input_mode);
1471 assert(me); /* all callers are in this file and call with non null argument */
1474 coord = &me->config.internal_frame_origin_bqs_on_sctbl;
1475 params = me->stream->isp_params_configs;
1478 sh_css_sp_init_pipeline(&me->pipeline,
1480 (uint8_t)ia_css_pipe_get_pipe_num(me),
1481 me->config.default_capture_config.enable_xnr != 0,
1482 me->stream->config.pixels_per_clock == 2,
1483 me->stream->config.continuous,
1485 me->required_bds_factor,
1488 &me->stream->config.metadata_config,
1489 &me->stream->info.metadata_info
1490 #if !defined(HAS_NO_INPUT_SYSTEM)
1491 , (input_mode == IA_CSS_INPUT_MODE_MEMORY) ?
1492 (enum mipi_port_id)0 :
1493 me->stream->config.source.port.port,
1498 if (me->config.mode != IA_CSS_PIPE_MODE_COPY) {
1499 struct ia_css_pipeline_stage *stage;
1501 stage = me->pipeline.stages;
1503 me->pipeline.current_stage = stage;
1504 start_binary(me, stage->binary);
1507 IA_CSS_LEAVE_PRIVATE("void");
1511 sh_css_invalidate_shading_tables(struct ia_css_stream *stream)
1517 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1518 "sh_css_invalidate_shading_tables() enter:\n");
1520 for (i = 0; i < stream->num_pipes; i++) {
1521 assert(stream->pipes[i]);
1522 sh_css_pipe_free_shading_table(stream->pipes[i]);
1525 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
1526 "sh_css_invalidate_shading_tables() leave: return_void\n");
1530 enable_interrupts(enum ia_css_irq_type irq_type)
1532 #ifdef USE_INPUT_SYSTEM_VERSION_2
1533 enum mipi_port_id port;
1535 bool enable_pulse = irq_type != IA_CSS_IRQ_TYPE_EDGE;
1537 IA_CSS_ENTER_PRIVATE("");
1538 /* Enable IRQ on the SP which signals that SP goes to idle
1539 * (aka ready state) */
1540 cnd_sp_irq_enable(SP0_ID, true);
1541 /* Set the IRQ device 0 to either level or pulse */
1542 irq_enable_pulse(IRQ0_ID, enable_pulse);
1544 cnd_virq_enable_channel(virq_sp, true);
1546 /* Enable SW interrupt 0, this is used to signal ISYS events */
1547 cnd_virq_enable_channel(
1548 (enum virq_id)(IRQ_SW_CHANNEL0_ID + IRQ_SW_CHANNEL_OFFSET),
1550 /* Enable SW interrupt 1, this is used to signal PSYS events */
1551 cnd_virq_enable_channel(
1552 (enum virq_id)(IRQ_SW_CHANNEL1_ID + IRQ_SW_CHANNEL_OFFSET),
1554 #if !defined(HAS_IRQ_MAP_VERSION_2)
1555 /* IRQ_SW_CHANNEL2_ID does not exist on 240x systems */
1556 cnd_virq_enable_channel(
1557 (enum virq_id)(IRQ_SW_CHANNEL2_ID + IRQ_SW_CHANNEL_OFFSET),
1562 #ifdef USE_INPUT_SYSTEM_VERSION_2
1563 for (port = 0; port < N_MIPI_PORT_ID; port++)
1564 ia_css_isys_rx_enable_all_interrupts(port);
1567 IA_CSS_LEAVE_PRIVATE("");
1570 static bool sh_css_setup_spctrl_config(const struct ia_css_fw_info *fw,
1571 const char *program,
1572 ia_css_spctrl_cfg *spctrl_cfg)
1574 if ((!fw) || (!spctrl_cfg))
1576 spctrl_cfg->sp_entry = 0;
1577 spctrl_cfg->program_name = (char *)(program);
1579 spctrl_cfg->ddr_data_offset = fw->blob.data_source;
1580 spctrl_cfg->dmem_data_addr = fw->blob.data_target;
1581 spctrl_cfg->dmem_bss_addr = fw->blob.bss_target;
1582 spctrl_cfg->data_size = fw->blob.data_size;
1583 spctrl_cfg->bss_size = fw->blob.bss_size;
1585 spctrl_cfg->spctrl_config_dmem_addr = fw->info.sp.init_dmem_data;
1586 spctrl_cfg->spctrl_state_dmem_addr = fw->info.sp.sw_state;
1588 spctrl_cfg->code_size = fw->blob.size;
1589 spctrl_cfg->code = fw->blob.code;
1590 spctrl_cfg->sp_entry = fw->info.sp.sp_entry; /* entry function ptr on SP */
1596 ia_css_unload_firmware(void)
1598 if (sh_css_num_binaries) {
1599 /* we have already loaded before so get rid of the old stuff */
1600 ia_css_binary_uninit();
1601 sh_css_unload_firmware();
1603 fw_explicitly_loaded = false;
1607 ia_css_reset_defaults(struct sh_css *css)
1609 struct sh_css default_css;
1611 /* Reset everything to zero */
1612 memset(&default_css, 0, sizeof(default_css));
1614 /* Initialize the non zero values*/
1615 default_css.check_system_idle = true;
1616 default_css.num_cont_raw_frames = NUM_CONTINUOUS_FRAMES;
1618 /* All should be 0: but memset does it already.
1619 * default_css.num_mipi_frames[N_CSI_PORTS] = 0;
1622 default_css.irq_type = IA_CSS_IRQ_TYPE_EDGE;
1624 /*Set the defaults to the output */
1629 ia_css_load_firmware(struct device *dev, const struct ia_css_env *env,
1630 const struct ia_css_fw *fw) {
1638 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() enter\n");
1640 /* make sure we initialize my_css */
1641 if (my_css.flush != env->cpu_mem_env.flush)
1643 ia_css_reset_defaults(&my_css);
1644 my_css.flush = env->cpu_mem_env.flush;
1647 ia_css_unload_firmware(); /* in case we are called twice */
1648 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1651 err = ia_css_binary_init_infos();
1653 fw_explicitly_loaded = true;
1656 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_load_firmware() leave\n");
1661 ia_css_init(struct device *dev, const struct ia_css_env *env,
1662 const struct ia_css_fw *fw,
1664 enum ia_css_irq_type irq_type) {
1666 ia_css_spctrl_cfg spctrl_cfg;
1668 void (*flush_func)(struct ia_css_acc_fw *fw);
1669 hrt_data select, enable;
1672 * The C99 standard does not specify the exact object representation of structs;
1673 * the representation is compiler dependent.
1675 * The structs that are communicated between host and SP/ISP should have the
1676 * exact same object representation. The compiler that is used to compile the
1677 * firmware is hivecc.
1679 * To check if a different compiler, used to compile a host application, uses
1680 * another object representation, macros are defined specifying the size of
1681 * the structs as expected by the firmware.
1683 * A host application shall verify that a sizeof( ) of the struct is equal to
1684 * the SIZE_OF_XXX macro of the corresponding struct. If they are not
1685 * equal, functionality will break.
1687 /* Check struct sh_css_ddr_address_map */
1688 COMPILATION_ERROR_IF(sizeof(struct sh_css_ddr_address_map) != SIZE_OF_SH_CSS_DDR_ADDRESS_MAP_STRUCT);
1689 /* Check struct host_sp_queues */
1690 COMPILATION_ERROR_IF(sizeof(struct host_sp_queues) != SIZE_OF_HOST_SP_QUEUES_STRUCT);
1691 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_desc_s) != SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT);
1692 COMPILATION_ERROR_IF(sizeof(struct ia_css_circbuf_elem_s) != SIZE_OF_IA_CSS_CIRCBUF_ELEM_S_STRUCT);
1694 /* Check struct host_sp_communication */
1695 COMPILATION_ERROR_IF(sizeof(struct host_sp_communication) != SIZE_OF_HOST_SP_COMMUNICATION_STRUCT);
1696 COMPILATION_ERROR_IF(sizeof(struct sh_css_event_irq_mask) != SIZE_OF_SH_CSS_EVENT_IRQ_MASK_STRUCT);
1698 /* Check struct sh_css_hmm_buffer */
1699 COMPILATION_ERROR_IF(sizeof(struct sh_css_hmm_buffer) != SIZE_OF_SH_CSS_HMM_BUFFER_STRUCT);
1700 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_3a_statistics) != SIZE_OF_IA_CSS_ISP_3A_STATISTICS_STRUCT);
1701 COMPILATION_ERROR_IF(sizeof(struct ia_css_isp_dvs_statistics) != SIZE_OF_IA_CSS_ISP_DVS_STATISTICS_STRUCT);
1702 COMPILATION_ERROR_IF(sizeof(struct ia_css_metadata) != SIZE_OF_IA_CSS_METADATA_STRUCT);
1704 /* Check struct ia_css_init_dmem_cfg */
1705 COMPILATION_ERROR_IF(sizeof(struct ia_css_sp_init_dmem_cfg) != SIZE_OF_IA_CSS_SP_INIT_DMEM_CFG_STRUCT);
1707 if (!fw && !fw_explicitly_loaded)
1712 sh_css_printf = env->print_env.debug_print;
1714 IA_CSS_ENTER("void");
1716 flush_func = env->cpu_mem_env.flush;
1719 ia_css_pipeline_init();
1720 ia_css_queue_map_init();
1722 ia_css_device_access_init(&env->hw_access_env);
1724 select = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_select)
1725 & (~GPIO_FLASH_PIN_MASK);
1726 enable = gpio_reg_load(GPIO0_ID, _gpio_block_reg_do_e)
1727 | GPIO_FLASH_PIN_MASK;
1728 sh_css_mmu_set_page_table_base_index(mmu_l1_base);
1730 my_css_save.mmu_base = mmu_l1_base;
1732 ia_css_reset_defaults(&my_css);
1734 my_css_save.driver_env = *env;
1735 my_css.flush = flush_func;
1737 err = ia_css_rmgr_init();
1740 IA_CSS_LEAVE_ERR(err);
1744 IA_CSS_LOG("init: %d", my_css_save_initialized);
1746 if (!my_css_save_initialized)
1748 my_css_save_initialized = true;
1749 my_css_save.mode = sh_css_mode_working;
1750 memset(my_css_save.stream_seeds, 0,
1751 sizeof(struct sh_css_stream_seed) * MAX_ACTIVE_STREAMS);
1752 IA_CSS_LOG("init: %d mode=%d", my_css_save_initialized, my_css_save.mode);
1758 /* In case this has been programmed already, update internal
1759 data structure ... DEPRECATED */
1760 my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID);
1763 my_css.irq_type = irq_type;
1765 my_css_save.irq_type = irq_type;
1767 enable_interrupts(my_css.irq_type);
1769 /* configure GPIO to output mode */
1770 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_select, select);
1771 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_e, enable);
1772 gpio_reg_store(GPIO0_ID, _gpio_block_reg_do_0, 0);
1774 err = ia_css_refcount_init(REFCOUNT_SIZE);
1777 IA_CSS_LEAVE_ERR(err);
1780 err = sh_css_params_init();
1783 IA_CSS_LEAVE_ERR(err);
1788 ia_css_unload_firmware(); /* in case we already had firmware loaded */
1789 err = sh_css_load_firmware(dev, fw->data, fw->bytes);
1791 IA_CSS_LEAVE_ERR(err);
1794 err = ia_css_binary_init_infos();
1796 IA_CSS_LEAVE_ERR(err);
1799 fw_explicitly_loaded = false;
1801 my_css_save.loaded_fw = (struct ia_css_fw *)fw;
1804 if (!sh_css_setup_spctrl_config(&sh_css_sp_fw, SP_PROG_NAME, &spctrl_cfg))
1807 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1810 IA_CSS_LEAVE_ERR(err);
1814 #if WITH_PC_MONITORING
1818 sh_css_print("PC_MONITORING: %s() -- create thread DISABLED\n",
1820 spying_thread_create();
1823 if (!sh_css_hrt_system_is_idle())
1825 IA_CSS_LEAVE_ERR(-EBUSY);
1828 /* can be called here, queuing works, but:
1829 - when sp is started later, it will wipe queued items
1830 so for now we leave it for later and make sure
1831 updates are not called to frequently.
1832 sh_css_init_buffer_queues();
1835 #if defined(HAS_INPUT_SYSTEM_VERSION_2) && defined(HAS_INPUT_SYSTEM_VERSION_2401)
1836 #if defined(USE_INPUT_SYSTEM_VERSION_2)
1837 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 0);
1838 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
1839 gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1);
1843 #if !defined(HAS_NO_INPUT_SYSTEM)
1846 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1847 ISP2400_DMA_MAX_BURST_LENGTH);
1849 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1850 ISP2401_DMA_MAX_BURST_LENGTH);
1852 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1856 sh_css_params_map_and_store_default_gdc_lut();
1858 IA_CSS_LEAVE_ERR(err);
1863 ia_css_enable_isys_event_queue(bool enable) {
1864 if (sh_css_sp_is_running())
1866 sh_css_sp_enable_isys_event_queue(enable);
1870 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1872 sh_css_flush(struct ia_css_acc_fw *fw)
1874 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1875 if ((fw) && (my_css.flush))
1879 /* Mapping sp threads. Currently, this is done when a stream is created and
1880 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1881 * doing it from stream_create since we could run out of sp threads due to
1882 * allocation on inactive pipelines. */
1884 map_sp_threads(struct ia_css_stream *stream, bool map) {
1885 struct ia_css_pipe *main_pipe = NULL;
1886 struct ia_css_pipe *copy_pipe = NULL;
1887 struct ia_css_pipe *capture_pipe = NULL;
1888 struct ia_css_pipe *acc_pipe = NULL;
1890 enum ia_css_pipe_id pipe_id;
1893 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1894 stream, map ? "true" : "false");
1898 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1902 main_pipe = stream->last_pipe;
1903 pipe_id = main_pipe->mode;
1905 ia_css_pipeline_map(main_pipe->pipe_num, map);
1909 case IA_CSS_PIPE_ID_PREVIEW:
1910 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1911 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1912 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1915 case IA_CSS_PIPE_ID_VIDEO:
1916 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1917 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1920 case IA_CSS_PIPE_ID_CAPTURE:
1921 case IA_CSS_PIPE_ID_ACC:
1928 ia_css_pipeline_map(acc_pipe->pipe_num, map);
1933 ia_css_pipeline_map(capture_pipe->pipe_num, map);
1936 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
1939 ia_css_pipeline_map(copy_pipe->pipe_num, map);
1941 /* DH regular multi pipe - not continuous mode: map the next pipes too */
1942 if (!stream->config.continuous)
1946 for (i = 1; i < stream->num_pipes; i++)
1947 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
1950 IA_CSS_LEAVE_ERR_PRIVATE(err);
1954 /* creates a host pipeline skeleton for all pipes in a stream. Called during
1957 create_host_pipeline_structure(struct ia_css_stream *stream) {
1958 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1959 struct ia_css_pipe *acc_pipe = NULL;
1960 enum ia_css_pipe_id pipe_id;
1961 struct ia_css_pipe *main_pipe = NULL;
1963 unsigned int copy_pipe_delay = 0,
1964 capture_pipe_delay = 0;
1967 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1971 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1975 main_pipe = stream->last_pipe;
1979 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
1983 pipe_id = main_pipe->mode;
1987 case IA_CSS_PIPE_ID_PREVIEW:
1988 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1989 copy_pipe_delay = main_pipe->dvs_frame_delay;
1990 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1991 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1992 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1993 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1994 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
1997 case IA_CSS_PIPE_ID_VIDEO:
1998 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1999 copy_pipe_delay = main_pipe->dvs_frame_delay;
2000 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2001 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2002 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2003 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2006 case IA_CSS_PIPE_ID_CAPTURE:
2007 capture_pipe = main_pipe;
2008 capture_pipe_delay = main_pipe->dvs_frame_delay;
2011 case IA_CSS_PIPE_ID_YUVPP:
2012 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2013 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2016 case IA_CSS_PIPE_ID_ACC:
2017 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2018 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2025 if (!(err) && copy_pipe)
2027 err = ia_css_pipeline_create(©_pipe->pipeline,
2029 copy_pipe->pipe_num,
2033 if (!(err) && capture_pipe)
2035 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2037 capture_pipe->pipe_num,
2038 capture_pipe_delay);
2041 if (!(err) && acc_pipe)
2043 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
2044 acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2047 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2048 if (!stream->config.continuous)
2052 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
2053 main_pipe = stream->pipes[i];
2054 err = ia_css_pipeline_create(&main_pipe->pipeline,
2056 main_pipe->pipe_num,
2057 main_pipe->dvs_frame_delay);
2061 IA_CSS_LEAVE_ERR_PRIVATE(err);
2065 /* creates a host pipeline for all pipes in a stream. Called during
2068 create_host_pipeline(struct ia_css_stream *stream) {
2069 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2070 struct ia_css_pipe *acc_pipe = NULL;
2071 enum ia_css_pipe_id pipe_id;
2072 struct ia_css_pipe *main_pipe = NULL;
2074 unsigned int max_input_width = 0;
2076 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2079 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2083 main_pipe = stream->last_pipe;
2084 pipe_id = main_pipe->mode;
2086 /* No continuous frame allocation for capture pipe. It uses the
2087 * "main" pipe's frames. */
2088 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2089 (pipe_id == IA_CSS_PIPE_ID_VIDEO))
2091 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2092 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2093 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2094 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2095 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2097 if (stream->config.continuous ||
2098 (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
2099 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2100 err = alloc_continuous_frames(main_pipe, true);
2106 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2107 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2108 if (pipe_id != IA_CSS_PIPE_ID_ACC)
2110 err = allocate_mipi_frames(main_pipe, &stream->info);
2114 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2115 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2116 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY))
2118 err = allocate_mipi_frames(main_pipe, &stream->info);
2126 case IA_CSS_PIPE_ID_PREVIEW:
2127 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2128 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2129 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2131 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2133 err = create_host_preview_pipeline(main_pipe);
2139 case IA_CSS_PIPE_ID_VIDEO:
2140 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2141 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2143 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2145 err = create_host_video_pipeline(main_pipe);
2151 case IA_CSS_PIPE_ID_CAPTURE:
2152 capture_pipe = main_pipe;
2156 case IA_CSS_PIPE_ID_YUVPP:
2157 err = create_host_yuvpp_pipeline(main_pipe);
2163 case IA_CSS_PIPE_ID_ACC:
2164 err = create_host_acc_pipeline(main_pipe);
2177 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2178 main_pipe->continuous_frames[0]);
2185 err = create_host_capture_pipeline(capture_pipe);
2192 err = create_host_acc_pipeline(acc_pipe);
2197 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2198 if (!stream->config.continuous)
2202 for (i = 1; i < stream->num_pipes && 0 == err; i++) {
2203 switch (stream->pipes[i]->mode) {
2204 case IA_CSS_PIPE_ID_PREVIEW:
2205 err = create_host_preview_pipeline(stream->pipes[i]);
2207 case IA_CSS_PIPE_ID_VIDEO:
2208 err = create_host_video_pipeline(stream->pipes[i]);
2210 case IA_CSS_PIPE_ID_CAPTURE:
2211 err = create_host_capture_pipeline(stream->pipes[i]);
2213 case IA_CSS_PIPE_ID_YUVPP:
2214 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2216 case IA_CSS_PIPE_ID_ACC:
2217 err = create_host_acc_pipeline(stream->pipes[i]);
2228 IA_CSS_LEAVE_ERR_PRIVATE(err);
2232 static const struct ia_css_pipe default_pipe = IA_CSS_DEFAULT_PIPE;
2233 static const struct ia_css_preview_settings preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2234 static const struct ia_css_capture_settings capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2235 static const struct ia_css_video_settings video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2236 static const struct ia_css_yuvpp_settings yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2239 init_pipe_defaults(enum ia_css_pipe_mode mode,
2240 struct ia_css_pipe *pipe,
2245 IA_CSS_ERROR("NULL pipe parameter");
2249 /* Initialize pipe to pre-defined defaults */
2250 memcpy(pipe, &default_pipe, sizeof(default_pipe));
2252 /* TODO: JB should not be needed, but temporary backward reference */
2255 case IA_CSS_PIPE_MODE_PREVIEW:
2256 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2257 memcpy(&pipe->pipe_settings.preview, &preview, sizeof(preview));
2259 case IA_CSS_PIPE_MODE_CAPTURE:
2261 pipe->mode = IA_CSS_PIPE_ID_COPY;
2263 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2265 memcpy(&pipe->pipe_settings.capture, &capture, sizeof(capture));
2267 case IA_CSS_PIPE_MODE_VIDEO:
2268 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2269 memcpy(&pipe->pipe_settings.video, &video, sizeof(video));
2271 case IA_CSS_PIPE_MODE_ACC:
2272 pipe->mode = IA_CSS_PIPE_ID_ACC;
2274 case IA_CSS_PIPE_MODE_COPY:
2275 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2277 case IA_CSS_PIPE_MODE_YUVPP:
2278 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2279 memcpy(&pipe->pipe_settings.yuvpp, &yuvpp, sizeof(yuvpp));
2289 pipe_global_init(void)
2293 my_css.pipe_counter = 0;
2294 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2295 my_css.all_pipes[i] = NULL;
2300 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
2301 unsigned int *pipe_number) {
2302 const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
2303 u8 pipe_num = INVALID_PIPE_NUM;
2308 IA_CSS_ERROR("NULL pipe parameter");
2312 /* Assign a new pipe_num .... search for empty place */
2313 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
2315 if (!my_css.all_pipes[i]) {
2316 /*position is reserved */
2317 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2322 if (pipe_num == INVALID_PIPE_NUM)
2324 /* Max number of pipes already allocated */
2325 IA_CSS_ERROR("Max number of pipes already created");
2329 my_css.pipe_counter++;
2331 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2333 *pipe_number = pipe_num;
2338 pipe_release_pipe_num(unsigned int pipe_num)
2340 my_css.all_pipes[pipe_num] = NULL;
2341 my_css.pipe_counter--;
2342 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2343 "pipe_release_pipe_num (%d)\n", pipe_num);
2347 create_pipe(enum ia_css_pipe_mode mode,
2348 struct ia_css_pipe **pipe,
2351 struct ia_css_pipe *me;
2355 IA_CSS_ERROR("NULL pipe parameter");
2359 me = kmalloc(sizeof(*me), GFP_KERNEL);
2363 err = init_pipe_defaults(mode, me, copy_pipe);
2370 err = pipe_generate_pipe_num(me, &me->pipe_num);
2381 struct ia_css_pipe *
2382 find_pipe_by_num(uint32_t pipe_num)
2386 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2387 if (my_css.all_pipes[i] &&
2388 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2389 return my_css.all_pipes[i];
2395 static void sh_css_pipe_free_acc_binaries(
2396 struct ia_css_pipe *pipe)
2398 struct ia_css_pipeline *pipeline;
2399 struct ia_css_pipeline_stage *stage;
2403 IA_CSS_ERROR("NULL input pointer");
2406 pipeline = &pipe->pipeline;
2408 /* loop through the stages and unload them */
2409 for (stage = pipeline->stages; stage; stage = stage->next) {
2410 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2413 ia_css_pipe_unload_extension(pipe, firmware);
2418 ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
2421 IA_CSS_ENTER("pipe = %p", pipe);
2425 IA_CSS_LEAVE_ERR(-EINVAL);
2431 IA_CSS_LOG("ia_css_stream_destroy not called!");
2432 IA_CSS_LEAVE_ERR(-EINVAL);
2436 switch (pipe->config.mode)
2438 case IA_CSS_PIPE_MODE_PREVIEW:
2439 /* need to take into account that this function is also called
2440 on the internal copy pipe */
2441 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2442 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2443 pipe->continuous_frames);
2444 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2445 pipe->cont_md_buffers);
2446 if (pipe->pipe_settings.preview.copy_pipe) {
2447 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2448 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2449 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2454 case IA_CSS_PIPE_MODE_VIDEO:
2455 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2456 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2457 pipe->continuous_frames);
2458 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2459 pipe->cont_md_buffers);
2460 if (pipe->pipe_settings.video.copy_pipe) {
2461 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2462 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2463 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2468 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2469 pipe->pipe_settings.video.tnr_frames);
2471 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2472 pipe->pipe_settings.video.tnr_frames);
2474 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2475 pipe->pipe_settings.video.delay_frames);
2477 case IA_CSS_PIPE_MODE_CAPTURE:
2478 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2479 pipe->pipe_settings.capture.delay_frames);
2481 case IA_CSS_PIPE_MODE_ACC:
2482 sh_css_pipe_free_acc_binaries(pipe);
2484 case IA_CSS_PIPE_MODE_COPY:
2486 case IA_CSS_PIPE_MODE_YUVPP:
2490 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2491 pipe->scaler_pp_lut = mmgr_NULL;
2493 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2494 sh_css_pipe_free_shading_table(pipe);
2496 ia_css_pipeline_destroy(&pipe->pipeline);
2497 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2499 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2500 if (pipe->config.acc_extension)
2502 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2505 IA_CSS_LEAVE("err = %d", err);
2512 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2513 #if WITH_PC_MONITORING
2514 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2515 print_pc_histogram();
2518 sh_css_params_free_default_gdc_lut();
2520 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2521 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2522 /* cleanup generic data */
2523 sh_css_params_uninit();
2524 ia_css_refcount_uninit();
2526 ia_css_rmgr_uninit();
2528 #if !defined(HAS_NO_INPUT_FORMATTER)
2529 /* needed for reprogramming the inputformatter after power cycle of css */
2530 ifmtr_set_if_blocking_mode_reset = true;
2533 if (!fw_explicitly_loaded) {
2534 ia_css_unload_firmware();
2536 ia_css_spctrl_unload_fw(SP0_ID);
2537 sh_css_sp_set_sp_running(false);
2538 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2539 /* check and free any remaining mipi frames */
2540 free_mipi_frames(NULL);
2543 sh_css_sp_reset_global_vars();
2545 #if !defined(HAS_NO_INPUT_SYSTEM)
2546 ia_css_isys_uninit();
2549 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2552 #if defined(HAS_IRQ_MAP_VERSION_2)
2553 int ia_css_irq_translate(
2554 unsigned int *irq_infos)
2557 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2558 unsigned int infos = 0;
2560 /* irq_infos can be NULL, but that would make the function useless */
2561 /* assert(irq_infos != NULL); */
2562 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2563 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2565 while (status == hrt_isp_css_irq_status_more_irqs) {
2566 status = virq_get_channel_id(&irq);
2567 if (status == hrt_isp_css_irq_status_error)
2570 #if WITH_PC_MONITORING
2571 sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n",
2573 sh_binary_running = 0;
2578 /* When SP goes to idle, info is available in the
2580 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2584 #if !defined(HAS_NO_INPUT_SYSTEM)
2586 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2589 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2592 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2595 #if !defined(HAS_NO_INPUT_FORMATTER)
2597 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2601 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2604 infos |= sh_css_get_sw_interrupt_value(0);
2607 infos |= sh_css_get_sw_interrupt_value(1);
2608 /* pqiao TODO: also assumption here */
2618 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2619 "ia_css_irq_translate() leave: irq_infos=%u\n",
2625 int ia_css_irq_enable(
2626 enum ia_css_irq_info info,
2629 enum virq_id irq = N_virq_id;
2631 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2634 #if !defined(HAS_NO_INPUT_FORMATTER)
2635 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2636 irq = virq_isys_sof;
2638 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2639 irq = virq_isys_eof;
2641 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2642 irq = virq_isys_csi;
2644 case IA_CSS_IRQ_INFO_IF_ERROR:
2645 irq = virq_ifmt0_id;
2648 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2649 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2650 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2651 case IA_CSS_IRQ_INFO_IF_ERROR:
2652 /* Just ignore those unused IRQs without printing errors */
2655 case IA_CSS_IRQ_INFO_DMA_ERROR:
2658 case IA_CSS_IRQ_INFO_SW_0:
2659 irq = virq_sw_pin_0;
2661 case IA_CSS_IRQ_INFO_SW_1:
2662 irq = virq_sw_pin_1;
2665 IA_CSS_LEAVE_ERR(-EINVAL);
2669 cnd_virq_enable_channel(irq, enable);
2671 IA_CSS_LEAVE_ERR(0);
2676 #error "sh_css.c: IRQ MAP must be one of { IRQ_MAP_VERSION_2 }"
2680 sh_css_get_sw_interrupt_value(unsigned int irq)
2682 unsigned int irq_value;
2684 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2685 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2686 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2687 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2688 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2692 /* configure and load the copy binary, the next binary is used to
2693 determine whether the copy binary needs to do left padding. */
2694 static int load_copy_binary(
2695 struct ia_css_pipe *pipe,
2696 struct ia_css_binary *copy_binary,
2697 struct ia_css_binary *next_binary)
2699 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2700 unsigned int left_padding;
2702 struct ia_css_binary_descr copy_descr;
2704 /* next_binary can be NULL */
2706 assert(copy_binary);
2707 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2708 "load_copy_binary() enter:\n");
2711 copy_out_info = next_binary->in_frame_info;
2712 left_padding = next_binary->left_padding;
2714 copy_out_info = pipe->output_info[0];
2715 copy_vf_info = pipe->vf_output_info[0];
2716 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2720 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2721 ©_in_info, ©_out_info,
2722 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/);
2723 err = ia_css_binary_find(©_descr, copy_binary);
2726 copy_binary->left_padding = left_padding;
2731 alloc_continuous_frames(
2732 struct ia_css_pipe *pipe, bool init_time) {
2734 struct ia_css_frame_info ref_info;
2735 enum ia_css_pipe_id pipe_id;
2737 unsigned int i, idx;
2738 unsigned int num_frames;
2739 struct ia_css_pipe *capture_pipe = NULL;
2741 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2743 if ((!pipe) || (!pipe->stream))
2745 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2749 pipe_id = pipe->mode;
2750 continuous = pipe->stream->config.continuous;
2755 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2756 pipe->stream->continuous_pipe = pipe;
2758 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2761 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2764 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2766 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2767 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2769 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2772 /* should not happen */
2773 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2777 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2778 /* For CSI2+, the continuous frame will hold the full input frame */
2779 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2780 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2782 /* Ensure padded width is aligned for 2401 */
2783 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2786 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2787 if (pipe->stream->config.pack_raw_pixels)
2789 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2790 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2791 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2795 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2796 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2797 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2800 /* Write format back to binary */
2801 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2803 pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2805 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2806 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2808 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2809 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2812 /* should not happen */
2813 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
2820 idx = pipe->stream->config.init_num_cont_raw_buf;
2822 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++)
2824 /* free previous frame */
2825 if (pipe->continuous_frames[i]) {
2826 ia_css_frame_free(pipe->continuous_frames[i]);
2827 pipe->continuous_frames[i] = NULL;
2829 /* free previous metadata buffer */
2830 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2831 pipe->cont_md_buffers[i] = NULL;
2833 /* check if new frame needed */
2834 if (i < num_frames) {
2835 /* allocate new frame */
2836 err = ia_css_frame_allocate_from_info(
2837 &pipe->continuous_frames[i],
2840 IA_CSS_LEAVE_ERR_PRIVATE(err);
2843 /* allocate metadata buffer */
2844 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2845 &pipe->stream->info.metadata_info);
2848 IA_CSS_LEAVE_ERR_PRIVATE(0);
2853 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) {
2856 return alloc_continuous_frames(stream->continuous_pipe, false);
2860 load_preview_binaries(struct ia_css_pipe *pipe) {
2861 struct ia_css_frame_info prev_in_info,
2865 struct ia_css_binary_descr preview_descr;
2868 bool continuous, need_vf_pp = false;
2869 bool need_isp_copy_binary = false;
2870 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2871 bool sensor = false;
2873 /* preview only have 1 output pin now */
2874 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2875 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2877 IA_CSS_ENTER_PRIVATE("");
2879 assert(pipe->stream);
2880 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2882 online = pipe->stream->config.online;
2883 continuous = pipe->stream->config.continuous;
2884 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2885 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2888 if (mycs->preview_binary.info)
2891 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2894 err = ia_css_frame_check_info(pipe_out_info);
2898 /* Note: the current selection of vf_pp binary and
2899 * parameterization of the preview binary contains a few pieces
2900 * of hardcoded knowledge. This needs to be cleaned up such that
2901 * the binary selection becomes more generic.
2902 * The vf_pp binary is needed if one or more of the following features
2904 * 1. YUV downscaling.
2906 * 3. An output format that is not supported by the preview binary.
2907 * In practice this means something other than yuv_line or nv12.
2908 * The decision if the vf_pp binary is needed for YUV downscaling is
2909 * made after the preview binary selection, since some preview binaries
2910 * can perform the requested YUV downscaling.
2912 need_vf_pp = pipe->config.enable_dz;
2913 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2914 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2915 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2916 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2918 /* Preview step 1 */
2919 if (pipe->vf_yuv_ds_input_info.res.width)
2920 prev_vf_info = pipe->vf_yuv_ds_input_info;
2922 prev_vf_info = *pipe_out_info;
2923 /* If vf_pp is needed, then preview must output yuv_line.
2924 * The exception is when vf_pp is manually disabled, that is only
2925 * used in combination with a pipeline extension that requires
2926 * yuv_line as input.
2929 ia_css_frame_info_set_format(&prev_vf_info,
2930 IA_CSS_FRAME_FORMAT_YUV_LINE);
2932 err = ia_css_pipe_get_preview_binarydesc(
2941 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2946 /* The delay latency determines the number of invalid frames after
2947 * a stream is started. */
2948 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2949 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2951 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2952 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2953 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2956 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2957 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2958 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2960 /* When vf_pp is needed, then the output format of the selected
2961 * preview binary must be yuv_line. If this is not the case,
2962 * then the preview binary selection is done again.
2965 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE))
2967 /* Preview step 2 */
2968 if (pipe->vf_yuv_ds_input_info.res.width)
2969 prev_vf_info = pipe->vf_yuv_ds_input_info;
2971 prev_vf_info = *pipe_out_info;
2973 ia_css_frame_info_set_format(&prev_vf_info,
2974 IA_CSS_FRAME_FORMAT_YUV_LINE);
2976 err = ia_css_pipe_get_preview_binarydesc(
2985 err = ia_css_binary_find(&preview_descr,
2986 &mycs->preview_binary);
2993 struct ia_css_binary_descr vf_pp_descr;
2995 /* Viewfinder post-processing */
2996 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
2997 &mycs->preview_binary.out_frame_info[0],
2999 err = ia_css_binary_find(&vf_pp_descr,
3000 &mycs->vf_pp_binary);
3005 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3006 /* When the input system is 2401, only the Direct Sensor Mode
3007 * Offline Preview uses the ISP copy binary.
3009 need_isp_copy_binary = !online && sensor;
3011 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3012 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3013 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3014 * copies sensor data to DDR) does not have much use.
3017 need_isp_copy_binary = !online && !continuous;
3019 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3023 if (need_isp_copy_binary)
3025 err = load_copy_binary(pipe,
3027 &mycs->preview_binary);
3032 if (pipe->shading_table)
3034 ia_css_shading_table_free(pipe->shading_table);
3035 pipe->shading_table = NULL;
3042 ia_css_binary_unload(struct ia_css_binary *binary)
3044 ia_css_binary_destroy_isp_parameters(binary);
3048 unload_preview_binaries(struct ia_css_pipe *pipe) {
3049 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3051 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3053 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3056 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3057 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3058 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3060 IA_CSS_LEAVE_ERR_PRIVATE(0);
3064 static const struct ia_css_fw_info *last_output_firmware(
3065 const struct ia_css_fw_info *fw)
3067 const struct ia_css_fw_info *last_fw = NULL;
3068 /* fw can be NULL */
3069 IA_CSS_ENTER_LEAVE_PRIVATE("");
3071 for (; fw; fw = fw->next) {
3072 const struct ia_css_fw_info *info = fw;
3074 if (info->info.isp.sp.enable.output)
3080 static int add_firmwares(
3081 struct ia_css_pipeline *me,
3082 struct ia_css_binary *binary,
3083 const struct ia_css_fw_info *fw,
3084 const struct ia_css_fw_info *last_fw,
3085 unsigned int binary_mode,
3086 struct ia_css_frame *in_frame,
3087 struct ia_css_frame *out_frame,
3088 struct ia_css_frame *vf_frame,
3089 struct ia_css_pipeline_stage **my_stage,
3090 struct ia_css_pipeline_stage **vf_stage)
3093 struct ia_css_pipeline_stage *extra_stage = NULL;
3094 struct ia_css_pipeline_stage_desc stage_desc;
3096 /* all args can be NULL ??? */
3097 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3098 "add_firmwares() enter:\n");
3100 for (; fw; fw = fw->next) {
3101 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3102 struct ia_css_frame *in = NULL;
3103 struct ia_css_frame *vf = NULL;
3105 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3108 if (fw->info.isp.sp.enable.in_frame != 0) {
3111 if (fw->info.isp.sp.enable.out_frame != 0) {
3114 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3115 out, in, vf, fw, binary_mode);
3116 err = ia_css_pipeline_create_and_add_stage(me,
3121 if (fw->info.isp.sp.enable.output != 0)
3122 in_frame = extra_stage->args.out_frame[0];
3123 if (my_stage && !*my_stage && extra_stage)
3124 *my_stage = extra_stage;
3125 if (vf_stage && !*vf_stage && extra_stage &&
3126 fw->info.isp.sp.enable.vf_veceven)
3127 *vf_stage = extra_stage;
3132 static int add_vf_pp_stage(
3133 struct ia_css_pipe *pipe,
3134 struct ia_css_frame *in_frame,
3135 struct ia_css_frame *out_frame,
3136 struct ia_css_binary *vf_pp_binary,
3137 struct ia_css_pipeline_stage **vf_pp_stage)
3139 struct ia_css_pipeline *me = NULL;
3140 const struct ia_css_fw_info *last_fw = NULL;
3142 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3143 struct ia_css_pipeline_stage_desc stage_desc;
3145 /* out_frame can be NULL ??? */
3156 ia_css_pipe_util_create_output_frames(out_frames);
3157 me = &pipe->pipeline;
3159 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3160 "add_vf_pp_stage() enter:\n");
3162 *vf_pp_stage = NULL;
3164 last_fw = last_output_firmware(pipe->vf_stage);
3165 if (!pipe->extra_config.disable_vf_pp) {
3167 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3168 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3169 out_frames, in_frame, NULL);
3171 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3172 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3173 out_frames, in_frame, NULL);
3175 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3178 in_frame = (*vf_pp_stage)->args.out_frame[0];
3180 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3181 IA_CSS_BINARY_MODE_VF_PP,
3182 in_frame, out_frame, NULL,
3187 static int add_yuv_scaler_stage(
3188 struct ia_css_pipe *pipe,
3189 struct ia_css_pipeline *me,
3190 struct ia_css_frame *in_frame,
3191 struct ia_css_frame *out_frame,
3192 struct ia_css_frame *internal_out_frame,
3193 struct ia_css_binary *yuv_scaler_binary,
3194 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3196 const struct ia_css_fw_info *last_fw;
3198 struct ia_css_frame *vf_frame = NULL;
3199 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3200 struct ia_css_pipeline_stage_desc stage_desc;
3202 /* out_frame can be NULL ??? */
3206 assert(yuv_scaler_binary);
3207 assert(pre_vf_pp_stage);
3208 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3209 "add_yuv_scaler_stage() enter:\n");
3211 *pre_vf_pp_stage = NULL;
3212 ia_css_pipe_util_create_output_frames(out_frames);
3214 last_fw = last_output_firmware(pipe->output_stage);
3217 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3218 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3219 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3221 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3222 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3223 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3224 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3226 err = ia_css_pipeline_create_and_add_stage(me,
3231 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3233 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3234 IA_CSS_BINARY_MODE_CAPTURE_PP,
3235 in_frame, out_frame, vf_frame,
3236 NULL, pre_vf_pp_stage);
3237 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3238 (*pre_vf_pp_stage)->args.vf_downscale_log2 =
3239 yuv_scaler_binary->vf_downscale_log2;
3241 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3242 "add_yuv_scaler_stage() leave:\n");
3246 static int add_capture_pp_stage(
3247 struct ia_css_pipe *pipe,
3248 struct ia_css_pipeline *me,
3249 struct ia_css_frame *in_frame,
3250 struct ia_css_frame *out_frame,
3251 struct ia_css_binary *capture_pp_binary,
3252 struct ia_css_pipeline_stage **capture_pp_stage)
3254 const struct ia_css_fw_info *last_fw = NULL;
3256 struct ia_css_frame *vf_frame = NULL;
3257 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3258 struct ia_css_pipeline_stage_desc stage_desc;
3260 /* out_frame can be NULL ??? */
3264 assert(capture_pp_binary);
3265 assert(capture_pp_stage);
3266 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3267 "add_capture_pp_stage() enter:\n");
3269 *capture_pp_stage = NULL;
3270 ia_css_pipe_util_create_output_frames(out_frames);
3272 last_fw = last_output_firmware(pipe->output_stage);
3273 err = ia_css_frame_allocate_from_info(&vf_frame,
3274 &capture_pp_binary->vf_frame_info);
3278 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3279 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3280 capture_pp_binary, out_frames, NULL, vf_frame);
3282 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3283 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3284 capture_pp_binary, out_frames, NULL, vf_frame);
3286 err = ia_css_pipeline_create_and_add_stage(me,
3291 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3292 IA_CSS_BINARY_MODE_CAPTURE_PP,
3293 in_frame, out_frame, vf_frame,
3294 NULL, capture_pp_stage);
3295 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3296 if (*capture_pp_stage) {
3297 (*capture_pp_stage)->args.vf_downscale_log2 =
3298 capture_pp_binary->vf_downscale_log2;
3303 static void sh_css_setup_queues(void)
3305 const struct ia_css_fw_info *fw;
3306 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3308 sh_css_hmm_buffer_record_init();
3310 sh_css_event_init_irq_mask();
3313 HIVE_ADDR_host_sp_queues_initialized =
3314 fw->info.sp.host_sp_queues_initialized;
3318 /* set "host_sp_queues_initialized" to "true" */
3319 sp_dmem_store_uint32(SP0_ID,
3320 (unsigned int)sp_address_of(host_sp_queues_initialized),
3322 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3326 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3327 struct ia_css_frame *vf_frame, unsigned int idx) {
3329 unsigned int thread_id;
3330 enum sh_css_queue_id queue_id;
3334 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3335 vf_frame->contiguous = false;
3336 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3337 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3338 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3339 vf_frame->dynamic_queue_id = queue_id;
3340 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3342 err = ia_css_frame_init_planes(vf_frame);
3346 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3348 get_crop_lines_for_bayer_order(
3349 const struct ia_css_stream_config *config)
3352 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
3353 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3360 get_crop_columns_for_bayer_order(
3361 const struct ia_css_stream_config *config)
3364 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
3365 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3371 /* This function is to get the sum of all extra pixels in addition to the effective
3372 * input, it includes dvs envelop and filter run-in */
3373 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3374 unsigned int *extra_row, unsigned int *extra_column)
3376 enum ia_css_pipe_id pipe_id = pipe->mode;
3377 unsigned int left_cropping = 0, top_cropping = 0;
3379 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3381 /* The dvs envelope info may not be correctly sent down via pipe config
3382 * The check is made and the correct value is populated in the binary info
3383 * Use this value when computing crop, else excess lines may get trimmed
3386 case IA_CSS_PIPE_ID_PREVIEW:
3387 if (pipe->pipe_settings.preview.preview_binary.info) {
3389 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3391 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3393 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3395 case IA_CSS_PIPE_ID_VIDEO:
3396 if (pipe->pipe_settings.video.video_binary.info) {
3398 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3400 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3402 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3404 case IA_CSS_PIPE_ID_CAPTURE:
3405 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3406 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3408 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3410 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3413 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3415 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3422 *extra_row = top_cropping + dvs_env.height;
3423 *extra_column = left_cropping + dvs_env.width;
3427 ia_css_get_crop_offsets(
3428 struct ia_css_pipe *pipe,
3429 struct ia_css_frame_info *in_frame)
3431 unsigned int row = 0;
3432 unsigned int column = 0;
3433 struct ia_css_resolution *input_res;
3434 struct ia_css_resolution *effective_res;
3435 unsigned int extra_row = 0, extra_col = 0;
3436 unsigned int min_reqd_height, min_reqd_width;
3439 assert(pipe->stream);
3442 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3443 pipe, pipe->config.input_effective_res.width,
3444 pipe->config.input_effective_res.height);
3446 input_res = &pipe->stream->config.input_config.input_res;
3448 effective_res = &pipe->stream->config.input_config.effective_res;
3450 effective_res = &pipe->config.input_effective_res;
3453 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3455 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3457 min_reqd_height = effective_res->height + extra_row;
3458 min_reqd_width = effective_res->width + extra_col;
3460 if (input_res->height > min_reqd_height) {
3461 row = (input_res->height - min_reqd_height) / 2;
3464 if (input_res->width > min_reqd_width) {
3465 column = (input_res->width - min_reqd_width) / 2;
3471 * 1. Require the special support for RAW10 packed mode.
3472 * 2. Require the special support for the online use cases.
3475 /* ISP expects GRBG bayer order, we skip one line and/or one row
3476 * to correct in case the input bayer order is different.
3478 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3479 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3481 in_frame->crop_info.start_column = column;
3482 in_frame->crop_info.start_line = row;
3484 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3491 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3492 struct ia_css_frame *frame, enum ia_css_frame_format format) {
3493 struct ia_css_frame *in_frame;
3495 unsigned int thread_id;
3496 enum sh_css_queue_id queue_id;
3501 in_frame->info.format = format;
3503 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3504 if (format == IA_CSS_FRAME_FORMAT_RAW)
3505 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3506 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3509 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3510 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3511 in_frame->info.raw_bit_depth =
3512 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3513 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3514 in_frame->contiguous = false;
3515 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3516 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3517 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3518 in_frame->dynamic_queue_id = queue_id;
3519 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3520 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3521 ia_css_get_crop_offsets(pipe, &in_frame->info);
3523 err = ia_css_frame_init_planes(in_frame);
3525 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3526 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3532 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3533 struct ia_css_frame *out_frame, unsigned int idx) {
3535 unsigned int thread_id;
3536 enum sh_css_queue_id queue_id;
3540 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3541 out_frame->contiguous = false;
3542 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3543 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3544 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3545 out_frame->dynamic_queue_id = queue_id;
3546 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3547 err = ia_css_frame_init_planes(out_frame);
3552 /* Create stages for video pipe */
3553 static int create_host_video_pipeline(struct ia_css_pipe *pipe)
3555 struct ia_css_pipeline_stage_desc stage_desc;
3556 struct ia_css_binary *copy_binary, *video_binary,
3557 *yuv_scaler_binary, *vf_pp_binary;
3558 struct ia_css_pipeline_stage *copy_stage = NULL;
3559 struct ia_css_pipeline_stage *video_stage = NULL;
3560 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3561 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3562 struct ia_css_pipeline *me;
3563 struct ia_css_frame *in_frame = NULL;
3564 struct ia_css_frame *out_frame;
3565 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3566 struct ia_css_frame *vf_frame = NULL;
3568 bool need_copy = false;
3569 bool need_vf_pp = false;
3570 bool need_yuv_pp = false;
3571 unsigned int num_output_pins;
3572 bool need_in_frameinfo_memory = false;
3574 unsigned int i, num_yuv_scaler;
3575 bool *is_output_stage = NULL;
3577 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3578 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3579 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3582 ia_css_pipe_util_create_output_frames(out_frames);
3583 out_frame = &pipe->out_frame_struct;
3585 /* pipeline already created as part of create_host_pipeline_structure */
3586 me = &pipe->pipeline;
3587 ia_css_pipeline_clean(me);
3589 me->dvs_frame_delay = pipe->dvs_frame_delay;
3591 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3592 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3593 * except for the following: online or continuous
3595 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3596 pipe->stream->config.continuous);
3598 /* Construct in_frame info (only in case we have dynamic input */
3599 need_in_frameinfo_memory = pipe->stream->config.mode ==
3600 IA_CSS_INPUT_MODE_MEMORY;
3603 /* Construct in_frame info (only in case we have dynamic input */
3604 if (need_in_frameinfo_memory) {
3605 in_frame = &pipe->in_frame_struct;
3606 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3607 IA_CSS_FRAME_FORMAT_RAW);
3612 out_frame->data = 0;
3613 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3617 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3618 vf_frame = &pipe->vf_frame_struct;
3620 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3625 copy_binary = &pipe->pipe_settings.video.copy_binary;
3626 video_binary = &pipe->pipe_settings.video.video_binary;
3627 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3628 num_output_pins = video_binary->info->num_output_pins;
3630 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3631 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3632 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3634 need_copy = (copy_binary && copy_binary->info);
3635 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3636 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3639 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3640 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3641 out_frames, NULL, NULL);
3642 err = ia_css_pipeline_create_and_add_stage(me,
3647 in_frame = me->stages->args.out_frame[0];
3648 } else if (pipe->stream->config.continuous) {
3649 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3650 /* When continuous is enabled, configure in_frame with the
3651 * last pipe, which is the copy pipe.
3653 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3655 in_frame = pipe->continuous_frames[0];
3659 ia_css_pipe_util_set_output_frames(out_frames, 0,
3660 need_yuv_pp ? NULL : out_frame);
3662 /* when the video binary supports a second output pin,
3663 it can directly produce the vf_frame. */
3665 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3666 out_frames, in_frame, NULL);
3668 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3669 out_frames, in_frame, vf_frame);
3671 err = ia_css_pipeline_create_and_add_stage(me,
3677 /* If we use copy iso video, the input must be yuv iso raw */
3679 video_stage->args.copy_vf =
3680 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3681 video_stage->args.copy_output = video_stage->args.copy_vf;
3684 /* when the video binary supports only 1 output pin, vf_pp is needed to
3685 produce the vf_frame.*/
3686 if (need_vf_pp && video_stage) {
3687 in_frame = video_stage->args.out_vf_frame;
3688 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3696 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3697 video_stage->args.tnr_frames[frm] =
3698 pipe->pipe_settings.video.tnr_frames[frm];
3700 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3701 video_stage->args.delay_frames[frm] =
3702 pipe->pipe_settings.video.delay_frames[frm];
3706 /* Append Extension on Video out, if enabled */
3707 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3708 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3709 struct ia_css_frame *out = NULL;
3710 struct ia_css_frame *in = NULL;
3712 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3713 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3714 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3715 /* In/Out Frame mapping to support output frame extension.*/
3716 out = video_stage->args.out_frame[0];
3717 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3720 video_stage->args.out_frame[0] = in;
3723 err = add_firmwares(me, video_binary, pipe->output_stage,
3724 last_output_firmware(pipe->output_stage),
3725 IA_CSS_BINARY_MODE_VIDEO,
3726 in, out, NULL, &video_stage, NULL);
3731 if (need_yuv_pp && video_stage) {
3732 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3733 struct ia_css_frame *tmp_out_frame = NULL;
3735 for (i = 0; i < num_yuv_scaler; i++) {
3736 if (is_output_stage[i] == true) {
3737 tmp_out_frame = out_frame;
3739 tmp_out_frame = NULL;
3741 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3743 &yuv_scaler_binary[i],
3747 IA_CSS_LEAVE_ERR_PRIVATE(err);
3750 /* we use output port 1 as internal output port */
3751 if (yuv_scaler_stage)
3752 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3756 pipe->pipeline.acquire_isp_each_stage = false;
3757 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3758 pipe->stream->config.continuous);
3761 IA_CSS_LEAVE_ERR_PRIVATE(err);
3766 create_host_acc_pipeline(struct ia_css_pipe *pipe) {
3768 const struct ia_css_fw_info *fw;
3771 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3772 if ((!pipe) || (!pipe->stream))
3774 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3778 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3779 /* Reset pipe_qos_config to default disable all QOS extension stages */
3780 if (pipe->config.acc_extension)
3781 pipe->pipeline.pipe_qos_config = 0;
3783 fw = pipe->vf_stage;
3784 for (i = 0; fw; fw = fw->next)
3786 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3791 for (i = 0; i < pipe->config.num_acc_stages; i++)
3793 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3795 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3800 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3803 IA_CSS_LEAVE_ERR_PRIVATE(err);
3807 /* Create stages for preview */
3809 create_host_preview_pipeline(struct ia_css_pipe *pipe) {
3810 struct ia_css_pipeline_stage *copy_stage = NULL;
3811 struct ia_css_pipeline_stage *preview_stage = NULL;
3812 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3813 struct ia_css_pipeline_stage_desc stage_desc;
3814 struct ia_css_pipeline *me = NULL;
3815 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3816 struct ia_css_frame *in_frame = NULL;
3818 struct ia_css_frame *out_frame;
3819 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3820 bool need_in_frameinfo_memory = false;
3821 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3822 bool sensor = false;
3823 bool buffered_sensor = false;
3824 bool online = false;
3825 bool continuous = false;
3828 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3829 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3831 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3835 ia_css_pipe_util_create_output_frames(out_frames);
3836 /* pipeline already created as part of create_host_pipeline_structure */
3837 me = &pipe->pipeline;
3838 ia_css_pipeline_clean(me);
3840 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3841 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3842 * except for the following:
3843 * - Direct Sensor Mode Online Preview
3844 * - Buffered Sensor Mode Online Preview
3845 * - Direct Sensor Mode Continuous Preview
3846 * - Buffered Sensor Mode Continuous Preview
3848 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3849 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3850 online = pipe->stream->config.online;
3851 continuous = pipe->stream->config.continuous;
3852 need_in_frameinfo_memory =
3853 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3855 /* Construct in_frame info (only in case we have dynamic input */
3856 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3858 if (need_in_frameinfo_memory)
3860 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3861 IA_CSS_FRAME_FORMAT_RAW);
3865 in_frame = &me->in_frame;
3871 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3874 out_frame = &me->out_frame[0];
3876 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3877 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3878 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3879 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3881 if (pipe->pipe_settings.preview.copy_binary.info)
3883 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3884 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3885 out_frames, NULL, NULL);
3886 err = ia_css_pipeline_create_and_add_stage(me,
3891 in_frame = me->stages->args.out_frame[0];
3896 } else if (pipe->stream->config.continuous)
3899 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3900 /* When continuous is enabled, configure in_frame with the
3901 * last pipe, which is the copy pipe.
3903 if (continuous || !online) {
3904 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3907 in_frame = pipe->continuous_frames[0];
3913 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3914 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3915 out_frames, in_frame, NULL);
3918 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3919 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3920 out_frames, in_frame, NULL);
3922 err = ia_css_pipeline_create_and_add_stage(me,
3927 /* If we use copy iso preview, the input must be yuv iso raw */
3928 preview_stage->args.copy_vf =
3929 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3930 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3931 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame)
3933 /* in case of copy, use the vf frame as output frame */
3934 preview_stage->args.out_vf_frame =
3935 preview_stage->args.out_frame[0];
3939 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3940 in_frame = preview_stage->args.out_vf_frame;
3942 in_frame = preview_stage->args.out_frame[0];
3943 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3949 pipe->pipeline.acquire_isp_each_stage = false;
3950 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3953 IA_CSS_LEAVE_ERR_PRIVATE(err);
3957 static void send_raw_frames(struct ia_css_pipe *pipe)
3959 if (pipe->stream->config.continuous) {
3962 sh_css_update_host2sp_cont_num_raw_frames
3963 (pipe->stream->config.init_num_cont_raw_buf, true);
3964 sh_css_update_host2sp_cont_num_raw_frames
3965 (pipe->stream->config.target_num_cont_raw_buf, false);
3967 /* Hand-over all the SP-internal buffers */
3968 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3969 sh_css_update_host2sp_offline_frame(i,
3970 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3978 preview_start(struct ia_css_pipe *pipe) {
3979 struct ia_css_pipeline *me;
3980 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3982 struct ia_css_pipe *copy_pipe, *capture_pipe;
3983 struct ia_css_pipe *acc_pipe;
3984 enum sh_css_pipe_config_override copy_ovrd;
3985 enum ia_css_input_mode preview_pipe_input_mode;
3986 const struct ia_css_coordinate *coord = NULL;
3987 const struct ia_css_isp_parameters *params = NULL;
3989 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3990 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3992 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
3996 me = &pipe->pipeline;
3998 preview_pipe_input_mode = pipe->stream->config.mode;
4000 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4001 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4002 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
4004 copy_binary = &pipe->pipe_settings.preview.copy_binary;
4005 preview_binary = &pipe->pipe_settings.preview.preview_binary;
4006 if (pipe->pipe_settings.preview.vf_pp_binary.info)
4007 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4009 sh_css_metrics_start_frame();
4011 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4012 /* multi stream video needs mipi buffers */
4013 err = send_mipi_frames(pipe);
4015 IA_CSS_LEAVE_ERR_PRIVATE(err);
4019 send_raw_frames(pipe);
4022 unsigned int thread_id;
4024 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4025 copy_ovrd = 1 << thread_id;
4027 if (pipe->stream->cont_capt)
4029 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4031 copy_ovrd |= 1 << thread_id;
4036 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
4037 params = pipe->stream->isp_params_configs;
4040 /* Construct and load the copy pipe */
4041 if (pipe->stream->config.continuous)
4043 sh_css_sp_init_pipeline(©_pipe->pipeline,
4044 IA_CSS_PIPE_ID_COPY,
4045 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4047 pipe->stream->config.pixels_per_clock == 2, false,
4048 false, pipe->required_bds_factor,
4050 pipe->stream->config.mode,
4051 &pipe->stream->config.metadata_config,
4052 &pipe->stream->info.metadata_info,
4053 #if !defined(HAS_NO_INPUT_SYSTEM)
4054 pipe->stream->config.source.port.port,
4059 /* make the preview pipe start with mem mode input, copy handles
4061 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4064 /* Construct and load the capture pipe */
4065 if (pipe->stream->cont_capt)
4067 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4068 IA_CSS_PIPE_ID_CAPTURE,
4069 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4070 capture_pipe->config.default_capture_config.enable_xnr != 0,
4071 capture_pipe->stream->config.pixels_per_clock == 2,
4072 true, /* continuous */
4073 false, /* offline */
4074 capture_pipe->required_bds_factor,
4076 IA_CSS_INPUT_MODE_MEMORY,
4077 &pipe->stream->config.metadata_config,
4078 &pipe->stream->info.metadata_info,
4079 #if !defined(HAS_NO_INPUT_SYSTEM)
4080 (enum mipi_port_id)0,
4088 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4090 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
4092 pipe->stream->config.pixels_per_clock == 2,
4093 false, /* continuous */
4094 false, /* offline */
4095 pipe->required_bds_factor,
4097 IA_CSS_INPUT_MODE_MEMORY,
4100 #if !defined(HAS_NO_INPUT_SYSTEM)
4101 (enum mipi_port_id)0,
4107 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4109 IA_CSS_LEAVE_ERR_PRIVATE(err);
4114 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4115 const struct ia_css_buffer *buffer) {
4117 unsigned int thread_id;
4118 enum sh_css_queue_id queue_id;
4119 struct ia_css_pipeline *pipeline;
4120 struct ia_css_pipeline_stage *stage;
4121 struct ia_css_rmgr_vbuf_handle p_vbuf;
4122 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4123 struct sh_css_hmm_buffer ddr_buffer;
4124 enum ia_css_buffer_type buf_type;
4125 enum ia_css_pipe_id pipe_id;
4128 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4130 if ((!pipe) || (!buffer))
4132 IA_CSS_LEAVE_ERR(-EINVAL);
4136 buf_type = buffer->type;
4137 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4140 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4142 bool found_pipe = false;
4144 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4145 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4146 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4155 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4157 bool found_pipe = false;
4159 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4160 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4161 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4171 pipe_id = pipe->mode;
4173 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4175 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4176 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4177 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4178 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4179 (pipe_id >= IA_CSS_PIPE_ID_NUM))
4181 IA_CSS_LEAVE_ERR(-EINVAL);
4185 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4188 IA_CSS_LEAVE_ERR(-EINVAL);
4192 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4195 IA_CSS_LEAVE_ERR(-EINVAL);
4199 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4201 IA_CSS_LEAVE_ERR(-EINVAL);
4205 if (!sh_css_sp_is_running())
4207 IA_CSS_LOG("SP is not running!");
4208 IA_CSS_LEAVE_ERR(-EBUSY);
4209 /* SP is not running. The queues are not valid */
4213 pipeline = &pipe->pipeline;
4216 pipe_id == IA_CSS_PIPE_ID_COPY ||
4217 pipe_id == IA_CSS_PIPE_ID_ACC);
4219 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4220 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4221 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4222 ddr_buffer.timing_data = buffer->timing_data;
4224 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4226 if (!buffer->data.stats_3a) {
4227 IA_CSS_LEAVE_ERR(-EINVAL);
4230 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4231 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4232 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4234 if (!buffer->data.stats_dvs) {
4235 IA_CSS_LEAVE_ERR(-EINVAL);
4238 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4239 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4240 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA)
4242 if (!buffer->data.metadata) {
4243 IA_CSS_LEAVE_ERR(-EINVAL);
4246 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4247 ddr_buffer.payload.metadata = *buffer->data.metadata;
4248 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4249 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4250 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4251 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4252 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME))
4254 if (!buffer->data.frame) {
4255 IA_CSS_LEAVE_ERR(-EINVAL);
4258 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4259 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4260 ddr_buffer.payload.frame.flashed = 0;
4262 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4263 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4264 buf_type, buffer->data.frame->data);
4266 #if CONFIG_ON_FRAME_ENQUEUE()
4267 return_err = set_config_on_frame_enqueue(
4268 &buffer->data.frame->info,
4269 &ddr_buffer.payload.frame);
4271 IA_CSS_LEAVE_ERR(return_err);
4277 /* start of test for using rmgr for acq/rel memory */
4280 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4282 /* TODO: change next to correct pool for optimization */
4283 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4286 assert(h_vbuf->vptr != 0x0);
4288 if ((!h_vbuf) || (h_vbuf->vptr == 0x0))
4290 IA_CSS_LEAVE_ERR(-EINVAL);
4294 hmm_store(h_vbuf->vptr,
4295 (void *)(&ddr_buffer),
4296 sizeof(struct sh_css_hmm_buffer));
4297 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4298 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4299 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS))
4302 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4303 IA_CSS_LOG("pipeline is empty!");
4304 IA_CSS_LEAVE_ERR(-EINVAL);
4308 for (stage = pipeline->stages; stage; stage = stage->next) {
4309 /* The SP will read the params
4310 after it got empty 3a and dis */
4311 if (STATS_ENABLED(stage)) {
4312 /* there is a stage that needs it */
4313 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4315 (uint32_t)h_vbuf->vptr);
4318 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4319 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4320 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4321 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4322 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4323 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA))
4325 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4327 (uint32_t)h_vbuf->vptr);
4328 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4329 if (!(return_err) &&
4330 (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) {
4331 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4332 ddr_buffer.payload.frame.frame_data,
4333 queue_id, thread_id);
4340 if (sh_css_hmm_buffer_record_acquire(
4342 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4343 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4345 return_err = -EINVAL;
4346 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4351 * Tell the SP which queues are not empty,
4352 * by sending the software event.
4356 if (!sh_css_sp_is_running()) {
4357 /* SP is not running. The queues are not valid */
4358 IA_CSS_LOG("SP is not running!");
4359 IA_CSS_LEAVE_ERR(-EBUSY);
4362 return_err = ia_css_bufq_enqueue_psys_event(
4363 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4369 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4370 IA_CSS_ERROR("buffer not enqueued");
4373 IA_CSS_LEAVE("return value = %d", return_err);
4379 * TODO: Free up the hmm memory space.
4382 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4383 struct ia_css_buffer *buffer) {
4385 enum sh_css_queue_id queue_id;
4386 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
4387 struct sh_css_hmm_buffer ddr_buffer;
4388 enum ia_css_buffer_type buf_type;
4389 enum ia_css_pipe_id pipe_id;
4390 unsigned int thread_id;
4391 hrt_address kernel_ptr = 0;
4394 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4396 if ((!pipe) || (!buffer))
4398 IA_CSS_LEAVE_ERR(-EINVAL);
4402 pipe_id = pipe->mode;
4404 buf_type = buffer->type;
4406 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4408 ddr_buffer.kernel_ptr = 0;
4410 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4413 IA_CSS_LEAVE_ERR(-EINVAL);
4417 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4420 IA_CSS_LEAVE_ERR(-EINVAL);
4424 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4426 IA_CSS_LEAVE_ERR(-EINVAL);
4430 if (!sh_css_sp_is_running())
4432 IA_CSS_LOG("SP is not running!");
4433 IA_CSS_LEAVE_ERR(-EBUSY);
4434 /* SP is not running. The queues are not valid */
4438 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4439 (uint32_t *)&ddr_buffer_addr);
4443 struct ia_css_frame *frame;
4444 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4446 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4448 /* Validate the ddr_buffer_addr and buf_type */
4449 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4450 ddr_buffer_addr, buf_type);
4451 if (hmm_buffer_record) {
4452 /* valid hmm_buffer_record found. Save the kernel_ptr
4453 * for validation after performing hmm_load. The
4454 * vbuf handle and buffer_record can be released.
4456 kernel_ptr = hmm_buffer_record->kernel_ptr;
4457 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4458 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4460 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4461 ddr_buffer_addr, buf_type);
4462 IA_CSS_LEAVE_ERR(-EINVAL);
4466 hmm_load(ddr_buffer_addr,
4468 sizeof(struct sh_css_hmm_buffer));
4470 /* if the kernel_ptr is 0 or an invalid, return an error.
4471 * do not access the buffer via the kernal_ptr.
4473 if ((ddr_buffer.kernel_ptr == 0) ||
4474 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4475 IA_CSS_ERROR("kernel_ptr invalid");
4476 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4477 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4478 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4479 IA_CSS_LEAVE_ERR(-EINVAL);
4483 if (ddr_buffer.kernel_ptr != 0) {
4484 /* buffer->exp_id : all instances to be removed later once the driver change
4485 * is completed. See patch #5758 for reference */
4487 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4488 buffer->timing_data = ddr_buffer.timing_data;
4490 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4491 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4492 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4496 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4497 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4498 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4499 if ((pipe) && (pipe->stop_requested == true)) {
4500 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4501 /* free mipi frames only for old input system
4502 * for 2401 it is done in ia_css_stream_destroy call
4504 return_err = free_mipi_frames(pipe);
4506 IA_CSS_LOG("free_mipi_frames() failed");
4507 IA_CSS_LEAVE_ERR(return_err);
4511 pipe->stop_requested = false;
4514 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4515 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4516 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4517 buffer->data.frame = frame;
4518 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4519 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4520 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4521 if (ddr_buffer.payload.frame.flashed == 1)
4522 frame->flash_state =
4523 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4524 if (ddr_buffer.payload.frame.flashed == 2)
4525 frame->flash_state =
4526 IA_CSS_FRAME_FLASH_STATE_FULL;
4527 frame->valid = pipe->num_invalid_frames == 0;
4529 pipe->num_invalid_frames--;
4531 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4532 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4533 frame->planes.binary.size = frame->data_bytes;
4535 frame->planes.binary.size =
4536 sh_css_sp_get_binary_copy_size();
4539 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4540 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4541 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4542 frame->data, frame->isp_config_id, thread_id);
4546 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4547 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4548 buf_type, buffer->data.frame->data);
4551 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4552 buffer->data.stats_3a =
4553 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4554 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4555 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4556 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4558 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4559 buffer->data.stats_dvs =
4560 (struct ia_css_isp_dvs_statistics *)
4561 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4562 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4563 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4565 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4567 case IA_CSS_BUFFER_TYPE_METADATA:
4568 buffer->data.metadata =
4569 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4570 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4571 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4574 return_err = -EINVAL;
4581 * Tell the SP which queues are not full,
4582 * by sending the software event.
4586 if (!sh_css_sp_is_running()) {
4587 IA_CSS_LOG("SP is not running!");
4588 IA_CSS_LEAVE_ERR(-EBUSY);
4589 /* SP is not running. The queues are not valid */
4592 ia_css_bufq_enqueue_psys_event(
4593 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4598 IA_CSS_LEAVE("buffer=%p", buffer);
4604 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4605 * TODO: modify and move it if possible.
4607 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4608 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4609 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4610 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4611 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4613 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4614 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */
4615 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */
4616 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */
4617 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */
4618 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */
4619 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */
4620 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */
4621 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */
4622 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */
4623 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */
4624 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */
4625 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */
4626 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */
4627 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */
4628 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */
4629 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */
4630 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4634 ia_css_dequeue_event(struct ia_css_event *event) {
4635 return ia_css_dequeue_psys_event(event);
4639 ia_css_dequeue_psys_event(struct ia_css_event *event) {
4640 enum ia_css_pipe_id pipe_id = 0;
4641 u8 payload[4] = {0, 0, 0, 0};
4645 * a) use generic decoding function , same as the one used by sp.
4646 * b) group decode and dequeue into eventQueue module
4648 * We skip the IA_CSS_ENTER logging call
4649 * to avoid flooding the logs when the host application
4654 if (!sh_css_sp_is_running())
4656 /* SP is not running. The queues are not valid */
4660 /* dequeue the event (if any) from the psys event queue */
4661 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4665 IA_CSS_LOG("event dequeued from psys event queue");
4667 /* Tell the SP that we dequeued an event from the event queue. */
4668 ia_css_bufq_enqueue_psys_event(
4669 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4671 /* Events are decoded into 4 bytes of payload, the first byte
4672 * contains the sp event type. This is converted to a host enum.
4673 * TODO: can this enum conversion be eliminated */
4674 event->type = convert_event_sp_to_host_domain[payload[0]];
4675 /* Some sane default values since not all events use all fields. */
4677 event->port = MIPI_PORT0_ID;
4679 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4680 event->fw_handle = 0;
4681 event->timer_data = 0;
4682 event->timer_code = 0;
4683 event->timer_subcode = 0;
4685 if (event->type == IA_CSS_EVENT_TYPE_TIMER)
4687 /* timer event ??? get the 2nd event and decode the data into the event struct */
4689 /* 1st event: LSB 16-bit timer data and code */
4690 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4691 event->timer_code = payload[2];
4692 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4693 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4695 /* no 2nd event ??? an error */
4696 /* Putting IA_CSS_ERROR is resulting in failures in
4697 * Merrifield smoke testing */
4698 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4701 ia_css_bufq_enqueue_psys_event(
4702 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4703 event->type = convert_event_sp_to_host_domain[payload[0]];
4705 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4706 /* 2nd event data: MSB 16-bit timer and subcode */
4707 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4708 event->timer_data |= (tmp_data << 16);
4709 event->timer_subcode = payload[2];
4711 /* It's a non timer event. So clear first half of the timer event data.
4712 * If the second part of the TIMER event is not received, we discard
4713 * the first half of the timer data and process the non timer event without
4714 * affecting the flow. So the non timer event falls through
4717 event->timer_data = 0;
4718 event->timer_code = 0;
4719 event->timer_subcode = 0;
4720 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4723 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF)
4725 event->port = (enum mipi_port_id)payload[1];
4726 event->exp_id = payload[3];
4727 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING)
4729 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4730 /* exp_id is only available in these warning types */
4731 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4732 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4733 event->exp_id = payload[3];
4734 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT)
4736 event->fw_assert_module_id = payload[1]; /* module */
4737 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4738 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4739 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER)
4741 /* pipe related events.
4742 * payload[1] contains the pipe_num,
4743 * payload[2] contains the pipe_id. These are different. */
4744 event->pipe = find_pipe_by_num(payload[1]);
4745 pipe_id = (enum ia_css_pipe_id)payload[2];
4746 /* Check to see if pipe still exists */
4750 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4751 /* find the capture pipe that goes with this */
4754 n = event->pipe->stream->num_pipes;
4755 for (i = 0; i < n; i++) {
4756 struct ia_css_pipe *p =
4757 event->pipe->stream->pipes[i];
4758 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4763 event->exp_id = payload[3];
4765 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4766 /* payload[3] contains the acc fw handle. */
4767 u32 stage_num = (uint32_t)payload[3];
4769 ret_err = ia_css_pipeline_get_fw_from_stage(
4770 &event->pipe->pipeline,
4774 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4782 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4784 IA_CSS_LEAVE("event_id=%d", event->type);
4790 ia_css_dequeue_isys_event(struct ia_css_event *event) {
4791 u8 payload[4] = {0, 0, 0, 0};
4794 /* We skip the IA_CSS_ENTER logging call
4795 * to avoid flooding the logs when the host application
4800 if (!sh_css_sp_is_running())
4802 /* SP is not running. The queues are not valid */
4806 err = ia_css_bufq_dequeue_isys_event(payload);
4810 IA_CSS_LOG("event dequeued from isys event queue");
4812 /* Update SP state to indicate that element was dequeued. */
4813 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4815 /* Fill return struct with appropriate info */
4816 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4817 /* EOF events are associated with a CSI port, not with a pipe */
4819 event->port = payload[1];
4820 event->exp_id = payload[3];
4822 IA_CSS_LEAVE_ERR(err);
4827 acc_start(struct ia_css_pipe *pipe)
4830 assert(pipe->stream);
4832 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4833 pipe->stream->config.mode);
4837 sh_css_pipe_start(struct ia_css_stream *stream) {
4840 struct ia_css_pipe *pipe;
4841 enum ia_css_pipe_id pipe_id;
4842 unsigned int thread_id;
4844 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4848 IA_CSS_LEAVE_ERR(-EINVAL);
4851 pipe = stream->last_pipe;
4854 IA_CSS_LEAVE_ERR(-EINVAL);
4858 pipe_id = pipe->mode;
4860 if (stream->started == true)
4862 IA_CSS_WARNING("Cannot start stream that is already started");
4863 IA_CSS_LEAVE_ERR(err);
4867 pipe->stop_requested = false;
4871 case IA_CSS_PIPE_ID_PREVIEW:
4872 err = preview_start(pipe);
4874 case IA_CSS_PIPE_ID_VIDEO:
4875 err = video_start(pipe);
4877 case IA_CSS_PIPE_ID_CAPTURE:
4878 err = capture_start(pipe);
4880 case IA_CSS_PIPE_ID_YUVPP:
4881 err = yuvpp_start(pipe);
4883 case IA_CSS_PIPE_ID_ACC:
4889 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4890 if (!stream->config.continuous)
4894 for (i = 1; i < stream->num_pipes && 0 == err ; i++) {
4895 switch (stream->pipes[i]->mode) {
4896 case IA_CSS_PIPE_ID_PREVIEW:
4897 stream->pipes[i]->stop_requested = false;
4898 err = preview_start(stream->pipes[i]);
4900 case IA_CSS_PIPE_ID_VIDEO:
4901 stream->pipes[i]->stop_requested = false;
4902 err = video_start(stream->pipes[i]);
4904 case IA_CSS_PIPE_ID_CAPTURE:
4905 stream->pipes[i]->stop_requested = false;
4906 err = capture_start(stream->pipes[i]);
4908 case IA_CSS_PIPE_ID_YUVPP:
4909 stream->pipes[i]->stop_requested = false;
4910 err = yuvpp_start(stream->pipes[i]);
4912 case IA_CSS_PIPE_ID_ACC:
4913 stream->pipes[i]->stop_requested = false;
4914 acc_start(stream->pipes[i]);
4923 IA_CSS_LEAVE_ERR_PRIVATE(err);
4927 /* Force ISP parameter calculation after a mode change
4928 * Acceleration API examples pass NULL for stream but they
4929 * don't use ISP parameters anyway. So this should be okay.
4930 * The SP binary (jpeg) copy does not use any parameters.
4932 if (!copy_on_sp(pipe))
4934 sh_css_invalidate_params(stream);
4935 err = sh_css_param_update_isp_params(pipe,
4936 stream->isp_params_configs, true, NULL);
4938 IA_CSS_LEAVE_ERR_PRIVATE(err);
4943 ia_css_debug_pipe_graph_dump_epilogue();
4945 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4947 if (!sh_css_sp_is_running())
4949 IA_CSS_LEAVE_ERR_PRIVATE(-EBUSY);
4950 /* SP is not running. The queues are not valid */
4953 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4954 (uint8_t)thread_id, 0, 0);
4956 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4957 if (!stream->config.continuous)
4961 for (i = 1; i < stream->num_pipes; i++) {
4962 ia_css_pipeline_get_sp_thread_id(
4963 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4965 ia_css_bufq_enqueue_psys_event(
4966 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4967 (uint8_t)thread_id, 0, 0);
4971 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4972 if (pipe->stream->config.continuous)
4974 struct ia_css_pipe *copy_pipe = NULL;
4976 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4977 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4978 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4979 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4982 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
4985 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4987 /* by the time we reach here q is initialized and handle is available.*/
4988 ia_css_bufq_enqueue_psys_event(
4989 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4990 (uint8_t)thread_id, 0, 0);
4992 if (pipe->stream->cont_capt)
4994 struct ia_css_pipe *capture_pipe = NULL;
4996 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4997 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4998 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4999 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5001 if (!capture_pipe) {
5002 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5005 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5007 /* by the time we reach here q is initialized and handle is available.*/
5008 ia_css_bufq_enqueue_psys_event(
5009 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5010 (uint8_t)thread_id, 0, 0);
5013 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
5014 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5016 struct ia_css_pipe *acc_pipe = NULL;
5018 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5021 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
5023 /* by the time we reach here q is initialized and handle is available.*/
5024 ia_css_bufq_enqueue_psys_event(
5025 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5026 (uint8_t)thread_id, 0, 0);
5030 stream->started = true;
5032 IA_CSS_LEAVE_ERR_PRIVATE(err);
5038 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5040 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5041 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5042 //my_css.cont_capt = enable;
5043 my_css.stop_copy_preview = stop_copy_preview;
5047 sh_css_continuous_is_enabled(uint8_t pipe_num)
5049 struct ia_css_pipe *pipe;
5052 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5053 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5055 pipe = find_pipe_by_num(pipe_num);
5056 continuous = pipe && pipe->stream->config.continuous;
5057 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5058 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5065 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
5066 int *buffer_depth) {
5069 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5071 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5076 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
5077 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
5079 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5081 /* ok, value allowed */
5082 stream->config.target_num_cont_raw_buf = buffer_depth;
5083 /* TODO: check what to regarding initialization */
5089 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
5090 int *buffer_depth) {
5093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5095 *buffer_depth = stream->config.target_num_cont_raw_buf;
5100 * @brief Stop all "ia_css_pipe" instances in the target
5101 * "ia_css_stream" instance.
5103 * Refer to "Local prototypes" for more info.
5107 sh_css_pipes_stop(struct ia_css_stream *stream)
5110 struct ia_css_pipe *main_pipe;
5111 enum ia_css_pipe_id main_pipe_id;
5117 IA_CSS_LOG("stream does NOT exist!");
5122 main_pipe = stream->last_pipe;
5126 IA_CSS_LOG("main_pipe does NOT exist!");
5131 main_pipe_id = main_pipe->mode;
5132 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5135 * Stop all "ia_css_pipe" instances in this target
5136 * "ia_css_stream" instance.
5138 for (i = 0; i < stream->num_pipes; i++)
5140 /* send the "stop" request to the "ia_css_pipe" instance */
5141 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5142 stream->pipes[i]->pipeline.pipe_id);
5143 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5146 * Exit this loop if "ia_css_pipeline_request_stop()"
5147 * returns the error code.
5149 * The error code would be generated in the following
5151 * (1) The Scalar Processor has already been stopped.
5152 * (2) The "Host->SP" event queue is full.
5154 * As the convention of using CSS API 2.0/2.1, such CSS
5155 * error code would be propogated from the CSS-internal
5156 * API returned value to the CSS API returned value. Then
5157 * the CSS driver should capture these error code and
5158 * handle it in the driver exception handling mechanism.
5166 * In the CSS firmware use scenario "Continuous Preview"
5167 * as well as "Continuous Video", the "ia_css_pipe" instance
5168 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5169 * the CSS firmware so that it is not listed in the target
5170 * "ia_css_stream" instance.
5172 * We need to stop this "Copy Pipe", as well.
5174 if (main_pipe->stream->config.continuous)
5176 struct ia_css_pipe *copy_pipe = NULL;
5178 /* get the reference to "Copy Pipe" */
5179 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5180 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5181 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5182 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5184 /* return the error code if "Copy Pipe" does NOT exist */
5187 IA_CSS_LOG("Copy Pipe does NOT exist!");
5192 /* send the "stop" request to "Copy Pipe" */
5193 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5194 copy_pipe->pipeline.pipe_id);
5195 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
5199 IA_CSS_LEAVE_ERR_PRIVATE(err);
5204 * @brief Check if all "ia_css_pipe" instances in the target
5205 * "ia_css_stream" instance have stopped.
5207 * Refer to "Local prototypes" for more info.
5211 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5215 struct ia_css_pipe *main_pipe;
5216 enum ia_css_pipe_id main_pipe_id;
5222 IA_CSS_LOG("stream does NOT exist!");
5227 main_pipe = stream->last_pipe;
5231 IA_CSS_LOG("main_pipe does NOT exist!");
5236 main_pipe_id = main_pipe->mode;
5237 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5240 * Check if every "ia_css_pipe" instance in this target
5241 * "ia_css_stream" instance has stopped.
5243 for (i = 0; i < stream->num_pipes; i++) {
5244 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5245 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5246 stream->pipes[i]->pipeline.pipe_id,
5251 * In the CSS firmware use scenario "Continuous Preview"
5252 * as well as "Continuous Video", the "ia_css_pipe" instance
5253 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5254 * the CSS firmware so that it is not listed in the target
5255 * "ia_css_stream" instance.
5257 * We need to check if this "Copy Pipe" has stopped, as well.
5259 if (main_pipe->stream->config.continuous) {
5260 struct ia_css_pipe *copy_pipe = NULL;
5262 /* get the reference to "Copy Pipe" */
5263 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5264 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5265 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5266 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5268 /* return if "Copy Pipe" does NOT exist */
5271 IA_CSS_LOG("Copy Pipe does NOT exist!");
5277 /* check if "Copy Pipe" has stopped or not */
5278 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5279 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5280 copy_pipe->pipeline.pipe_id,
5285 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5289 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5291 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5293 OP___assert(port < N_CSI_PORTS);
5294 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5295 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5296 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5297 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5298 return my_css.mipi_sizes_for_check[port][idx];
5302 static int sh_css_pipe_configure_output(
5303 struct ia_css_pipe *pipe,
5305 unsigned int height,
5306 unsigned int padded_width,
5307 enum ia_css_frame_format format,
5312 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
5313 pipe, width, height, padded_width, format, idx);
5315 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5319 err = ia_css_util_check_res(width, height);
5321 IA_CSS_LEAVE_ERR_PRIVATE(err);
5324 if (pipe->output_info[idx].res.width != width ||
5325 pipe->output_info[idx].res.height != height ||
5326 pipe->output_info[idx].format != format) {
5327 ia_css_frame_info_init(
5328 &pipe->output_info[idx],
5334 IA_CSS_LEAVE_ERR_PRIVATE(0);
5339 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5340 struct ia_css_shading_info *shading_info,
5341 struct ia_css_pipe_config *pipe_config)
5344 struct ia_css_binary *binary = NULL;
5346 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5347 "sh_css_pipe_get_shading_info() enter:\n");
5349 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5353 err = ia_css_binary_get_shading_info(binary,
5354 IA_CSS_SHADING_CORRECTION_TYPE_1,
5355 pipe->required_bds_factor,
5356 (const struct ia_css_stream_config *)&pipe->stream->config,
5357 shading_info, pipe_config);
5359 /* Other function calls can be added here when other shading correction types will be added
5364 /* When the pipe does not have a binary which has the shading
5365 * correction, this function does not need to fill the shading
5366 * information. It is not a error case, and then
5367 * this function should return 0.
5369 memset(shading_info, 0, sizeof(*shading_info));
5375 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5376 struct ia_css_grid_info *info) {
5378 struct ia_css_binary *binary = NULL;
5383 IA_CSS_ENTER_PRIVATE("");
5385 binary = ia_css_pipe_get_s3a_binary(pipe);
5389 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5393 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5395 binary = ia_css_pipe_get_sdis_binary(pipe);
5399 ia_css_binary_dvs_grid_info(binary, info, pipe);
5400 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5403 memset(&info->dvs_grid.dvs_grid_info, 0,
5404 sizeof(info->dvs_grid.dvs_grid_info));
5405 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5406 sizeof(info->dvs_grid.dvs_stat_grid_info));
5411 /* copy pipe does not have ISP binary*/
5412 info->isp_in_width = binary->internal_frame_info.res.width;
5413 info->isp_in_height = binary->internal_frame_info.res.height;
5416 #if defined(HAS_VAMEM_VERSION_2)
5417 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5418 #elif defined(HAS_VAMEM_VERSION_1)
5419 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5421 #error "Unknown VAMEM version"
5425 IA_CSS_LEAVE_ERR_PRIVATE(err);
5431 * @brief Check if a format is supported by the pipe.
5435 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
5436 enum ia_css_frame_format format) {
5437 const enum ia_css_frame_format *supported_formats;
5438 int number_of_formats;
5442 IA_CSS_ENTER_PRIVATE("");
5444 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info)
5446 IA_CSS_ERROR("Pipe or binary info is not set");
5447 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5451 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5452 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
5454 for (i = 0; i < number_of_formats && !found; i++)
5456 if (supported_formats[i] == format) {
5463 IA_CSS_ERROR("Requested format is not supported by binary");
5464 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5468 IA_CSS_LEAVE_ERR_PRIVATE(0);
5473 static int load_video_binaries(struct ia_css_pipe *pipe)
5475 struct ia_css_frame_info video_in_info, tnr_info,
5476 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5479 bool continuous = pipe->stream->config.continuous;
5481 unsigned int num_output_pins;
5482 struct ia_css_frame_info video_bin_out_info;
5483 bool need_scaler = false;
5484 bool vf_res_different_than_output = false;
5485 bool need_vf_pp = false;
5487 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5489 IA_CSS_ENTER_PRIVATE("");
5491 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5492 /* we only test the video_binary because offline video doesn't need a
5493 * vf_pp binary and online does not (always use) the copy_binary.
5494 * All are always reset at the same time anyway.
5496 if (mycs->video_binary.info)
5499 online = pipe->stream->config.online;
5500 pipe_out_info = &pipe->output_info[0];
5501 pipe_vf_out_info = &pipe->vf_output_info[0];
5503 assert(pipe_out_info);
5506 * There is no explicit input format requirement for raw or yuv
5507 * What matters is that there is a binary that supports the stream format.
5508 * This is checked in the binary_find(), so no need to check it here
5510 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5513 /* cannot have online video and input_mode memory */
5514 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5516 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5517 err = ia_css_util_check_vf_out_info(pipe_out_info,
5522 err = ia_css_frame_check_info(pipe_out_info);
5527 if (pipe->out_yuv_ds_input_info.res.width)
5528 video_bin_out_info = pipe->out_yuv_ds_input_info;
5530 video_bin_out_info = *pipe_out_info;
5533 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5534 video_vf_info = pipe_vf_out_info;
5535 vf_res_different_than_output = (video_vf_info->res.width !=
5536 video_bin_out_info.res.width) ||
5537 (video_vf_info->res.height != video_bin_out_info.res.height);
5539 video_vf_info = NULL;
5542 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5544 /* we build up the pipeline starting at the end */
5545 /* YUV post-processing if needed */
5547 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5549 /* NV12 is the common format that is supported by both */
5550 /* yuv_scaler and the video_xx_isp2_min binaries. */
5551 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5553 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5554 &video_bin_out_info,
5560 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5561 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5562 sizeof(struct ia_css_binary), GFP_KERNEL);
5563 if (!mycs->yuv_scaler_binary) {
5567 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5568 * sizeof(bool), GFP_KERNEL);
5569 if (!mycs->is_output_stage) {
5573 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5574 struct ia_css_binary_descr yuv_scaler_descr;
5576 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5577 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5578 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5579 &cas_scaler_descr.out_info[i],
5580 &cas_scaler_descr.internal_out_info[i],
5581 &cas_scaler_descr.vf_info[i]);
5582 err = ia_css_binary_find(&yuv_scaler_descr,
5583 &mycs->yuv_scaler_binary[i]);
5585 kfree(mycs->is_output_stage);
5586 mycs->is_output_stage = NULL;
5590 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5594 struct ia_css_binary_descr video_descr;
5595 enum ia_css_frame_format vf_info_format;
5597 err = ia_css_pipe_get_video_binarydesc(pipe,
5598 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5600 pipe->stream->config.left_padding);
5604 /* In the case where video_vf_info is not NULL, this allows
5605 * us to find a potential video library with desired vf format.
5606 * If success, no vf_pp binary is needed.
5607 * If failed, we will look up video binary with YUV_LINE vf format
5609 err = ia_css_binary_find(&video_descr,
5610 &mycs->video_binary);
5613 if (video_vf_info) {
5614 /* This will do another video binary lookup later for YUV_LINE format*/
5618 } else if (video_vf_info) {
5619 /* The first video binary lookup is successful, but we may
5620 * still need vf_pp binary based on additiona check */
5621 num_output_pins = mycs->video_binary.info->num_output_pins;
5622 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5624 /* If the binary has dual output pins, we need vf_pp if the resolution
5626 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5628 /* If the binary has single output pin, we need vf_pp if additional
5629 * scaling is needed for vf */
5630 need_vf_pp |= ((num_output_pins == 1) &&
5631 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5632 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5636 /* save the current vf_info format for restoration later */
5637 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5638 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5640 vf_info_format = video_vf_info->format;
5642 if (!pipe->config.enable_vfpp_bci)
5643 ia_css_frame_info_set_format(video_vf_info,
5644 IA_CSS_FRAME_FORMAT_YUV_LINE);
5646 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5648 err = ia_css_binary_find(&video_descr,
5649 &mycs->video_binary);
5651 /* restore original vf_info format */
5652 ia_css_frame_info_set_format(video_vf_info,
5659 /* If a video binary does not use a ref_frame, we set the frame delay
5660 * to 0. This is the case for the 1-stage low-power video binary. */
5661 if (!mycs->video_binary.info->sp.enable.ref_frame)
5662 pipe->dvs_frame_delay = 0;
5664 /* The delay latency determines the number of invalid frames after
5665 * a stream is started. */
5666 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5667 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5669 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5670 * outputs a viewfinder output, then we need double the number of
5673 pipe->num_invalid_frames *= 2;
5675 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5676 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5677 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5679 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5680 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5682 if (!online && !continuous) {
5683 /* TODO: what exactly needs doing, prepend the copy binary to
5684 * video base this only on !online?
5686 err = load_copy_binary(pipe,
5688 &mycs->video_binary);
5696 #if !defined(HAS_OUTPUT_SYSTEM)
5697 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5698 struct ia_css_binary_descr vf_pp_descr;
5700 if (mycs->video_binary.vf_frame_info.format
5701 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5702 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5703 &mycs->video_binary.vf_frame_info,
5706 /* output from main binary is not yuv line. currently this is
5707 * possible only when bci is enabled on vfpp output */
5708 assert(pipe->config.enable_vfpp_bci == true);
5709 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5710 &mycs->video_binary.vf_frame_info,
5711 pipe_vf_out_info, NULL, NULL);
5714 err = ia_css_binary_find(&vf_pp_descr,
5715 &mycs->vf_pp_binary);
5721 err = allocate_delay_frames(pipe);
5726 if (mycs->video_binary.info->sp.enable.block_output) {
5727 unsigned int tnr_width;
5728 unsigned int tnr_height;
5730 tnr_info = mycs->video_binary.out_frame_info[0];
5733 /* Select resolution for TNR. If
5734 * output_system_in_resolution(GDC_out_resolution) is
5735 * being used, then select that as it will also be in resolution for
5736 * TNR. At present, it only make sense for Skycam */
5737 if (pipe->config.output_system_in_res.width &&
5738 pipe->config.output_system_in_res.height) {
5739 tnr_width = pipe->config.output_system_in_res.width;
5740 tnr_height = pipe->config.output_system_in_res.height;
5742 tnr_width = tnr_info.res.width;
5743 tnr_height = tnr_info.res.height;
5746 /* Make tnr reference buffers output block width(in pix) align */
5747 tnr_info.res.width = CEIL_MUL(tnr_width,
5748 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5749 tnr_info.padded_width = tnr_info.res.width;
5751 tnr_height = tnr_info.res.height;
5754 /* Make tnr reference buffers output block height align */
5755 tnr_info.res.height = CEIL_MUL(tnr_height,
5756 mycs->video_binary.info->sp.block.output_block_height);
5758 tnr_info = mycs->video_binary.internal_frame_info;
5760 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5761 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5763 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5764 if (mycs->tnr_frames[i]) {
5765 ia_css_frame_free(mycs->tnr_frames[i]);
5766 mycs->tnr_frames[i] = NULL;
5768 err = ia_css_frame_allocate_from_info(
5769 &mycs->tnr_frames[i],
5774 IA_CSS_LEAVE_PRIVATE("");
5779 unload_video_binaries(struct ia_css_pipe *pipe) {
5782 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5784 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO))
5786 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5789 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5790 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5791 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5793 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5794 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5796 kfree(pipe->pipe_settings.video.is_output_stage);
5797 pipe->pipe_settings.video.is_output_stage = NULL;
5798 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5799 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5801 IA_CSS_LEAVE_ERR_PRIVATE(0);
5805 static int video_start(struct ia_css_pipe *pipe)
5807 struct ia_css_binary *copy_binary;
5809 struct ia_css_pipe *copy_pipe, *capture_pipe;
5810 enum sh_css_pipe_config_override copy_ovrd;
5811 enum ia_css_input_mode video_pipe_input_mode;
5813 const struct ia_css_coordinate *coord = NULL;
5814 const struct ia_css_isp_parameters *params = NULL;
5816 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5817 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5818 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5822 video_pipe_input_mode = pipe->stream->config.mode;
5824 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5825 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5827 copy_binary = &pipe->pipe_settings.video.copy_binary;
5829 sh_css_metrics_start_frame();
5831 /* multi stream video needs mipi buffers */
5833 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5834 err = send_mipi_frames(pipe);
5839 send_raw_frames(pipe);
5841 unsigned int thread_id;
5843 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5844 copy_ovrd = 1 << thread_id;
5846 if (pipe->stream->cont_capt) {
5847 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5849 copy_ovrd |= 1 << thread_id;
5854 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
5855 params = pipe->stream->isp_params_configs;
5858 /* Construct and load the copy pipe */
5859 if (pipe->stream->config.continuous) {
5860 sh_css_sp_init_pipeline(©_pipe->pipeline,
5861 IA_CSS_PIPE_ID_COPY,
5862 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5864 pipe->stream->config.pixels_per_clock == 2, false,
5865 false, pipe->required_bds_factor,
5867 pipe->stream->config.mode,
5868 &pipe->stream->config.metadata_config,
5869 &pipe->stream->info.metadata_info,
5870 #if !defined(HAS_NO_INPUT_SYSTEM)
5871 pipe->stream->config.source.port.port,
5876 /* make the video pipe start with mem mode input, copy handles
5878 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5881 /* Construct and load the capture pipe */
5882 if (pipe->stream->cont_capt) {
5883 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5884 IA_CSS_PIPE_ID_CAPTURE,
5885 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5886 capture_pipe->config.default_capture_config.enable_xnr != 0,
5887 capture_pipe->stream->config.pixels_per_clock == 2,
5888 true, /* continuous */
5889 false, /* offline */
5890 capture_pipe->required_bds_factor,
5892 IA_CSS_INPUT_MODE_MEMORY,
5893 &pipe->stream->config.metadata_config,
5894 &pipe->stream->info.metadata_info,
5895 #if !defined(HAS_NO_INPUT_SYSTEM)
5896 (enum mipi_port_id)0,
5902 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5904 IA_CSS_LEAVE_ERR_PRIVATE(err);
5909 int sh_css_pipe_get_viewfinder_frame_info(
5910 struct ia_css_pipe *pipe,
5911 struct ia_css_frame_info *info,
5917 /* We could print the pointer as input arg, and the values as output */
5918 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5919 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5921 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5922 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5923 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5925 /* offline video does not generate viewfinder output */
5926 *info = pipe->vf_output_info[idx];
5928 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5929 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5930 info.res.width=%d, info.res.height=%d, \
5931 info.padded_width=%d, info.format=%d, \
5932 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5933 info->res.width, info->res.height,
5934 info->padded_width, info->format,
5935 info->raw_bit_depth, info->raw_bayer_order);
5941 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
5942 unsigned int height, unsigned int min_width,
5943 enum ia_css_frame_format format,
5947 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
5948 pipe, width, height, min_width, format, idx);
5952 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
5956 err = ia_css_util_check_res(width, height);
5959 IA_CSS_LEAVE_ERR_PRIVATE(err);
5962 if (pipe->vf_output_info[idx].res.width != width ||
5963 pipe->vf_output_info[idx].res.height != height ||
5964 pipe->vf_output_info[idx].format != format)
5966 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
5969 IA_CSS_LEAVE_ERR_PRIVATE(0);
5973 static int load_copy_binaries(struct ia_css_pipe *pipe)
5978 IA_CSS_ENTER_PRIVATE("");
5980 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5981 pipe->mode == IA_CSS_PIPE_ID_COPY);
5982 if (pipe->pipe_settings.capture.copy_binary.info)
5985 err = ia_css_frame_check_info(&pipe->output_info[0]);
5989 err = verify_copy_out_frame_format(pipe);
5993 err = load_copy_binary(pipe,
5994 &pipe->pipe_settings.capture.copy_binary,
5998 IA_CSS_LEAVE_ERR_PRIVATE(err);
6002 static bool need_capture_pp(
6003 const struct ia_css_pipe *pipe)
6005 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6007 IA_CSS_ENTER_LEAVE_PRIVATE("");
6009 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6012 /* ldc and capture_pp are not supported in the same pipeline */
6013 if (need_capt_ldc(pipe) == true)
6017 /* determine whether we need to use the capture_pp binary.
6018 * This is needed for:
6020 * 2. Digital Zoom or
6021 * 3. YUV downscaling
6023 if (pipe->out_yuv_ds_input_info.res.width &&
6024 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6025 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6028 if (pipe->config.default_capture_config.enable_xnr != 0)
6031 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6032 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6033 pipe->config.enable_dz)
6039 static bool need_capt_ldc(
6040 const struct ia_css_pipe *pipe)
6042 IA_CSS_ENTER_LEAVE_PRIVATE("");
6044 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6045 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
6048 static int set_num_primary_stages(unsigned int *num,
6049 enum ia_css_pipe_version version)
6057 case IA_CSS_PIPE_VERSION_2_6_1:
6058 *num = NUM_PRIMARY_HQ_STAGES;
6060 case IA_CSS_PIPE_VERSION_2_2:
6061 case IA_CSS_PIPE_VERSION_1:
6062 *num = NUM_PRIMARY_STAGES;
6072 static int load_primary_binaries(
6073 struct ia_css_pipe *pipe)
6075 bool online = false;
6076 bool memory = false;
6077 bool continuous = false;
6078 bool need_pp = false;
6079 bool need_isp_copy_binary = false;
6080 bool need_ldc = false;
6081 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6082 bool sensor = false;
6084 struct ia_css_frame_info prim_in_info,
6086 capt_pp_out_info, vf_info,
6087 *vf_pp_in_info, *pipe_out_info,
6088 *pipe_vf_out_info, *capt_pp_in_info,
6091 struct ia_css_capture_settings *mycs;
6093 bool need_extra_yuv_scaler = false;
6094 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6096 IA_CSS_ENTER_PRIVATE("");
6098 assert(pipe->stream);
6099 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6100 pipe->mode == IA_CSS_PIPE_ID_COPY);
6102 online = pipe->stream->config.online;
6103 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6104 continuous = pipe->stream->config.continuous;
6105 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6106 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6109 mycs = &pipe->pipe_settings.capture;
6110 pipe_out_info = &pipe->output_info[0];
6111 pipe_vf_out_info = &pipe->vf_output_info[0];
6113 if (mycs->primary_binary[0].info)
6116 err = set_num_primary_stages(&mycs->num_primary_stage,
6117 pipe->config.isp_pipe_version);
6119 IA_CSS_LEAVE_ERR_PRIVATE(err);
6123 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6124 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6126 IA_CSS_LEAVE_ERR_PRIVATE(err);
6130 err = ia_css_frame_check_info(pipe_out_info);
6132 IA_CSS_LEAVE_ERR_PRIVATE(err);
6136 need_pp = need_capture_pp(pipe);
6138 /* we use the vf output info to get the primary/capture_pp binary
6139 configured for vf_veceven. It will select the closest downscaling
6141 vf_info = *pipe_vf_out_info;
6144 * WARNING: The #if def flag has been added below as a
6145 * temporary solution to solve the problem of enabling the
6146 * view finder in a single binary in a capture flow. The
6147 * vf-pp stage has been removed for Skycam in the solution
6148 * provided. The vf-pp stage should be re-introduced when
6149 * required. This should not be considered as a clean solution.
6150 * Proper investigation should be done to come up with the clean
6153 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6155 /* TODO: All this yuv_scaler and capturepp calculation logic
6156 * can be shared later. Capture_pp is also a yuv_scale binary
6157 * with extra XNR funcionality. Therefore, it can be made as the
6158 * first step of the cascade. */
6159 capt_pp_out_info = pipe->out_yuv_ds_input_info;
6160 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6161 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
6162 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6163 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6165 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6166 pipe_out_info->res);
6168 if (need_extra_yuv_scaler) {
6169 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6171 err = ia_css_pipe_create_cas_scaler_desc_single_output(
6177 IA_CSS_LEAVE_ERR_PRIVATE(err);
6180 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6181 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6182 sizeof(struct ia_css_binary), GFP_KERNEL);
6183 if (!mycs->yuv_scaler_binary) {
6185 IA_CSS_LEAVE_ERR_PRIVATE(err);
6188 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6189 sizeof(bool), GFP_KERNEL);
6190 if (!mycs->is_output_stage) {
6192 IA_CSS_LEAVE_ERR_PRIVATE(err);
6195 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6196 struct ia_css_binary_descr yuv_scaler_descr;
6198 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6199 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6200 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6201 &cas_scaler_descr.out_info[i],
6202 &cas_scaler_descr.internal_out_info[i],
6203 &cas_scaler_descr.vf_info[i]);
6204 err = ia_css_binary_find(&yuv_scaler_descr,
6205 &mycs->yuv_scaler_binary[i]);
6207 IA_CSS_LEAVE_ERR_PRIVATE(err);
6211 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6214 capt_pp_out_info = pipe->output_info[0];
6217 /* TODO Do we disable ldc for skycam */
6218 need_ldc = need_capt_ldc(pipe);
6219 if (IS_ISP2401 && need_ldc) {
6220 /* ldc and capt_pp are not supported in the same pipeline */
6221 struct ia_css_binary_descr capt_ldc_descr;
6223 ia_css_pipe_get_ldc_binarydesc(pipe,
6224 &capt_ldc_descr, &prim_out_info,
6227 err = ia_css_binary_find(&capt_ldc_descr,
6228 &mycs->capture_ldc_binary);
6230 IA_CSS_LEAVE_ERR_PRIVATE(err);
6237 /* we build up the pipeline starting at the end */
6238 /* Capture post-processing */
6240 struct ia_css_binary_descr capture_pp_descr;
6243 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6245 capt_pp_in_info = &prim_out_info;
6247 ia_css_pipe_get_capturepp_binarydesc(pipe,
6248 &capture_pp_descr, capt_pp_in_info,
6249 &capt_pp_out_info, &vf_info);
6250 err = ia_css_binary_find(&capture_pp_descr,
6251 &mycs->capture_pp_binary);
6253 IA_CSS_LEAVE_ERR_PRIVATE(err);
6258 struct ia_css_binary_descr capt_ldc_descr;
6260 ia_css_pipe_get_ldc_binarydesc(pipe,
6261 &capt_ldc_descr, &prim_out_info,
6262 &capt_ldc_out_info);
6264 err = ia_css_binary_find(&capt_ldc_descr,
6265 &mycs->capture_ldc_binary);
6267 IA_CSS_LEAVE_ERR_PRIVATE(err);
6272 prim_out_info = *pipe_out_info;
6276 for (i = 0; i < mycs->num_primary_stage; i++) {
6277 struct ia_css_frame_info *local_vf_info = NULL;
6279 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
6280 (i == mycs->num_primary_stage - 1))
6281 local_vf_info = &vf_info;
6282 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info,
6283 &prim_out_info, local_vf_info, i);
6284 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6286 IA_CSS_LEAVE_ERR_PRIVATE(err);
6291 /* Viewfinder post-processing */
6293 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
6295 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6298 * WARNING: The #if def flag has been added below as a
6299 * temporary solution to solve the problem of enabling the
6300 * view finder in a single binary in a capture flow. The
6301 * vf-pp stage has been removed for Skycam in the solution
6302 * provided. The vf-pp stage should be re-introduced when
6303 * required. Thisshould not be considered as a clean solution.
6304 * Proper * investigation should be done to come up with the clean
6307 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6308 struct ia_css_binary_descr vf_pp_descr;
6310 ia_css_pipe_get_vfpp_binarydesc(pipe,
6311 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6312 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6314 IA_CSS_LEAVE_ERR_PRIVATE(err);
6318 err = allocate_delay_frames(pipe);
6323 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6324 /* When the input system is 2401, only the Direct Sensor Mode
6325 * Offline Capture uses the ISP copy binary.
6327 need_isp_copy_binary = !online && sensor;
6329 need_isp_copy_binary = !online && !continuous && !memory;
6333 if (need_isp_copy_binary) {
6334 err = load_copy_binary(pipe,
6336 &mycs->primary_binary[0]);
6338 IA_CSS_LEAVE_ERR_PRIVATE(err);
6347 allocate_delay_frames(struct ia_css_pipe *pipe) {
6348 unsigned int num_delay_frames = 0, i = 0;
6349 unsigned int dvs_frame_delay = 0;
6350 struct ia_css_frame_info ref_info;
6352 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6353 struct ia_css_frame **delay_frames = NULL;
6355 IA_CSS_ENTER_PRIVATE("");
6359 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6364 dvs_frame_delay = pipe->dvs_frame_delay;
6366 if (dvs_frame_delay > 0)
6367 num_delay_frames = dvs_frame_delay + 1;
6371 case IA_CSS_PIPE_ID_CAPTURE: {
6372 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6377 case IA_CSS_PIPE_ID_VIDEO: {
6378 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6380 ref_info = mycs_video->video_binary.internal_frame_info;
6381 /*The ref frame expects
6383 * 2. UV plane with line interleaving, like below
6384 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6386 * This format is not YUV420(which has Y, U and V planes).
6387 * Its closer to NV12, except that the UV plane has UV
6388 * interleaving, like UVUVUVUVUVUVUVUVU...
6390 * TODO: make this ref_frame format as a separate frame format
6392 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6393 delay_frames = mycs_video->delay_frames;
6396 case IA_CSS_PIPE_ID_PREVIEW: {
6397 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6399 ref_info = mycs_preview->preview_binary.internal_frame_info;
6400 /*The ref frame expects
6402 * 2. UV plane with line interleaving, like below
6403 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6405 * This format is not YUV420(which has Y, U and V planes).
6406 * Its closer to NV12, except that the UV plane has UV
6407 * interleaving, like UVUVUVUVUVUVUVUVU...
6409 * TODO: make this ref_frame format as a separate frame format
6411 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6412 delay_frames = mycs_preview->delay_frames;
6419 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6421 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6422 for (i = 0; i < num_delay_frames; i++)
6424 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6428 IA_CSS_LEAVE_PRIVATE("");
6432 static int load_advanced_binaries(
6433 struct ia_css_pipe *pipe) {
6434 struct ia_css_frame_info pre_in_info, gdc_in_info,
6435 post_in_info, post_out_info,
6436 vf_info, *vf_pp_in_info, *pipe_out_info,
6439 bool need_isp_copy = true;
6442 IA_CSS_ENTER_PRIVATE("");
6445 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6446 pipe->mode == IA_CSS_PIPE_ID_COPY);
6447 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6449 pipe_out_info = &pipe->output_info[0];
6450 pipe_vf_out_info = &pipe->vf_output_info[0];
6452 vf_info = *pipe_vf_out_info;
6453 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6456 need_pp = need_capture_pp(pipe);
6458 ia_css_frame_info_set_format(&vf_info,
6459 IA_CSS_FRAME_FORMAT_YUV_LINE);
6461 /* we build up the pipeline starting at the end */
6462 /* Capture post-processing */
6464 struct ia_css_binary_descr capture_pp_descr;
6466 ia_css_pipe_get_capturepp_binarydesc(pipe,
6467 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6468 err = ia_css_binary_find(&capture_pp_descr,
6469 &pipe->pipe_settings.capture.capture_pp_binary);
6473 post_out_info = *pipe_out_info;
6478 struct ia_css_binary_descr post_gdc_descr;
6480 ia_css_pipe_get_post_gdc_binarydesc(pipe,
6481 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6482 err = ia_css_binary_find(&post_gdc_descr,
6483 &pipe->pipe_settings.capture.post_isp_binary);
6490 struct ia_css_binary_descr gdc_descr;
6492 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6493 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6494 err = ia_css_binary_find(&gdc_descr,
6495 &pipe->pipe_settings.capture.anr_gdc_binary);
6499 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6500 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6504 struct ia_css_binary_descr pre_gdc_descr;
6506 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6507 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6508 err = ia_css_binary_find(&pre_gdc_descr,
6509 &pipe->pipe_settings.capture.pre_isp_binary);
6513 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6514 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6516 /* Viewfinder post-processing */
6519 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6522 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6526 struct ia_css_binary_descr vf_pp_descr;
6528 ia_css_pipe_get_vfpp_binarydesc(pipe,
6529 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6530 err = ia_css_binary_find(&vf_pp_descr,
6531 &pipe->pipe_settings.capture.vf_pp_binary);
6537 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6538 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6539 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6542 load_copy_binary(pipe,
6543 &pipe->pipe_settings.capture.copy_binary,
6544 &pipe->pipe_settings.capture.pre_isp_binary);
6549 static int load_bayer_isp_binaries(
6550 struct ia_css_pipe *pipe) {
6551 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6553 struct ia_css_binary_descr pre_de_descr;
6555 IA_CSS_ENTER_PRIVATE("");
6557 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6558 pipe->mode == IA_CSS_PIPE_ID_COPY);
6559 pipe_out_info = &pipe->output_info[0];
6561 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6564 err = ia_css_frame_check_info(pipe_out_info);
6568 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6572 err = ia_css_binary_find(&pre_de_descr,
6573 &pipe->pipe_settings.capture.pre_isp_binary);
6578 static int load_low_light_binaries(
6579 struct ia_css_pipe *pipe) {
6580 struct ia_css_frame_info pre_in_info, anr_in_info,
6581 post_in_info, post_out_info,
6582 vf_info, *pipe_vf_out_info, *pipe_out_info,
6585 bool need_isp_copy = true;
6588 IA_CSS_ENTER_PRIVATE("");
6590 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6591 pipe->mode == IA_CSS_PIPE_ID_COPY);
6593 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6595 pipe_vf_out_info = &pipe->vf_output_info[0];
6596 pipe_out_info = &pipe->output_info[0];
6598 vf_info = *pipe_vf_out_info;
6599 err = ia_css_util_check_vf_out_info(pipe_out_info,
6603 need_pp = need_capture_pp(pipe);
6605 ia_css_frame_info_set_format(&vf_info,
6606 IA_CSS_FRAME_FORMAT_YUV_LINE);
6608 /* we build up the pipeline starting at the end */
6609 /* Capture post-processing */
6611 struct ia_css_binary_descr capture_pp_descr;
6613 ia_css_pipe_get_capturepp_binarydesc(pipe,
6614 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6615 err = ia_css_binary_find(&capture_pp_descr,
6616 &pipe->pipe_settings.capture.capture_pp_binary);
6620 post_out_info = *pipe_out_info;
6625 struct ia_css_binary_descr post_anr_descr;
6627 ia_css_pipe_get_post_anr_binarydesc(pipe,
6628 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6629 err = ia_css_binary_find(&post_anr_descr,
6630 &pipe->pipe_settings.capture.post_isp_binary);
6637 struct ia_css_binary_descr anr_descr;
6639 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6640 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6641 err = ia_css_binary_find(&anr_descr,
6642 &pipe->pipe_settings.capture.anr_gdc_binary);
6646 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6647 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6651 struct ia_css_binary_descr pre_anr_descr;
6653 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6654 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6655 err = ia_css_binary_find(&pre_anr_descr,
6656 &pipe->pipe_settings.capture.pre_isp_binary);
6660 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6661 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6663 /* Viewfinder post-processing */
6666 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6669 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6673 struct ia_css_binary_descr vf_pp_descr;
6675 ia_css_pipe_get_vfpp_binarydesc(pipe,
6676 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6677 err = ia_css_binary_find(&vf_pp_descr,
6678 &pipe->pipe_settings.capture.vf_pp_binary);
6684 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6685 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6686 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6689 err = load_copy_binary(pipe,
6690 &pipe->pipe_settings.capture.copy_binary,
6691 &pipe->pipe_settings.capture.pre_isp_binary);
6696 static bool copy_on_sp(struct ia_css_pipe *pipe)
6701 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6705 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6707 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6709 rval &= ((pipe->stream->config.input_config.format ==
6710 ATOMISP_INPUT_FORMAT_BINARY_8) ||
6711 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6716 static int load_capture_binaries(
6717 struct ia_css_pipe *pipe) {
6721 IA_CSS_ENTER_PRIVATE("");
6723 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6724 pipe->mode == IA_CSS_PIPE_ID_COPY);
6726 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6727 IA_CSS_LEAVE_ERR_PRIVATE(0);
6731 /* in primary, advanced,low light or bayer,
6732 the input format must be raw */
6734 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6735 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6736 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6737 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6739 IA_CSS_LEAVE_ERR_PRIVATE(err);
6742 if (copy_on_sp(pipe) &&
6743 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6744 ia_css_frame_info_init(
6745 &pipe->output_info[0],
6748 IA_CSS_FRAME_FORMAT_BINARY_8,
6750 IA_CSS_LEAVE_ERR_PRIVATE(0);
6754 switch (pipe->config.default_capture_config.mode) {
6755 case IA_CSS_CAPTURE_MODE_RAW:
6756 err = load_copy_binaries(pipe);
6757 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6759 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6762 case IA_CSS_CAPTURE_MODE_BAYER:
6763 err = load_bayer_isp_binaries(pipe);
6765 case IA_CSS_CAPTURE_MODE_PRIMARY:
6766 err = load_primary_binaries(pipe);
6768 case IA_CSS_CAPTURE_MODE_ADVANCED:
6769 err = load_advanced_binaries(pipe);
6771 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6772 err = load_low_light_binaries(pipe);
6776 IA_CSS_LEAVE_ERR_PRIVATE(err);
6780 IA_CSS_LEAVE_ERR_PRIVATE(err);
6785 unload_capture_binaries(struct ia_css_pipe *pipe) {
6788 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6790 if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY)))
6792 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
6795 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6796 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6797 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6798 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6799 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6800 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6801 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6802 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6803 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6805 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6806 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6808 kfree(pipe->pipe_settings.capture.is_output_stage);
6809 pipe->pipe_settings.capture.is_output_stage = NULL;
6810 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6811 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6813 IA_CSS_LEAVE_ERR_PRIVATE(0);
6818 need_downscaling(const struct ia_css_resolution in_res,
6819 const struct ia_css_resolution out_res) {
6820 if (in_res.width > out_res.width || in_res.height > out_res.height)
6827 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
6829 struct ia_css_resolution in_res, out_res;
6831 bool need_format_conversion = false;
6833 IA_CSS_ENTER_PRIVATE("");
6835 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6837 /* TODO: make generic function */
6838 need_format_conversion =
6839 ((pipe->stream->config.input_config.format ==
6840 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6841 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6843 in_res = pipe->config.input_effective_res;
6845 if (pipe->config.enable_dz)
6848 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6851 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6852 out_res = pipe->output_info[i].res;
6854 /* A non-zero width means it is a valid output port */
6855 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6862 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6863 /* which has some hard-coded knowledge which prevents reuse of the function. */
6864 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6865 static int ia_css_pipe_create_cas_scaler_desc_single_output(
6866 struct ia_css_frame_info *cas_scaler_in_info,
6867 struct ia_css_frame_info *cas_scaler_out_info,
6868 struct ia_css_frame_info *cas_scaler_vf_info,
6869 struct ia_css_cas_binary_descr *descr) {
6871 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6873 struct ia_css_frame_info tmp_in_info;
6875 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6877 assert(cas_scaler_in_info);
6878 assert(cas_scaler_out_info);
6880 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6881 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6883 /* We assume that this function is used only for single output port case. */
6884 descr->num_output_stage = 1;
6886 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6887 cas_scaler_out_info->res.width);
6888 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6889 cas_scaler_out_info->res.height);
6890 /* use the same horizontal and vertical downscaling factor for simplicity */
6891 assert(hor_ds_factor == ver_ds_factor);
6894 while (i < hor_ds_factor) {
6896 i *= max_scale_factor_per_stage;
6899 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6901 if (!descr->in_info) {
6905 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
6906 struct ia_css_frame_info), GFP_KERNEL);
6907 if (!descr->internal_out_info) {
6911 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6913 if (!descr->out_info) {
6917 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6919 if (!descr->vf_info) {
6923 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
6924 if (!descr->is_output_stage) {
6929 tmp_in_info = *cas_scaler_in_info;
6930 for (i = 0; i < descr->num_stage; i++) {
6931 descr->in_info[i] = tmp_in_info;
6932 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6933 cas_scaler_out_info->res.width) {
6934 descr->is_output_stage[i] = true;
6935 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6936 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
6937 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
6938 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
6939 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6941 assert(i == (descr->num_stage - 1));
6942 descr->internal_out_info[i].res.width = 0;
6943 descr->internal_out_info[i].res.height = 0;
6945 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
6946 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
6947 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
6948 descr->out_info[i].format = cas_scaler_out_info->format;
6949 if (cas_scaler_vf_info) {
6950 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
6951 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
6952 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
6953 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6955 descr->vf_info[i].res.width = 0;
6956 descr->vf_info[i].res.height = 0;
6957 descr->vf_info[i].padded_width = 0;
6960 descr->is_output_stage[i] = false;
6961 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6962 max_scale_factor_per_stage;
6963 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6964 max_scale_factor_per_stage;
6965 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6966 ia_css_frame_info_init(&descr->internal_out_info[i],
6967 tmp_in_info.res.width / max_scale_factor_per_stage,
6968 tmp_in_info.res.height / max_scale_factor_per_stage,
6969 IA_CSS_FRAME_FORMAT_YUV420, 0);
6970 descr->out_info[i].res.width = 0;
6971 descr->out_info[i].res.height = 0;
6972 descr->vf_info[i].res.width = 0;
6973 descr->vf_info[i].res.height = 0;
6975 tmp_in_info = descr->internal_out_info[i];
6978 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6979 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6984 /* FIXME: merge most of this and single output version */
6985 static int ia_css_pipe_create_cas_scaler_desc(
6986 struct ia_css_pipe *pipe,
6987 struct ia_css_cas_binary_descr *descr) {
6988 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6989 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6990 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6991 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6993 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6994 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6996 unsigned int num_stages = 0;
6999 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
7001 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7002 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
7004 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7006 vf_out_info[i] = NULL;
7007 hor_scale_factor[i] = 0;
7008 ver_scale_factor[i] = 0;
7011 in_info.res = pipe->config.input_effective_res;
7012 in_info.padded_width = in_info.res.width;
7013 descr->num_output_stage = 0;
7014 /* Find out how much scaling we need for each output */
7015 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7016 if (pipe->output_info[i].res.width != 0) {
7017 out_info[i] = &pipe->output_info[i];
7018 if (pipe->vf_output_info[i].res.width != 0)
7019 vf_out_info[i] = &pipe->vf_output_info[i];
7020 descr->num_output_stage += 1;
7024 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7025 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7026 /* use the same horizontal and vertical scaling factor for simplicity */
7027 assert(hor_scale_factor[i] == ver_scale_factor[i]);
7031 scale_factor *= max_scale_factor_per_stage;
7032 } while (scale_factor < hor_scale_factor[i]);
7034 in_info.res = out_info[i]->res;
7038 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7041 descr->num_stage = num_stages;
7043 descr->in_info = kmalloc_array(descr->num_stage,
7044 sizeof(struct ia_css_frame_info), GFP_KERNEL);
7045 if (!descr->in_info) {
7049 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
7050 struct ia_css_frame_info), GFP_KERNEL);
7051 if (!descr->internal_out_info) {
7055 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7057 if (!descr->out_info) {
7061 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7063 if (!descr->vf_info) {
7067 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7068 if (!descr->is_output_stage) {
7073 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7076 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
7077 (out_info[i - 1]->res.height >= out_info[i]->res.height));
7082 tmp_in_info.res = pipe->config.input_effective_res;
7083 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7084 for (i = 0, j = 0; i < descr->num_stage; i++) {
7086 assert(out_info[j]);
7088 descr->in_info[i] = tmp_in_info;
7089 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
7090 out_info[j]->res.width) {
7091 descr->is_output_stage[i] = true;
7092 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7093 descr->internal_out_info[i].res.width = out_info[j]->res.width;
7094 descr->internal_out_info[i].res.height = out_info[j]->res.height;
7095 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7096 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7098 assert(i == (descr->num_stage - 1));
7099 descr->internal_out_info[i].res.width = 0;
7100 descr->internal_out_info[i].res.height = 0;
7102 descr->out_info[i].res.width = out_info[j]->res.width;
7103 descr->out_info[i].res.height = out_info[j]->res.height;
7104 descr->out_info[i].padded_width = out_info[j]->padded_width;
7105 descr->out_info[i].format = out_info[j]->format;
7106 if (vf_out_info[j]) {
7107 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7108 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7109 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7110 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7112 descr->vf_info[i].res.width = 0;
7113 descr->vf_info[i].res.height = 0;
7114 descr->vf_info[i].padded_width = 0;
7118 descr->is_output_stage[i] = false;
7119 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
7120 max_scale_factor_per_stage;
7121 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
7122 max_scale_factor_per_stage;
7123 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7124 ia_css_frame_info_init(&descr->internal_out_info[i],
7125 tmp_in_info.res.width / max_scale_factor_per_stage,
7126 tmp_in_info.res.height / max_scale_factor_per_stage,
7127 IA_CSS_FRAME_FORMAT_YUV420, 0);
7128 descr->out_info[i].res.width = 0;
7129 descr->out_info[i].res.height = 0;
7130 descr->vf_info[i].res.width = 0;
7131 descr->vf_info[i].res.height = 0;
7133 tmp_in_info = descr->internal_out_info[i];
7136 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7137 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7142 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
7144 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7145 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7146 kfree(descr->in_info);
7147 descr->in_info = NULL;
7148 kfree(descr->internal_out_info);
7149 descr->internal_out_info = NULL;
7150 kfree(descr->out_info);
7151 descr->out_info = NULL;
7152 kfree(descr->vf_info);
7153 descr->vf_info = NULL;
7154 kfree(descr->is_output_stage);
7155 descr->is_output_stage = NULL;
7156 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7157 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7161 load_yuvpp_binaries(struct ia_css_pipe *pipe) {
7163 bool need_scaler = false;
7164 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7165 struct ia_css_yuvpp_settings *mycs;
7166 struct ia_css_binary *next_binary;
7167 struct ia_css_cas_binary_descr cas_scaler_descr = { };
7169 bool need_isp_copy_binary = false;
7171 IA_CSS_ENTER_PRIVATE("");
7173 assert(pipe->stream);
7174 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7176 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7179 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7180 err = ia_css_util_check_input(&pipe->stream->config, false, false);
7184 mycs = &pipe->pipe_settings.yuvpp;
7186 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7188 if (pipe->vf_output_info[i].res.width != 0) {
7189 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7190 &pipe->vf_output_info[i]);
7194 vf_pp_in_info[i] = NULL;
7197 need_scaler = need_yuv_scaler_stage(pipe);
7199 /* we build up the pipeline starting at the end */
7200 /* Capture post-processing */
7203 struct ia_css_binary_descr yuv_scaler_descr;
7205 err = ia_css_pipe_create_cas_scaler_desc(pipe,
7209 mycs->num_output = cas_scaler_descr.num_output_stage;
7210 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
7211 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7212 sizeof(struct ia_css_binary), GFP_KERNEL);
7213 if (!mycs->yuv_scaler_binary) {
7217 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7218 sizeof(bool), GFP_KERNEL);
7219 if (!mycs->is_output_stage) {
7223 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7224 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7225 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7226 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7227 &cas_scaler_descr.out_info[i],
7228 &cas_scaler_descr.internal_out_info[i],
7229 &cas_scaler_descr.vf_info[i]);
7230 err = ia_css_binary_find(&yuv_scaler_descr,
7231 &mycs->yuv_scaler_binary[i]);
7235 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7238 mycs->num_output = 1;
7243 next_binary = &mycs->yuv_scaler_binary[0];
7249 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7252 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7253 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
7255 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7256 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7257 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7259 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7260 * _scale_binary". It would translate the input-frame to the frame formats that
7261 * are supported by the "yuv_scale_binary".
7263 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7264 * pp_defs.h" for the list of input-frame formats that are supported by the
7265 * "yuv_scale_binary".
7267 need_isp_copy_binary =
7268 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7269 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7270 need_isp_copy_binary = true;
7271 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7273 if (need_isp_copy_binary)
7275 err = load_copy_binary(pipe,
7284 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7286 * In some use cases, the first stage in the "yuvpp" pipe is the
7287 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7288 * the input from either the system DDR or from the IPU internal VMEM.
7289 * So it provides the flag "online" to specify where its input is from,
7292 * (1) "online <= true", the input is from the IPU internal VMEM.
7293 * (2) "online <= false", the input is from the system DDR.
7295 * In other use cases, the first stage in the "yuvpp" pipe is the
7296 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7297 * input ONLY from the system DDR. So it does not provide the flag "online"
7298 * to specify where its input is from.
7300 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7303 /* Viewfinder post-processing */
7306 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7307 if (mycs->is_output_stage[i]) {
7310 &mycs->yuv_scaler_binary[i].vf_frame_info;
7314 mycs->num_vf_pp = j;
7318 &mycs->copy_binary.vf_frame_info;
7319 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7320 vf_pp_in_info[i] = NULL;
7322 mycs->num_vf_pp = 1;
7324 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7326 if (!mycs->vf_pp_binary)
7333 struct ia_css_binary_descr vf_pp_descr;
7335 for (i = 0; i < mycs->num_vf_pp; i++)
7337 if (pipe->vf_output_info[i].res.width != 0) {
7338 ia_css_pipe_get_vfpp_binarydesc(pipe,
7339 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7340 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7353 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7355 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7361 unload_yuvpp_binaries(struct ia_css_pipe *pipe) {
7364 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7366 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7368 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7371 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7372 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
7374 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7376 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
7378 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7380 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7381 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7382 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7383 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7384 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7385 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7387 IA_CSS_LEAVE_ERR_PRIVATE(0);
7391 static int yuvpp_start(struct ia_css_pipe *pipe)
7393 struct ia_css_binary *copy_binary;
7395 enum sh_css_pipe_config_override copy_ovrd;
7396 enum ia_css_input_mode yuvpp_pipe_input_mode;
7398 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7399 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7400 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7404 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7406 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7408 sh_css_metrics_start_frame();
7410 /* multi stream video needs mipi buffers */
7412 #if !defined(HAS_NO_INPUT_SYSTEM) && (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401))
7413 err = send_mipi_frames(pipe);
7415 IA_CSS_LEAVE_ERR_PRIVATE(err);
7421 unsigned int thread_id;
7423 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7424 copy_ovrd = 1 << thread_id;
7427 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7429 IA_CSS_LEAVE_ERR_PRIVATE(err);
7434 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
7437 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7441 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7444 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7445 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7447 IA_CSS_LEAVE_ERR_PRIVATE(0);
7453 case IA_CSS_PIPE_ID_PREVIEW:
7454 err = unload_preview_binaries(pipe);
7456 case IA_CSS_PIPE_ID_VIDEO:
7457 err = unload_video_binaries(pipe);
7459 case IA_CSS_PIPE_ID_CAPTURE:
7460 err = unload_capture_binaries(pipe);
7462 case IA_CSS_PIPE_ID_YUVPP:
7463 err = unload_yuvpp_binaries(pipe);
7468 IA_CSS_LEAVE_ERR_PRIVATE(err);
7473 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
7477 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7479 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7480 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7485 case IA_CSS_PIPE_ID_PREVIEW:
7486 err = load_preview_binaries(pipe);
7488 case IA_CSS_PIPE_ID_VIDEO:
7489 err = load_video_binaries(pipe);
7491 case IA_CSS_PIPE_ID_CAPTURE:
7492 err = load_capture_binaries(pipe);
7494 case IA_CSS_PIPE_ID_YUVPP:
7495 err = load_yuvpp_binaries(pipe);
7497 case IA_CSS_PIPE_ID_ACC:
7505 if (sh_css_pipe_unload_binaries(pipe)) {
7506 /* currently css does not support multiple error returns in a single function,
7507 * using -EINVAL in this case */
7515 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
7516 struct ia_css_pipeline *me;
7518 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7520 *yuv_scaler_stage = NULL;
7521 struct ia_css_binary *copy_binary,
7524 bool need_scaler = false;
7525 unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7528 struct ia_css_frame *in_frame = NULL;
7529 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7530 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7531 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7532 struct ia_css_pipeline_stage_desc stage_desc;
7533 bool need_in_frameinfo_memory = false;
7534 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7535 bool sensor = false;
7536 bool buffered_sensor = false;
7537 bool online = false;
7538 bool continuous = false;
7541 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7542 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7544 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7547 me = &pipe->pipeline;
7548 ia_css_pipeline_clean(me);
7549 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7551 out_frame[i] = NULL;
7554 ia_css_pipe_util_create_output_frames(bin_out_frame);
7555 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7556 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp;
7557 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7559 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7560 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7561 * except for the following:
7562 * - Direct Sensor Mode Online Capture
7563 * - Direct Sensor Mode Continuous Capture
7564 * - Buffered Sensor Mode Continuous Capture
7566 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7567 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7568 online = pipe->stream->config.online;
7569 continuous = pipe->stream->config.continuous;
7570 need_in_frameinfo_memory =
7571 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7573 /* Construct in_frame info (only in case we have dynamic input */
7574 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7576 /* the input frame can come from:
7577 * a) memory: connect yuvscaler to me->in_frame
7578 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7579 if (need_in_frameinfo_memory)
7581 /* TODO: improve for different input formats. */
7584 * "pipe->stream->config.input_config.format" represents the sensor output
7585 * frame format, e.g. YUV422 8-bit.
7587 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7590 int in_frame_format;
7592 if (pipe->stream->config.input_config.format ==
7593 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7594 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7595 } else if (pipe->stream->config.input_config.format ==
7596 ATOMISP_INPUT_FORMAT_YUV422_8) {
7598 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
7599 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7602 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7603 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7605 * By now, the "isp_copy_var" binary does NOT provide a separated
7606 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7607 * the YUV422-8 pixels in the frame-line buffer which is designed to
7608 * store the Bayer-Quad RAW pixels.
7610 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7611 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7614 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7616 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7619 err = init_in_frameinfo_memory_defaults(pipe,
7624 IA_CSS_LEAVE_ERR_PRIVATE(err);
7628 in_frame = &me->in_frame;
7634 for (i = 0; i < num_output_stage; i++)
7636 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7637 if (pipe->output_info[i].res.width != 0) {
7638 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7640 IA_CSS_LEAVE_ERR_PRIVATE(err);
7643 out_frame[i] = &me->out_frame[i];
7646 /* Construct vf_frame info (only in case we have VF) */
7647 if (pipe->vf_output_info[i].res.width != 0) {
7648 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7650 IA_CSS_LEAVE_ERR_PRIVATE(err);
7653 vf_frame[i] = &me->vf_frame[i];
7657 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7658 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7659 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7660 need_scaler = need_yuv_scaler_stage(pipe);
7662 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7664 struct ia_css_frame *in_frame_local = NULL;
7666 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7667 /* After isp copy is enabled in_frame needs to be passed. */
7669 in_frame_local = in_frame;
7673 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7674 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7675 bin_out_frame, in_frame_local, NULL);
7677 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7678 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7679 bin_out_frame, in_frame_local, NULL);
7682 err = ia_css_pipeline_create_and_add_stage(me,
7687 IA_CSS_LEAVE_ERR_PRIVATE(err);
7692 /* if we use yuv scaler binary, vf output should be from there */
7693 copy_stage->args.copy_vf = !need_scaler;
7694 /* for yuvpp pipe, it should always be enabled */
7695 copy_stage->args.copy_output = true;
7696 /* connect output of copy binary to input of yuv scaler */
7697 in_frame = copy_stage->args.out_frame[0];
7703 struct ia_css_frame *tmp_out_frame = NULL;
7704 struct ia_css_frame *tmp_vf_frame = NULL;
7705 struct ia_css_frame *tmp_in_frame = in_frame;
7707 for (i = 0, j = 0; i < num_stage; i++) {
7708 assert(j < num_output_stage);
7709 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7710 tmp_out_frame = out_frame[j];
7711 tmp_vf_frame = vf_frame[j];
7713 tmp_out_frame = NULL;
7714 tmp_vf_frame = NULL;
7717 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7719 &yuv_scaler_binary[i],
7723 IA_CSS_LEAVE_ERR_PRIVATE(err);
7726 /* we use output port 1 as internal output port */
7727 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7728 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7729 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7730 in_frame = yuv_scaler_stage->args.out_vf_frame;
7731 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7735 IA_CSS_LEAVE_ERR_PRIVATE(err);
7742 } else if (copy_stage)
7744 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7745 in_frame = copy_stage->args.out_vf_frame;
7746 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7750 IA_CSS_LEAVE_ERR_PRIVATE(err);
7755 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7757 IA_CSS_LEAVE_ERR_PRIVATE(0);
7763 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7764 unsigned int max_input_width,
7765 struct ia_css_frame *out_frame) {
7766 struct ia_css_pipeline *me;
7768 struct ia_css_pipeline_stage_desc stage_desc;
7770 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7771 "create_host_copy_pipeline() enter:\n");
7773 /* pipeline already created as part of create_host_pipeline_structure */
7774 me = &pipe->pipeline;
7775 ia_css_pipeline_clean(me);
7777 /* Construct out_frame info */
7778 out_frame->contiguous = false;
7779 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7781 if (copy_on_sp(pipe) &&
7782 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
7784 ia_css_frame_info_init(
7788 IA_CSS_FRAME_FORMAT_BINARY_8,
7790 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW)
7792 out_frame->info.raw_bit_depth =
7793 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7797 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7798 pipe->mode = IA_CSS_PIPE_ID_COPY;
7800 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7801 IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7802 err = ia_css_pipeline_create_and_add_stage(me,
7806 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7808 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7809 "create_host_copy_pipeline() leave:\n");
7815 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
7816 struct ia_css_pipeline *me = &pipe->pipeline;
7818 struct ia_css_pipeline_stage_desc stage_desc;
7819 struct ia_css_frame *out_frame = &me->out_frame[0];
7820 struct ia_css_pipeline_stage *out_stage = NULL;
7821 unsigned int thread_id;
7822 enum sh_css_queue_id queue_id;
7823 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7825 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7826 "create_host_isyscopy_capture_pipeline() enter:\n");
7827 ia_css_pipeline_clean(me);
7829 /* Construct out_frame info */
7830 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7833 out_frame->contiguous = false;
7834 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7835 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7836 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7837 out_frame->dynamic_queue_id = queue_id;
7838 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7841 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7842 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7843 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7844 IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7845 err = ia_css_pipeline_create_and_add_stage(me,
7846 &stage_desc, &out_stage);
7850 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7852 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7853 "create_host_isyscopy_capture_pipeline() leave:\n");
7859 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
7860 struct ia_css_pipeline *me;
7862 enum ia_css_capture_mode mode;
7863 struct ia_css_pipeline_stage *current_stage = NULL;
7864 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7865 struct ia_css_binary *copy_binary,
7866 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7873 *capture_ldc_binary;
7874 bool need_pp = false;
7877 struct ia_css_frame *in_frame;
7878 struct ia_css_frame *out_frame;
7879 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7880 struct ia_css_frame *vf_frame;
7881 struct ia_css_pipeline_stage_desc stage_desc;
7882 bool need_in_frameinfo_memory = false;
7883 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7884 bool sensor = false;
7885 bool buffered_sensor = false;
7886 bool online = false;
7887 bool continuous = false;
7889 unsigned int i, num_yuv_scaler, num_primary_stage;
7890 bool need_yuv_pp = false;
7891 bool *is_output_stage = NULL;
7892 bool need_ldc = false;
7894 IA_CSS_ENTER_PRIVATE("");
7896 assert(pipe->stream);
7897 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7899 me = &pipe->pipeline;
7900 mode = pipe->config.default_capture_config.mode;
7901 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7902 ia_css_pipeline_clean(me);
7903 ia_css_pipe_util_create_output_frames(out_frames);
7905 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7906 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7907 * except for the following:
7908 * - Direct Sensor Mode Online Capture
7909 * - Direct Sensor Mode Online Capture
7910 * - Direct Sensor Mode Continuous Capture
7911 * - Buffered Sensor Mode Continuous Capture
7913 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7914 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7915 online = pipe->stream->config.online;
7916 continuous = pipe->stream->config.continuous;
7917 need_in_frameinfo_memory =
7918 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7920 /* Construct in_frame info (only in case we have dynamic input */
7921 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7923 if (need_in_frameinfo_memory)
7925 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
7926 IA_CSS_FRAME_FORMAT_RAW);
7928 IA_CSS_LEAVE_ERR_PRIVATE(err);
7932 in_frame = &me->in_frame;
7938 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7941 IA_CSS_LEAVE_ERR_PRIVATE(err);
7944 out_frame = &me->out_frame[0];
7946 /* Construct vf_frame info (only in case we have VF) */
7947 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
7949 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7950 /* These modes don't support viewfinder output */
7953 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7954 vf_frame = &me->vf_frame[0];
7961 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7962 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7963 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY))
7965 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
7968 for (i = 0; i < num_primary_stage; i++)
7970 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7972 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7973 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7974 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
7975 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
7976 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
7977 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
7978 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
7979 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
7980 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
7982 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
7983 mode != IA_CSS_CAPTURE_MODE_RAW &&
7984 mode != IA_CSS_CAPTURE_MODE_BAYER;
7985 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
7986 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
7988 if (pipe->pipe_settings.capture.copy_binary.info)
7991 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7992 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
7994 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7995 out_frames, in_frame, NULL);
7997 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7998 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7999 out_frames, in_frame, NULL);
8002 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8003 out_frames, NULL, NULL);
8006 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
8007 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8008 out_frames, NULL, NULL);
8011 err = ia_css_pipeline_create_and_add_stage(me,
8015 IA_CSS_LEAVE_ERR_PRIVATE(err);
8018 } else if (pipe->stream->config.continuous)
8020 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8023 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY)
8025 struct ia_css_frame *local_in_frame = NULL;
8026 struct ia_css_frame *local_out_frame = NULL;
8028 for (i = 0; i < num_primary_stage; i++) {
8030 local_in_frame = in_frame;
8032 local_in_frame = NULL;
8034 if (!need_pp && (i == num_primary_stage - 1))
8036 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8038 local_out_frame = out_frame;
8040 local_out_frame = NULL;
8041 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8043 * WARNING: The #if def flag has been added below as a
8044 * temporary solution to solve the problem of enabling the
8045 * view finder in a single binary in a capture flow. The
8046 * vf-pp stage has been removed from Skycam in the solution
8047 * provided. The vf-pp stage should be re-introduced when
8048 * required. This * should not be considered as a clean solution.
8049 * Proper investigation should be done to come up with the clean
8052 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8053 out_frames, local_in_frame, NULL);
8054 err = ia_css_pipeline_create_and_add_stage(me,
8058 IA_CSS_LEAVE_ERR_PRIVATE(err);
8062 /* If we use copy iso primary,
8063 the input must be yuv iso raw */
8064 current_stage->args.copy_vf =
8065 primary_binary[0]->info->sp.pipeline.mode ==
8066 IA_CSS_BINARY_MODE_COPY;
8067 current_stage->args.copy_output = current_stage->args.copy_vf;
8068 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8069 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT)
8071 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8072 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8073 out_frames, in_frame, NULL);
8074 err = ia_css_pipeline_create_and_add_stage(me,
8077 IA_CSS_LEAVE_ERR_PRIVATE(err);
8080 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8081 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8082 out_frames, NULL, NULL);
8083 err = ia_css_pipeline_create_and_add_stage(me,
8086 IA_CSS_LEAVE_ERR_PRIVATE(err);
8091 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8092 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8093 out_frames, NULL, NULL);
8095 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8096 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8097 out_frames, NULL, NULL);
8100 err = ia_css_pipeline_create_and_add_stage(me,
8101 &stage_desc, ¤t_stage);
8103 IA_CSS_LEAVE_ERR_PRIVATE(err);
8106 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER)
8108 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8109 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8110 out_frames, in_frame, NULL);
8111 err = ia_css_pipeline_create_and_add_stage(me,
8115 IA_CSS_LEAVE_ERR_PRIVATE(err);
8121 if (need_pp && current_stage)
8123 struct ia_css_frame *local_in_frame = NULL;
8125 local_in_frame = current_stage->args.out_frame[0];
8128 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8129 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8130 out_frames, local_in_frame, NULL);
8131 err = ia_css_pipeline_create_and_add_stage(me,
8134 local_in_frame = current_stage->args.out_frame[0];
8136 err = add_capture_pp_stage(pipe, me, local_in_frame,
8137 need_yuv_pp ? NULL : out_frame,
8139 /* ldc and capture_pp not supported in same pipeline */
8140 if (need_ldc && current_stage)
8142 in_frame = current_stage->args.out_frame[0];
8143 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8144 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8145 out_frames, in_frame, NULL);
8146 err = ia_css_pipeline_create_and_add_stage(me,
8149 } else if (need_pp && current_stage)
8151 in_frame = current_stage->args.out_frame[0];
8152 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8157 IA_CSS_LEAVE_ERR_PRIVATE(err);
8162 if (need_yuv_pp && current_stage)
8164 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8165 struct ia_css_frame *tmp_out_frame = NULL;
8167 for (i = 0; i < num_yuv_scaler; i++) {
8168 if (is_output_stage[i] == true)
8169 tmp_out_frame = out_frame;
8171 tmp_out_frame = NULL;
8173 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8175 &yuv_scaler_binary[i],
8178 IA_CSS_LEAVE_ERR_PRIVATE(err);
8181 /* we use output port 1 as internal output port */
8182 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8187 * WARNING: The #if def flag has been added below as a
8188 * temporary solution to solve the problem of enabling the
8189 * view finder in a single binary in a capture flow. The vf-pp
8190 * stage has been removed from Skycam in the solution provided.
8191 * The vf-pp stage should be re-introduced when required. This
8192 * should not be considered as a clean solution. Proper
8193 * investigation should be done to come up with the clean solution.
8195 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame)
8197 in_frame = current_stage->args.out_vf_frame;
8198 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8201 IA_CSS_LEAVE_ERR_PRIVATE(err);
8205 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8207 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8208 "create_host_regular_capture_pipeline() leave:\n");
8214 create_host_capture_pipeline(struct ia_css_pipe *pipe) {
8217 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8219 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8220 err = create_host_isyscopy_capture_pipeline(pipe);
8222 err = create_host_regular_capture_pipeline(pipe);
8225 IA_CSS_LEAVE_ERR_PRIVATE(err);
8229 IA_CSS_LEAVE_ERR_PRIVATE(err);
8234 static int capture_start(
8235 struct ia_css_pipe *pipe) {
8236 struct ia_css_pipeline *me;
8239 enum sh_css_pipe_config_override copy_ovrd;
8241 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8243 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8247 me = &pipe->pipeline;
8249 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8250 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
8251 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8252 if (copy_on_sp(pipe)) {
8253 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8254 IA_CSS_LEAVE_ERR_PRIVATE(err);
8259 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8260 /* old isys: need to send_mipi_frames() in all pipe modes */
8261 err = send_mipi_frames(pipe);
8263 IA_CSS_LEAVE_ERR_PRIVATE(err);
8266 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8267 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8268 err = send_mipi_frames(pipe);
8270 IA_CSS_LEAVE_ERR_PRIVATE(err);
8278 unsigned int thread_id;
8280 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8281 copy_ovrd = 1 << thread_id;
8283 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8285 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8287 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8288 * which is currently done in start_binary(); but COPY pipe contains no binary,
8289 * and does not call start_binary(); so we need to configure the rx here.
8291 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
8292 pipe->stream->reconfigure_css_rx) {
8293 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
8294 pipe->stream->config.mode);
8295 pipe->stream->reconfigure_css_rx = false;
8299 IA_CSS_LEAVE_ERR_PRIVATE(err);
8304 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8305 struct ia_css_frame_info *info,
8310 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8311 "sh_css_pipe_get_output_frame_info() enter:\n");
8313 *info = pipe->output_info[idx];
8314 if (copy_on_sp(pipe) &&
8315 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
8317 ia_css_frame_info_init(
8321 IA_CSS_FRAME_FORMAT_BINARY_8,
8323 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8324 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
8326 info->raw_bit_depth =
8327 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8330 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8331 "sh_css_pipe_get_output_frame_info() leave:\n");
8335 #if !defined(HAS_NO_INPUT_SYSTEM)
8337 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8338 const unsigned short *data,
8340 unsigned int height) {
8343 ia_css_inputfifo_send_input_frame(
8344 data, width, height,
8345 stream->config.channel_id,
8346 stream->config.input_config.format,
8347 stream->config.pixels_per_clock == 2);
8351 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
8354 ia_css_inputfifo_start_frame(
8355 stream->config.channel_id,
8356 stream->config.input_config.format,
8357 stream->config.pixels_per_clock == 2);
8361 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8362 const unsigned short *data,
8364 const unsigned short *data2,
8365 unsigned int width2) {
8368 ia_css_inputfifo_send_line(stream->config.channel_id,
8369 data, width, data2, width2);
8373 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8374 enum atomisp_input_format format,
8375 const unsigned short *data,
8376 unsigned int width) {
8378 if (!data || width == 0)
8380 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8381 format, data, width);
8385 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) {
8388 ia_css_inputfifo_end_frame(stream->config.channel_id);
8393 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8394 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
8396 IA_CSS_ERROR("NULL fw_info");
8397 IA_CSS_LEAVE_PRIVATE("");
8403 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8404 IA_CSS_LEAVE_PRIVATE("");
8408 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8413 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8415 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8416 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8419 static int upload_isp_code(struct ia_css_fw_info *firmware)
8424 IA_CSS_ERROR("NULL input parameter");
8427 binary = firmware->info.isp.xmem_addr;
8430 unsigned int size = firmware->blob.size;
8431 const unsigned char *blob;
8432 const unsigned char *binary_name;
8435 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8437 blob = binary_name +
8438 strlen((const char *)binary_name) +
8440 binary = sh_css_load_blob(blob, size);
8441 firmware->info.isp.xmem_addr = binary;
8450 acc_load_extension(struct ia_css_fw_info *firmware) {
8452 struct ia_css_fw_info *hd = firmware;
8456 err = upload_isp_code(hd);
8464 firmware->loaded = true;
8469 acc_unload_extension(struct ia_css_fw_info *firmware) {
8470 struct ia_css_fw_info *hd = firmware;
8471 struct ia_css_fw_info *hdn = NULL;
8473 if (!firmware) /* should not happen */
8475 /* unload and remove multiple firmwares */
8477 hdn = (hd->next) ? &(*hd->next) : NULL;
8478 if (hd->info.isp.xmem_addr) {
8479 hmm_free(hd->info.isp.xmem_addr);
8480 hd->info.isp.xmem_addr = mmgr_NULL;
8482 hd->isp_code = NULL;
8487 firmware->loaded = false;
8490 /* Load firmware for extension */
8492 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8493 struct ia_css_fw_info *firmware) {
8496 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8498 if ((!firmware) || (!pipe))
8500 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8504 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8505 append_firmware(&pipe->output_stage, firmware);
8506 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8507 append_firmware(&pipe->vf_stage, firmware);
8508 err = acc_load_extension(firmware);
8510 IA_CSS_LEAVE_ERR_PRIVATE(err);
8514 /* Unload firmware for extension */
8516 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8517 struct ia_css_fw_info *firmware) {
8518 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8520 if ((!firmware) || (!pipe)) {
8521 IA_CSS_ERROR("NULL input parameters");
8522 IA_CSS_LEAVE_PRIVATE("");
8526 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8527 remove_firmware(&pipe->output_stage, firmware);
8528 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8529 remove_firmware(&pipe->vf_stage, firmware);
8530 acc_unload_extension(firmware);
8532 IA_CSS_LEAVE_PRIVATE("");
8536 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
8537 struct ia_css_pipeline_stage *stage;
8541 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8542 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8544 for (stage = me->stages; stage; stage = stage->next)
8545 if (stage->binary_info && stage->binary_info->enable.params) {
8546 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8547 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
8550 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8551 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8556 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8557 const void *acc_fw) {
8558 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8559 /* In QoS case, load_extension already called, so skipping */
8562 if (fw->loaded == false)
8563 err = acc_load_extension(fw);
8565 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8566 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
8571 struct ia_css_pipeline_stage_desc stage_desc;
8573 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8574 err = ia_css_pipeline_create_and_add_stage(pipeline,
8579 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8580 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
8585 * @brief Tag a specific frame in continuous capture.
8586 * Refer to "sh_css_internal.h" for details.
8588 int ia_css_stream_capture_frame(struct ia_css_stream *stream,
8589 unsigned int exp_id) {
8590 struct sh_css_tag_descr tag_descr;
8591 u32 encoded_tag_descr;
8595 IA_CSS_ENTER("exp_id=%d", exp_id);
8597 /* Only continuous streams have a tagger */
8598 if (exp_id == 0 || !stream->config.continuous) {
8599 IA_CSS_LEAVE_ERR(-EINVAL);
8603 if (!sh_css_sp_is_running()) {
8604 /* SP is not running. The queues are not valid */
8605 IA_CSS_LEAVE_ERR(-EBUSY);
8609 /* Create the tag descriptor from the parameters */
8610 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8611 /* Encode the tag descriptor into a 32-bit value */
8612 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8613 /* Enqueue the encoded tag to the host2sp queue.
8614 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8615 * on both host and the SP side.
8616 * It is mainly because it is enough to have only one tag_cmd queue */
8617 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8619 IA_CSS_LEAVE_ERR(err);
8624 * @brief Configure the continuous capture.
8625 * Refer to "sh_css_internal.h" for details.
8627 int ia_css_stream_capture(
8628 struct ia_css_stream *stream,
8632 struct sh_css_tag_descr tag_descr;
8633 unsigned int encoded_tag_descr;
8639 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8640 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8641 num_captures, skip, offset);
8643 /* Check if the tag descriptor is valid */
8644 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8645 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8646 "ia_css_stream_capture() leave: return_err=%d\n",
8651 /* Create the tag descriptor from the parameters */
8652 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8654 /* Encode the tag descriptor into a 32-bit value */
8655 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8657 if (!sh_css_sp_is_running()) {
8658 /* SP is not running. The queues are not valid */
8659 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8660 "ia_css_stream_capture() leaving:queues unavailable\n");
8664 /* Enqueue the encoded tag to the host2sp queue.
8665 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8666 * on both host and the SP side.
8667 * It is mainly because it is enough to have only one tag_cmd queue */
8668 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8670 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8671 "ia_css_stream_capture() leave: return_err=%d\n",
8677 void ia_css_stream_request_flash(struct ia_css_stream *stream)
8682 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8683 "ia_css_stream_request_flash() enter: void\n");
8686 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8688 if (sh_css_sp_is_running()) {
8689 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8690 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8691 ia_css_debug_dump_sp_sw_debug_info();
8692 ia_css_debug_dump_debug_info(NULL);
8695 IA_CSS_LOG("SP is not running!");
8698 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8699 "ia_css_stream_request_flash() leave: return_void\n");
8703 sh_css_init_host_sp_control_vars(void) {
8704 const struct ia_css_fw_info *fw;
8705 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8707 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8708 unsigned int HIVE_ADDR_sp_sleep_mode;
8709 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8711 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8713 unsigned int HIVE_ADDR_host_sp_com;
8714 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8717 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8721 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8722 "sh_css_init_host_sp_control_vars() enter: void\n");
8725 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8727 HIVE_ADDR_host_sp_queues_initialized =
8728 fw->info.sp.host_sp_queues_initialized;
8729 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8730 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8732 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8734 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8736 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8738 (void)HIVE_ADDR_sp_sleep_mode;
8739 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8741 (void)HIVE_ADDR_sp_stop_copy_preview;
8743 (void)HIVE_ADDR_host_sp_com;
8745 sp_dmem_store_uint32(SP0_ID,
8746 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8749 sp_dmem_store_uint32(SP0_ID,
8750 (unsigned int)sp_address_of(host_sp_queues_initialized),
8752 sp_dmem_store_uint32(SP0_ID,
8753 (unsigned int)sp_address_of(sp_sleep_mode),
8755 sp_dmem_store_uint32(SP0_ID,
8756 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8759 sp_dmem_store_uint32(SP0_ID,
8760 (unsigned int)sp_address_of(sp_stop_copy_preview),
8761 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8763 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8765 #if !defined(HAS_NO_INPUT_SYSTEM)
8766 for (i = 0; i < N_CSI_PORTS; i++) {
8767 sh_css_update_host2sp_num_mipi_frames
8768 (my_css.num_mipi_frames[i]);
8772 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8773 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8777 * create the internal structures and fill in the configuration data
8781 ia_css_pipe_config ia_css_pipe_default_config = DEFAULT_PIPE_CONFIG;
8783 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config)
8785 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8786 memcpy(pipe_config, &ia_css_pipe_default_config, sizeof(*pipe_config));
8790 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
8792 if (!extra_config) {
8793 IA_CSS_ERROR("NULL input parameter");
8797 extra_config->enable_raw_binning = false;
8798 extra_config->enable_yuv_ds = false;
8799 extra_config->enable_high_speed = false;
8800 extra_config->enable_dvs_6axis = false;
8801 extra_config->enable_reduced_pipe = false;
8802 extra_config->disable_vf_pp = false;
8803 extra_config->enable_fractional_ds = false;
8806 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config)
8808 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8809 assert(stream_config);
8810 memset(stream_config, 0, sizeof(*stream_config));
8811 stream_config->online = true;
8812 stream_config->left_padding = -1;
8813 stream_config->pixels_per_clock = 1;
8814 /* temporary default value for backwards compatibility.
8815 * This field used to be hardcoded within CSS but this has now
8816 * been moved to the stream_config struct. */
8817 stream_config->source.port.rxcount = 0x04040404;
8821 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
8826 IA_CSS_ERROR("NULL input parameter");
8830 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8831 if (pipe->config.acc_num_execs == 0)
8832 pipe->config.acc_num_execs = 1;
8834 if (pipe->config.acc_extension)
8836 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8843 ia_css_pipe_create(const struct ia_css_pipe_config *config,
8844 struct ia_css_pipe **pipe) {
8850 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8854 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8864 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8868 return ia_css_pipe_create_extra(config, NULL, pipe);
8872 err = ia_css_pipe_create_extra(config, NULL, pipe);
8876 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8879 IA_CSS_LEAVE_ERR_PRIVATE(err);
8886 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8887 const struct ia_css_pipe_extra_config *extra_config,
8888 struct ia_css_pipe **pipe) {
8890 struct ia_css_pipe *internal_pipe = NULL;
8893 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8895 /* do not allow to create more than the maximum limit */
8896 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX)
8898 IA_CSS_LEAVE_ERR_PRIVATE(-ENOSPC);
8902 if ((!pipe) || (!config))
8904 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
8908 ia_css_debug_dump_pipe_config(config);
8909 ia_css_debug_dump_pipe_extra_config(extra_config);
8911 err = create_pipe(config->mode, &internal_pipe, false);
8914 IA_CSS_LEAVE_ERR_PRIVATE(err);
8918 /* now we have a pipe structure to fill */
8919 internal_pipe->config = *config;
8921 internal_pipe->extra_config = *extra_config;
8923 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8925 if (config->mode == IA_CSS_PIPE_MODE_ACC)
8927 /* Temporary hack to migrate acceleration to CSS 2.0.
8928 * In the future the code for all pipe types should be
8930 *pipe = internal_pipe;
8931 if (!internal_pipe->config.acc_extension &&
8932 internal_pipe->config.num_acc_stages ==
8933 0) { /* if no acc binary and no standalone stage */
8935 IA_CSS_LEAVE_ERR_PRIVATE(0);
8938 return ia_css_acc_pipe_create(internal_pipe);
8941 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8942 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8943 internal_pipe->dvs_frame_delay = 2;
8945 internal_pipe->dvs_frame_delay = 1;
8947 /* we still keep enable_raw_binning for backward compatibility, for any new
8948 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8949 specified, bayer_ds_out_res will take precedence.if none is specified, we
8950 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8951 sensor output) or use default decimation factor 1. */
8952 if (internal_pipe->extra_config.enable_raw_binning &&
8953 internal_pipe->config.bayer_ds_out_res.width)
8955 /* fill some code here, if no code is needed, please remove it during integration */
8958 /* YUV downscaling */
8959 if ((internal_pipe->config.vf_pp_in_res.width ||
8960 internal_pipe->config.capt_pp_in_res.width))
8962 enum ia_css_frame_format format;
8964 if (internal_pipe->config.vf_pp_in_res.width) {
8965 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8966 ia_css_frame_info_init(
8967 &internal_pipe->vf_yuv_ds_input_info,
8968 internal_pipe->config.vf_pp_in_res.width,
8969 internal_pipe->config.vf_pp_in_res.height,
8972 if (internal_pipe->config.capt_pp_in_res.width) {
8973 format = IA_CSS_FRAME_FORMAT_YUV420;
8974 ia_css_frame_info_init(
8975 &internal_pipe->out_yuv_ds_input_info,
8976 internal_pipe->config.capt_pp_in_res.width,
8977 internal_pipe->config.capt_pp_in_res.height,
8981 if (internal_pipe->config.vf_pp_in_res.width &&
8982 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
8984 ia_css_frame_info_init(
8985 &internal_pipe->vf_yuv_ds_input_info,
8986 internal_pipe->config.vf_pp_in_res.width,
8987 internal_pipe->config.vf_pp_in_res.height,
8988 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
8990 /* handle bayer downscaling output info */
8991 if (internal_pipe->config.bayer_ds_out_res.width)
8993 ia_css_frame_info_init(
8994 &internal_pipe->bds_output_info,
8995 internal_pipe->config.bayer_ds_out_res.width,
8996 internal_pipe->config.bayer_ds_out_res.height,
8997 IA_CSS_FRAME_FORMAT_RAW, 0);
9000 /* handle output info, assume always needed */
9001 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
9003 if (internal_pipe->config.output_info[i].res.width) {
9004 err = sh_css_pipe_configure_output(
9006 internal_pipe->config.output_info[i].res.width,
9007 internal_pipe->config.output_info[i].res.height,
9008 internal_pipe->config.output_info[i].padded_width,
9009 internal_pipe->config.output_info[i].format,
9012 IA_CSS_LEAVE_ERR_PRIVATE(err);
9013 kvfree(internal_pipe);
9014 internal_pipe = NULL;
9019 /* handle vf output info, when configured */
9020 internal_pipe->enable_viewfinder[i] =
9021 (internal_pipe->config.vf_output_info[i].res.width != 0);
9022 if (internal_pipe->config.vf_output_info[i].res.width) {
9023 err = sh_css_pipe_configure_viewfinder(
9025 internal_pipe->config.vf_output_info[i].res.width,
9026 internal_pipe->config.vf_output_info[i].res.height,
9027 internal_pipe->config.vf_output_info[i].padded_width,
9028 internal_pipe->config.vf_output_info[i].format,
9031 IA_CSS_LEAVE_ERR_PRIVATE(err);
9032 kvfree(internal_pipe);
9033 internal_pipe = NULL;
9038 if (internal_pipe->config.acc_extension)
9040 err = ia_css_pipe_load_extension(internal_pipe,
9041 internal_pipe->config.acc_extension);
9043 IA_CSS_LEAVE_ERR_PRIVATE(err);
9044 kvfree(internal_pipe);
9048 /* set all info to zeroes first */
9049 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9051 /* all went well, return the pipe */
9052 *pipe = internal_pipe;
9053 IA_CSS_LEAVE_ERR_PRIVATE(0);
9058 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9059 struct ia_css_pipe_info *pipe_info) {
9060 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9061 "ia_css_pipe_get_info()\n");
9065 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9066 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9069 if (!pipe || !pipe->stream)
9071 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9072 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
9075 /* we succeeded return the info */
9076 *pipe_info = pipe->info;
9077 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9081 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info)
9086 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9087 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9096 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9098 enum ia_css_frame_format new_format) {
9101 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9105 IA_CSS_ERROR("pipe is not set");
9107 IA_CSS_LEAVE_ERR_PRIVATE(err);
9110 if (0 != pin_index && 1 != pin_index)
9112 IA_CSS_ERROR("pin index is not valid");
9114 IA_CSS_LEAVE_ERR_PRIVATE(err);
9117 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY)
9119 IA_CSS_ERROR("new format is not valid");
9121 IA_CSS_LEAVE_ERR_PRIVATE(err);
9125 err = ia_css_pipe_check_format(pipe, new_format);
9127 if (pin_index == 0) {
9128 pipe->output_info[0].format = new_format;
9130 pipe->vf_output_info[0].format = new_format;
9134 IA_CSS_LEAVE_ERR_PRIVATE(err);
9138 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9139 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9141 ia_css_stream_configure_rx(struct ia_css_stream *stream) {
9142 struct ia_css_input_port *config;
9146 config = &stream->config.source.port;
9147 /* AM: this code is not reliable, especially for 2400 */
9148 if (config->num_lanes == 1)
9149 stream->csi_rx_config.mode = MONO_1L_1L_0L;
9150 else if (config->num_lanes == 2)
9151 stream->csi_rx_config.mode = MONO_2L_1L_0L;
9152 else if (config->num_lanes == 3)
9153 stream->csi_rx_config.mode = MONO_3L_1L_0L;
9154 else if (config->num_lanes == 4)
9155 stream->csi_rx_config.mode = MONO_4L_1L_0L;
9156 else if (config->num_lanes != 0)
9159 if (config->port > MIPI_PORT2_ID)
9161 stream->csi_rx_config.port =
9162 ia_css_isys_port_to_mipi_port(config->port);
9163 stream->csi_rx_config.timeout = config->timeout;
9164 stream->csi_rx_config.initcount = 0;
9165 stream->csi_rx_config.synccount = 0x28282828;
9166 stream->csi_rx_config.rxcount = config->rxcount;
9167 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9168 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9171 /* not implemented yet, requires extension of the rx_cfg_t
9175 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9176 stream->reconfigure_css_rx = true;
9181 static struct ia_css_pipe *
9182 find_pipe(struct ia_css_pipe *pipes[],
9183 unsigned int num_pipes,
9184 enum ia_css_pipe_mode mode,
9189 for (i = 0; i < num_pipes; i++) {
9191 if (pipes[i]->config.mode != mode)
9193 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9201 ia_css_acc_stream_create(struct ia_css_stream *stream) {
9206 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9210 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
9214 for (i = 0; i < stream->num_pipes; i++)
9216 struct ia_css_pipe *pipe = stream->pipes[i];
9220 IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL);
9224 pipe->stream = stream;
9227 /* Map SP threads before doing anything. */
9228 err = map_sp_threads(stream, true);
9231 IA_CSS_LEAVE_ERR_PRIVATE(err);
9235 for (i = 0; i < stream->num_pipes; i++)
9237 struct ia_css_pipe *pipe = stream->pipes[i];
9240 ia_css_pipe_map_queue(pipe, true);
9243 err = create_host_pipeline_structure(stream);
9246 IA_CSS_LEAVE_ERR_PRIVATE(err);
9250 stream->started = false;
9252 IA_CSS_LEAVE_ERR_PRIVATE(0);
9258 metadata_info_init(const struct ia_css_metadata_config *mdc,
9259 struct ia_css_metadata_info *md) {
9260 /* Either both width and height should be set or neither */
9261 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9264 md->resolution = mdc->resolution;
9265 /* We round up the stride to a multiple of the width
9266 * of the port going to DDR, this is a HW requirements (DMA). */
9267 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9268 md->size = mdc->resolution.height * md->stride;
9273 static int check_pipe_resolutions(const struct ia_css_pipe *pipe)
9277 IA_CSS_ENTER_PRIVATE("");
9279 if (!pipe || !pipe->stream) {
9280 IA_CSS_ERROR("null arguments");
9285 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9286 pipe->config.input_effective_res.height) != 0) {
9287 IA_CSS_ERROR("effective resolution not supported");
9291 if (!ia_css_util_resolution_is_zero(
9292 pipe->stream->config.input_config.input_res)) {
9293 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9294 pipe->stream->config.input_config.input_res)) {
9295 IA_CSS_ERROR("effective resolution is larger than input resolution");
9300 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9301 IA_CSS_ERROR("output resolution must be even");
9305 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9306 IA_CSS_ERROR("VF resolution must be even");
9311 IA_CSS_LEAVE_ERR_PRIVATE(err);
9316 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9318 struct ia_css_pipe *pipes[],
9319 struct ia_css_stream **stream) {
9320 struct ia_css_pipe *curr_pipe;
9321 struct ia_css_stream *curr_stream = NULL;
9323 bool sensor_binning_changed;
9326 struct ia_css_metadata_info md_info;
9327 struct ia_css_resolution effective_res;
9328 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9329 bool aspect_ratio_crop_enabled = false;
9332 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9333 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9336 if (num_pipes == 0 ||
9341 IA_CSS_LEAVE_ERR(err);
9345 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9346 /* We don't support metadata for JPEG stream, since they both use str2mem */
9347 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9348 stream_config->metadata_config.resolution.height > 0)
9351 IA_CSS_LEAVE_ERR(err);
9356 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9357 if (stream_config->online && stream_config->pack_raw_pixels)
9359 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9361 IA_CSS_LEAVE_ERR(err);
9366 #if !defined(HAS_NO_INPUT_SYSTEM)
9367 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9369 /* check if mipi size specified */
9370 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9371 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9372 if (!stream_config->online)
9375 unsigned int port = (unsigned int)stream_config->source.port.port;
9377 if (port >= N_MIPI_PORT_ID) {
9379 IA_CSS_LEAVE_ERR(err);
9383 if (my_css.size_mem_words != 0) {
9384 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9385 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9386 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9388 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9389 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9390 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9392 IA_CSS_LEAVE_ERR(err);
9396 if (my_css.size_mem_words != 0) {
9397 my_css.num_mipi_frames[port] =
9398 2; /* Temp change: Default for backwards compatibility. */
9399 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9400 my_css.num_mipi_frames[port] =
9401 stream_config->mipi_buffer_config.nof_mipi_buffers;
9403 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9404 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9405 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9407 IA_CSS_LEAVE_ERR(err);
9413 /* Currently we only supported metadata up to a certain size. */
9414 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9417 IA_CSS_LEAVE_ERR(err);
9421 /* allocate the stream instance */
9422 curr_stream = kzalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9426 IA_CSS_LEAVE_ERR(err);
9429 /* default all to 0 */
9430 curr_stream->info.metadata_info = md_info;
9432 /* allocate pipes */
9433 curr_stream->num_pipes = num_pipes;
9434 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
9435 if (!curr_stream->pipes)
9437 curr_stream->num_pipes = 0;
9441 IA_CSS_LEAVE_ERR(err);
9445 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9446 for (i = 0; i < num_pipes; i++)
9447 curr_stream->pipes[i] = pipes[i];
9448 curr_stream->last_pipe = curr_stream->pipes[0];
9449 /* take over stream config */
9450 curr_stream->config = *stream_config;
9452 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9453 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9454 stream_config->online)
9455 curr_stream->config.online = false;
9458 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9459 if (curr_stream->config.online)
9461 curr_stream->config.source.port.num_lanes =
9462 stream_config->source.port.num_lanes;
9463 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9466 /* in case driver doesn't configure init number of raw buffers, configure it here */
9467 if (curr_stream->config.target_num_cont_raw_buf == 0)
9468 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9469 if (curr_stream->config.init_num_cont_raw_buf == 0)
9470 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9472 /* Enable locking & unlocking of buffers in RAW buffer pool */
9473 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9474 sh_css_sp_configure_enable_raw_pool_locking(
9475 curr_stream->config.lock_all);
9477 /* copy mode specific stuff */
9478 switch (curr_stream->config.mode)
9480 case IA_CSS_INPUT_MODE_SENSOR:
9481 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9482 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9483 ia_css_stream_configure_rx(curr_stream);
9486 case IA_CSS_INPUT_MODE_TPG:
9487 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9488 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9489 curr_stream->config.source.tpg.x_mask,
9490 curr_stream->config.source.tpg.y_mask,
9491 curr_stream->config.source.tpg.x_delta,
9492 curr_stream->config.source.tpg.y_delta,
9493 curr_stream->config.source.tpg.xy_mask);
9495 sh_css_sp_configure_tpg(
9496 curr_stream->config.source.tpg.x_mask,
9497 curr_stream->config.source.tpg.y_mask,
9498 curr_stream->config.source.tpg.x_delta,
9499 curr_stream->config.source.tpg.y_delta,
9500 curr_stream->config.source.tpg.xy_mask);
9503 case IA_CSS_INPUT_MODE_PRBS:
9504 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9505 IA_CSS_LOG("mode prbs");
9506 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9509 case IA_CSS_INPUT_MODE_MEMORY:
9510 IA_CSS_LOG("mode memory");
9511 curr_stream->reconfigure_css_rx = false;
9514 IA_CSS_LOG("mode sensor/default");
9517 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9518 err = aspect_ratio_crop_init(curr_stream,
9520 &aspect_ratio_crop_enabled);
9523 IA_CSS_LEAVE_ERR(err);
9527 for (i = 0; i < num_pipes; i++)
9529 struct ia_css_resolution effective_res;
9531 curr_pipe = pipes[i];
9532 /* set current stream */
9533 curr_pipe->stream = curr_stream;
9534 /* take over effective info */
9536 effective_res = curr_pipe->config.input_effective_res;
9537 if (effective_res.height == 0 || effective_res.width == 0) {
9538 effective_res = curr_pipe->stream->config.input_config.effective_res;
9540 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9541 /* The aspect ratio cropping is currently only
9542 * supported on the new input system. */
9543 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9544 struct ia_css_resolution crop_res;
9546 err = aspect_ratio_crop(curr_pipe, &crop_res);
9548 effective_res = crop_res;
9550 /* in case of error fallback to default
9551 * effective resolution from driver. */
9552 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9556 curr_pipe->config.input_effective_res = effective_res;
9558 IA_CSS_LOG("effective_res=%dx%d",
9559 effective_res.width,
9560 effective_res.height);
9564 for (i = 0; i < num_pipes; i++) {
9565 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9566 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9567 err = check_pipe_resolutions(pipes[i]);
9575 err = ia_css_stream_isp_parameters_init(curr_stream);
9578 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9580 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC)
9582 *stream = curr_stream;
9583 err = ia_css_acc_stream_create(curr_stream);
9586 /* sensor binning */
9589 sensor_binning_changed =
9590 sh_css_params_set_binning_factor(curr_stream,
9591 curr_stream->config.sensor_binning_factor);
9594 sensor_binning_changed = false;
9597 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9598 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9599 /* loop over pipes */
9600 IA_CSS_LOG("num_pipes=%d", num_pipes);
9601 curr_stream->cont_capt = false;
9602 /* Temporary hack: we give the preview pipe a reference to the capture
9603 * pipe in continuous capture mode. */
9604 if (curr_stream->config.continuous)
9606 /* Search for the preview pipe and create the copy pipe */
9607 struct ia_css_pipe *preview_pipe;
9608 struct ia_css_pipe *video_pipe;
9609 struct ia_css_pipe *acc_pipe;
9610 struct ia_css_pipe *capture_pipe = NULL;
9611 struct ia_css_pipe *copy_pipe = NULL;
9613 if (num_pipes >= 2) {
9614 curr_stream->cont_capt = true;
9615 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9618 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9621 /* Create copy pipe here, since it may not be exposed to the driver */
9622 preview_pipe = find_pipe(pipes, num_pipes,
9623 IA_CSS_PIPE_MODE_PREVIEW, false);
9624 video_pipe = find_pipe(pipes, num_pipes,
9625 IA_CSS_PIPE_MODE_VIDEO, false);
9626 acc_pipe = find_pipe(pipes, num_pipes,
9627 IA_CSS_PIPE_MODE_ACC, false);
9628 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9629 curr_stream->cont_capt =
9630 false; /* preview + QoS case will not need cont_capt switch */
9631 if (curr_stream->cont_capt == true) {
9632 capture_pipe = find_pipe(pipes, num_pipes,
9633 IA_CSS_PIPE_MODE_CAPTURE, false);
9634 if (!capture_pipe) {
9639 /* We do not support preview and video pipe at the same time */
9640 if (preview_pipe && video_pipe) {
9645 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9646 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9649 ia_css_pipe_config_defaults(©_pipe->config);
9650 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9651 copy_pipe->stream = curr_stream;
9653 if (preview_pipe && (curr_stream->cont_capt == true)) {
9654 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9656 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9657 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9660 ia_css_pipe_config_defaults(©_pipe->config);
9661 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9662 copy_pipe->stream = curr_stream;
9664 if (video_pipe && (curr_stream->cont_capt == true)) {
9665 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9667 if (preview_pipe && acc_pipe) {
9668 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9671 for (i = 0; i < num_pipes; i++)
9673 curr_pipe = pipes[i];
9674 /* set current stream */
9675 curr_pipe->stream = curr_stream;
9678 /* take over effective info */
9680 effective_res = curr_pipe->config.input_effective_res;
9681 err = ia_css_util_check_res(
9682 effective_res.width,
9683 effective_res.height);
9687 /* sensor binning per pipe */
9688 if (sensor_binning_changed)
9689 sh_css_pipe_free_shading_table(curr_pipe);
9692 /* now pipes have been configured, info should be available */
9693 for (i = 0; i < num_pipes; i++)
9695 struct ia_css_pipe_info *pipe_info = NULL;
9697 curr_pipe = pipes[i];
9699 err = sh_css_pipe_load_binaries(curr_pipe);
9703 /* handle each pipe */
9704 pipe_info = &curr_pipe->info;
9705 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9706 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9707 &pipe_info->output_info[j], j);
9713 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9717 err = sh_css_pipe_get_shading_info(curr_pipe,
9718 &pipe_info->shading_info, NULL);
9720 err = sh_css_pipe_get_shading_info(curr_pipe,
9721 &pipe_info->shading_info, &curr_pipe->config);
9725 err = sh_css_pipe_get_grid_info(curr_pipe,
9726 &pipe_info->grid_info);
9729 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9730 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9731 &pipe_info->vf_output_info[j], j);
9737 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9740 curr_stream->started = false;
9742 /* Map SP threads before doing anything. */
9743 err = map_sp_threads(curr_stream, true);
9746 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9750 for (i = 0; i < num_pipes; i++)
9752 curr_pipe = pipes[i];
9753 ia_css_pipe_map_queue(curr_pipe, true);
9756 /* Create host side pipeline objects without stages */
9757 err = create_host_pipeline_structure(curr_stream);
9760 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9764 /* assign curr_stream */
9765 *stream = curr_stream;
9769 /* working mode: enter into the seed list */
9770 if (my_css_save.mode == sh_css_mode_working) {
9771 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9772 if (!my_css_save.stream_seeds[i].stream) {
9773 IA_CSS_LOG("entered stream into loc=%d", i);
9774 my_css_save.stream_seeds[i].orig_stream = stream;
9775 my_css_save.stream_seeds[i].stream = curr_stream;
9776 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9777 my_css_save.stream_seeds[i].stream_config = *stream_config;
9778 for (j = 0; j < num_pipes; j++) {
9779 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9780 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9781 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9787 ia_css_stream_destroy(curr_stream);
9790 ia_css_stream_destroy(curr_stream);
9792 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9797 ia_css_stream_destroy(struct ia_css_stream *stream) {
9801 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9805 IA_CSS_LEAVE_ERR_PRIVATE(err);
9809 ia_css_stream_isp_parameters_uninit(stream);
9811 if ((stream->last_pipe) &&
9812 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num))
9814 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9817 for (i = 0; i < stream->num_pipes; i++) {
9818 struct ia_css_pipe *entry = stream->pipes[i];
9819 unsigned int sp_thread_id;
9820 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9824 /* get the SP thread id */
9825 if (ia_css_pipeline_get_sp_thread_id(
9826 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9828 /* get the target input terminal */
9829 sp_pipeline_input_terminal =
9830 &sh_css_sp_group.pipe_io[sp_thread_id].input;
9832 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9833 ia_css_isys_stream_h isys_stream =
9834 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9835 if (stream->config.isys_config[i].valid && isys_stream->valid)
9836 ia_css_isys_stream_destroy(isys_stream);
9840 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9842 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG;
9843 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS;
9847 for (i = 0; i < stream->num_pipes; i++) {
9848 struct ia_css_pipe *entry = stream->pipes[i];
9849 /* free any mipi frames that are remaining:
9850 * some test stream create-destroy cycles do not generate output frames
9851 * and the mipi buffer is not freed in the deque function
9854 free_mipi_frames(entry);
9857 stream_unregister_with_csi_rx(stream);
9860 for (i = 0; i < stream->num_pipes; i++) {
9861 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9864 ia_css_pipe_map_queue(curr_pipe, false);
9867 err = map_sp_threads(stream, false);
9869 IA_CSS_LEAVE_ERR_PRIVATE(err);
9874 /* remove references from pipes to stream */
9875 for (i = 0; i < stream->num_pipes; i++)
9877 struct ia_css_pipe *entry = stream->pipes[i];
9881 /* clear reference to stream */
9882 entry->stream = NULL;
9883 /* check internal copy pipe */
9884 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9885 entry->pipe_settings.preview.copy_pipe) {
9886 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9887 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9889 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9890 entry->pipe_settings.video.copy_pipe) {
9891 IA_CSS_LOG("clearing stream on internal video copy pipe");
9892 entry->pipe_settings.video.copy_pipe->stream = NULL;
9894 err = sh_css_pipe_unload_binaries(entry);
9897 /* free associated memory of stream struct */
9898 kfree(stream->pipes);
9899 stream->pipes = NULL;
9900 stream->num_pipes = 0;
9902 /* working mode: take out of the seed list */
9903 if (my_css_save.mode == sh_css_mode_working) {
9904 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9905 if (my_css_save.stream_seeds[i].stream == stream)
9907 IA_CSS_LOG("took out stream %d", i);
9908 my_css_save.stream_seeds[i].stream = NULL;
9915 IA_CSS_LEAVE_ERR(err);
9921 ia_css_stream_get_info(const struct ia_css_stream *stream,
9922 struct ia_css_stream_info *stream_info) {
9923 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9925 assert(stream_info);
9927 *stream_info = stream->info;
9932 * Rebuild a stream, including allocating structs, setting configuration and
9933 * building the required pipes.
9934 * The data is taken from the css_save struct updated upon stream creation.
9935 * The stream handle is used to identify the correct entry in the css_save struct
9938 ia_css_stream_load(struct ia_css_stream *stream) {
9944 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
9945 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9947 if (my_css_save.stream_seeds[i].stream == stream) {
9950 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9951 if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
9952 &my_css_save.stream_seeds[i].pipes[j])) != 0) {
9956 for (k = 0; k < j; k++)
9957 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9962 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
9963 my_css_save.stream_seeds[i].num_pipes,
9964 my_css_save.stream_seeds[i].pipes,
9965 &my_css_save.stream_seeds[i].stream);
9967 ia_css_stream_destroy(stream);
9968 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9969 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9975 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
9978 /* TODO remove function - DEPRECATED */
9985 ia_css_stream_start(struct ia_css_stream *stream) {
9988 IA_CSS_ENTER("stream = %p", stream);
9989 if ((!stream) || (!stream->last_pipe))
9991 IA_CSS_LEAVE_ERR(-EINVAL);
9994 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
9996 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
9998 /* Create host side pipeline. */
9999 err = create_host_pipeline(stream);
10002 IA_CSS_LEAVE_ERR(err);
10006 #if !defined(HAS_NO_INPUT_SYSTEM)
10007 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
10008 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
10009 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
10010 stream_register_with_csi_rx(stream);
10014 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10015 /* Initialize mipi size checks */
10016 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10019 unsigned int port = (unsigned int)(stream->config.source.port.port);
10021 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10022 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
10023 sh_css_get_mipi_sizes_for_check(port, idx);
10028 #if !defined(HAS_NO_INPUT_SYSTEM)
10029 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)
10031 err = sh_css_config_input_network(stream);
10035 #endif /* !HAS_NO_INPUT_SYSTEM */
10037 err = sh_css_pipe_start(stream);
10038 IA_CSS_LEAVE_ERR(err);
10043 ia_css_stream_stop(struct ia_css_stream *stream) {
10046 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10048 assert(stream->last_pipe);
10049 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10050 stream->last_pipe->mode);
10052 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10053 /* De-initialize mipi size checks */
10054 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10057 unsigned int port = (unsigned int)(stream->config.source.port.port);
10059 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10060 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10066 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10068 err = sh_css_pipes_stop(stream);
10074 /* Ideally, unmapping should happen after pipeline_stop, but current
10075 * semantics do not allow that. */
10076 /* err = map_sp_threads(stream, false); */
10082 ia_css_stream_has_stopped(struct ia_css_stream *stream) {
10088 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10090 stopped = sh_css_pipes_have_stopped(stream);
10098 * Destroy the stream and all the pipes related to it.
10099 * The stream handle is used to identify the correct entry in the css_save struct
10102 ia_css_stream_unload(struct ia_css_stream *stream) {
10106 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
10109 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
10110 if (my_css_save.stream_seeds[i].stream == stream)
10114 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10115 "ia_css_stream_unload(): unloading %d (%p)\n", i,
10116 my_css_save.stream_seeds[i].stream);
10117 ia_css_stream_destroy(stream);
10118 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
10119 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10120 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10121 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
10122 my_css_save.stream_seeds[i].stream);
10125 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
10130 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
10131 enum ia_css_pipe_id *pipe_id) {
10132 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10134 *pipe_id = pipe->mode;
10136 *pipe_id = IA_CSS_PIPE_ID_COPY;
10141 enum atomisp_input_format
10142 ia_css_stream_get_format(const struct ia_css_stream *stream) {
10143 return stream->config.input_config.format;
10147 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) {
10148 return (stream->config.pixels_per_clock == 2);
10151 struct ia_css_binary *
10152 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
10154 struct ia_css_pipe *pipe;
10158 pipe = stream->pipes[0];
10160 if (stream->num_pipes == 2) {
10161 assert(stream->pipes[1]);
10162 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10163 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10164 pipe = stream->pipes[1];
10167 return ia_css_pipe_get_shading_correction_binary(pipe);
10170 struct ia_css_binary *
10171 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
10173 struct ia_css_pipe *video_pipe = NULL;
10175 /* First we find the video pipe */
10176 for (i = 0; i < stream->num_pipes; i++) {
10177 struct ia_css_pipe *pipe = stream->pipes[i];
10179 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10185 return &video_pipe->pipe_settings.video.video_binary;
10189 struct ia_css_binary *
10190 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
10191 struct ia_css_pipe *pipe;
10192 struct ia_css_binary *s3a_binary = NULL;
10196 pipe = stream->pipes[0];
10198 if (stream->num_pipes == 2) {
10199 assert(stream->pipes[1]);
10200 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10201 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10202 pipe = stream->pipes[1];
10205 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10211 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
10212 unsigned int output_padded_width) {
10213 struct ia_css_pipe *pipe;
10217 pipe = stream->last_pipe;
10221 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10222 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10223 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10228 static struct ia_css_binary *
10229 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
10230 struct ia_css_binary *binary = NULL;
10234 switch (pipe->config.mode) {
10235 case IA_CSS_PIPE_MODE_PREVIEW:
10236 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10238 case IA_CSS_PIPE_MODE_VIDEO:
10239 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10241 case IA_CSS_PIPE_MODE_CAPTURE:
10242 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10245 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10246 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10247 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10251 } else if (pipe->config.default_capture_config.mode ==
10252 IA_CSS_CAPTURE_MODE_BAYER)
10253 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10254 else if (pipe->config.default_capture_config.mode ==
10255 IA_CSS_CAPTURE_MODE_ADVANCED ||
10256 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10257 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10258 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10259 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10260 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10267 if (binary && binary->info->sp.enable.sc)
10273 static struct ia_css_binary *
10274 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
10275 struct ia_css_binary *binary = NULL;
10279 switch (pipe->config.mode) {
10280 case IA_CSS_PIPE_MODE_PREVIEW:
10281 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10283 case IA_CSS_PIPE_MODE_VIDEO:
10284 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10286 case IA_CSS_PIPE_MODE_CAPTURE:
10287 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10290 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10291 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10292 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10296 } else if (pipe->config.default_capture_config.mode ==
10297 IA_CSS_CAPTURE_MODE_BAYER)
10298 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10299 else if (pipe->config.default_capture_config.mode ==
10300 IA_CSS_CAPTURE_MODE_ADVANCED ||
10301 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10302 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10303 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10304 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10305 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10314 if (binary && !binary->info->sp.enable.s3a)
10320 static struct ia_css_binary *
10321 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
10322 struct ia_css_binary *binary = NULL;
10326 switch (pipe->config.mode) {
10327 case IA_CSS_PIPE_MODE_VIDEO:
10328 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10334 if (binary && !binary->info->sp.enable.dis)
10340 struct ia_css_pipeline *
10341 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) {
10344 return (struct ia_css_pipeline *)&pipe->pipeline;
10348 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
10351 /* KW was not sure this function was not returning a value
10352 that was out of range; so added an assert, and, for the
10353 case when asserts are not enabled, clip to the largest
10354 value; pipe_num is unsigned so the value cannot be too small
10356 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10358 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10359 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10361 return pipe->pipe_num;
10365 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
10368 return (unsigned int)pipe->config.isp_pipe_version;
10371 #define SP_START_TIMEOUT_US 30000000
10374 ia_css_start_sp(void) {
10375 unsigned long timeout;
10379 sh_css_sp_start_isp();
10381 /* waiting for the SP is completely started */
10382 timeout = SP_START_TIMEOUT_US;
10383 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout)
10390 IA_CSS_ERROR("timeout during SP initialization");
10394 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10395 /* TODO: Fix this. */
10397 sh_css_init_host_sp_control_vars();
10399 /* buffers should be initialized only when sp is started */
10400 /* AM: At the moment it will be done only when there is no stream active. */
10402 sh_css_setup_queues();
10403 ia_css_bufq_dump_queue_info();
10405 IA_CSS_LEAVE_ERR(err);
10410 * Time to wait SP for termincate. Only condition when this can happen
10411 * is a fatal hw failure, but we must be able to detect this and emit
10412 * a proper error trace.
10414 #define SP_SHUTDOWN_TIMEOUT_US 200000
10417 ia_css_stop_sp(void) {
10418 unsigned long timeout;
10421 IA_CSS_ENTER("void");
10423 if (!sh_css_sp_is_running())
10426 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10428 /* Return an error - stop SP should not have been called by driver */
10432 /* For now, stop whole SP */
10434 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10436 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate))
10438 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10439 ia_css_debug_dump_sp_sw_debug_info();
10440 ia_css_debug_dump_debug_info(NULL);
10444 sh_css_sp_set_sp_running(false);
10446 timeout = SP_SHUTDOWN_TIMEOUT_US;
10447 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout)
10452 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10453 IA_CSS_WARNING("SP has not terminated (SW)");
10457 IA_CSS_WARNING("SP is not idle");
10458 ia_css_debug_dump_sp_sw_debug_info();
10460 timeout = SP_SHUTDOWN_TIMEOUT_US;
10461 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout)
10468 IA_CSS_WARNING("ISP is not idle");
10469 ia_css_debug_dump_sp_sw_debug_info();
10472 sh_css_hmm_buffer_record_uninit();
10474 /* clear pending param sets from refcount */
10475 sh_css_param_clear_param_sets();
10477 IA_CSS_LEAVE_ERR(err);
10482 ia_css_update_continuous_frames(struct ia_css_stream *stream) {
10483 struct ia_css_pipe *pipe;
10486 ia_css_debug_dtrace(
10487 IA_CSS_DEBUG_TRACE,
10488 "sh_css_update_continuous_frames() enter:\n");
10492 ia_css_debug_dtrace(
10493 IA_CSS_DEBUG_TRACE,
10494 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10498 pipe = stream->continuous_pipe;
10500 for (i = stream->config.init_num_cont_raw_buf;
10501 i < stream->config.target_num_cont_raw_buf; i++)
10503 sh_css_update_host2sp_offline_frame(i,
10504 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10506 sh_css_update_host2sp_cont_num_raw_frames
10507 (stream->config.target_num_cont_raw_buf, true);
10508 ia_css_debug_dtrace(
10509 IA_CSS_DEBUG_TRACE,
10510 "sh_css_update_continuous_frames() leave: return_void\n");
10515 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map)
10517 unsigned int thread_id;
10518 enum ia_css_pipe_id pipe_id;
10519 unsigned int pipe_num;
10520 bool need_input_queue;
10525 pipe_id = pipe->mode;
10526 pipe_num = pipe->pipe_num;
10528 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10530 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10531 need_input_queue = true;
10533 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10536 /* map required buffer queues to resources */
10537 /* TODO: to be improved */
10538 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10539 if (need_input_queue)
10540 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10541 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10542 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10543 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10544 #if defined SH_CSS_ENABLE_METADATA
10545 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10547 if (pipe->pipe_settings.preview.preview_binary.info &&
10548 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10549 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10550 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10553 if (need_input_queue)
10554 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10555 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10556 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10557 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10558 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10559 #if defined SH_CSS_ENABLE_METADATA
10560 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10562 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10563 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10564 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10565 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10566 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10570 } else if (pipe->config.default_capture_config.mode ==
10571 IA_CSS_CAPTURE_MODE_ADVANCED ||
10572 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10573 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10574 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10575 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10576 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10578 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10579 if (need_input_queue)
10580 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10581 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10582 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10583 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10584 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10585 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10586 #if defined SH_CSS_ENABLE_METADATA
10587 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10589 if (pipe->pipe_settings.video.video_binary.info &&
10590 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10591 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10592 if (pipe->pipe_settings.video.video_binary.info &&
10593 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10595 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10596 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10597 if (need_input_queue)
10598 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10599 if (!pipe->stream->config.continuous)
10600 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10601 #if defined SH_CSS_ENABLE_METADATA
10602 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10604 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10605 if (need_input_queue)
10606 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10607 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10608 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10609 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10610 #if defined SH_CSS_ENABLE_METADATA
10611 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10613 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10616 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10617 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10618 if (pipe->enable_viewfinder[idx])
10619 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10621 if (need_input_queue)
10622 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10623 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10624 #if defined SH_CSS_ENABLE_METADATA
10625 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10631 #if CONFIG_ON_FRAME_ENQUEUE()
10632 static int set_config_on_frame_enqueue(struct ia_css_frame_info
10633 *info, struct frame_data_wrapper *frame) {
10634 frame->config_on_frame_enqueue.padded_width = 0;
10636 /* currently we support configuration on frame enqueue only on YUV formats */
10637 /* on other formats the padded_width is zeroed for no configuration override */
10638 switch (info->format) {
10639 case IA_CSS_FRAME_FORMAT_YUV420:
10640 case IA_CSS_FRAME_FORMAT_NV12:
10641 if (info->padded_width > info->res.width) {
10642 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10643 } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) {
10646 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10657 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
10662 /* Only continuous streams have a tagger to which we can send the
10663 * unlock message. */
10664 if (!stream || !stream->config.continuous)
10666 IA_CSS_ERROR("invalid stream pointer");
10670 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10671 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID)
10673 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
10677 /* Send the event. Since we verified that the exp_id is valid,
10678 * we can safely assign it to an 8-bit argument here. */
10679 ret = ia_css_bufq_enqueue_psys_event(
10680 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10682 IA_CSS_LEAVE_ERR(ret);
10686 /* @brief Set the state (Enable or Disable) of the Extension stage in the
10690 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10692 unsigned int thread_id;
10693 struct ia_css_pipeline_stage *stage;
10698 /* Parameter Check */
10699 if (!pipe || !pipe->stream)
10701 IA_CSS_ERROR("Invalid Pipe.");
10703 } else if (!(pipe->config.acc_extension))
10705 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10707 } else if (!sh_css_sp_is_running())
10709 IA_CSS_ERROR("Leaving: queue unavailable.");
10713 /* Query the threadid and stage_num for the Extension firmware*/
10714 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10715 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10717 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10718 err = ia_css_bufq_enqueue_psys_event(
10719 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10720 (uint8_t)thread_id,
10721 (uint8_t)stage->stage_num,
10725 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10727 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10731 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10735 /* @brief Get the state (Enable or Disable) of the Extension stage in the
10739 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10741 struct ia_css_pipeline_stage *stage;
10742 unsigned int thread_id;
10747 /* Parameter Check */
10748 if (!pipe || !pipe->stream)
10750 IA_CSS_ERROR("Invalid Pipe.");
10752 } else if (!(pipe->config.acc_extension))
10754 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10756 } else if (!sh_css_sp_is_running())
10758 IA_CSS_ERROR("Leaving: queue unavailable.");
10762 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10763 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10764 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10767 /* Get the Extension State */
10768 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10769 stage->stage_num)) ? true : false;
10772 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10778 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
10780 struct ia_css_isp_param_css_segments *css_seg,
10781 struct ia_css_isp_param_isp_segments *isp_seg) {
10782 unsigned int HIVE_ADDR_sp_group;
10783 static struct sh_css_sp_group sp_group;
10784 static struct sh_css_sp_stage sp_stage;
10785 static struct sh_css_isp_stage isp_stage;
10786 const struct ia_css_fw_info *fw;
10787 unsigned int thread_id;
10788 struct ia_css_pipeline_stage *stage;
10791 enum ia_css_isp_memories mem;
10796 fw = &sh_css_sp_fw;
10798 /* Parameter Check */
10799 if (!pipe || !pipe->stream)
10801 IA_CSS_ERROR("Invalid Pipe.");
10803 } else if (!(pipe->config.acc_extension))
10805 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10807 } else if (!sh_css_sp_is_running())
10809 IA_CSS_ERROR("Leaving: queue unavailable.");
10813 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10814 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10815 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10817 /* Get the Extension State */
10818 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10819 stage->stage_num)) ? true : false;
10820 /* Update mapped arg only when extension stage is not enabled */
10822 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10825 stage_num = stage->stage_num;
10827 HIVE_ADDR_sp_group = fw->info.sp.group;
10828 sp_dmem_load(SP0_ID,
10829 (unsigned int)sp_address_of(sp_group),
10830 &sp_group, sizeof(struct sh_css_sp_group));
10831 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10832 &sp_stage, sizeof(struct sh_css_sp_stage));
10834 hmm_load(sp_stage.isp_stage_addr,
10835 &isp_stage, sizeof(struct sh_css_isp_stage));
10837 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10838 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10839 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10840 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10841 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10842 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address
10844 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10845 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size
10847 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10850 hmm_store(sp_stage.isp_stage_addr,
10851 &isp_stage, sizeof(struct sh_css_isp_stage));
10855 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10859 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10861 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10862 struct ia_css_pipe *pipes[],
10863 bool *do_crop_status) {
10866 struct ia_css_pipe *curr_pipe;
10869 if ((!curr_stream) ||
10870 (curr_stream->num_pipes == 0) ||
10875 IA_CSS_LEAVE_ERR(err);
10879 for (i = 0; i < curr_stream->num_pipes; i++)
10881 curr_pipe = pipes[i];
10882 pipe_mask |= (1 << curr_pipe->config.mode);
10886 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10887 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10888 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10889 curr_stream->config.continuous);
10894 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
10895 bool status = false;
10897 if ((curr_pipe) && enabled) {
10898 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10899 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10900 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10908 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10909 struct ia_css_resolution *effective_res) {
10911 struct ia_css_resolution crop_res;
10912 struct ia_css_resolution *in_res = NULL;
10913 struct ia_css_resolution *out_res = NULL;
10914 bool use_bds_output_info = false;
10915 bool use_vf_pp_in_res = false;
10916 bool use_capt_pp_in_res = false;
10918 if ((!curr_pipe) ||
10922 IA_CSS_LEAVE_ERR(err);
10926 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10927 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10928 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE))
10931 IA_CSS_LEAVE_ERR(err);
10935 use_bds_output_info =
10936 ((curr_pipe->bds_output_info.res.width != 0) &&
10937 (curr_pipe->bds_output_info.res.height != 0));
10940 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10941 (curr_pipe->config.vf_pp_in_res.height != 0));
10943 use_capt_pp_in_res =
10944 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10945 (curr_pipe->config.capt_pp_in_res.height != 0));
10947 in_res = &curr_pipe->stream->config.input_config.effective_res;
10948 out_res = &curr_pipe->output_info[0].res;
10950 switch (curr_pipe->config.mode)
10952 case IA_CSS_PIPE_MODE_PREVIEW:
10953 if (use_bds_output_info)
10954 out_res = &curr_pipe->bds_output_info.res;
10955 else if (use_vf_pp_in_res)
10956 out_res = &curr_pipe->config.vf_pp_in_res;
10958 case IA_CSS_PIPE_MODE_VIDEO:
10959 if (use_bds_output_info)
10960 out_res = &curr_pipe->bds_output_info.res;
10962 case IA_CSS_PIPE_MODE_CAPTURE:
10963 if (use_capt_pp_in_res)
10964 out_res = &curr_pipe->config.capt_pp_in_res;
10966 case IA_CSS_PIPE_MODE_ACC:
10967 case IA_CSS_PIPE_MODE_COPY:
10968 case IA_CSS_PIPE_MODE_YUVPP:
10970 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10971 curr_pipe->config.mode);
10976 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10979 *effective_res = crop_res;
10982 /* in case of error fallback to default
10983 * effective resolution from driver. */
10984 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10991 sh_css_hmm_buffer_record_init(void) {
10994 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
10995 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
10999 sh_css_hmm_buffer_record_uninit(void) {
11001 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11003 buffer_record = &hmm_buffer_record[0];
11004 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11005 if (buffer_record->in_use) {
11006 if (buffer_record->h_vbuf)
11007 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
11008 sh_css_hmm_buffer_record_reset(buffer_record);
11015 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
11016 assert(buffer_record);
11017 buffer_record->in_use = false;
11018 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11019 buffer_record->h_vbuf = NULL;
11020 buffer_record->kernel_ptr = 0;
11023 static struct sh_css_hmm_buffer_record
11024 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11025 enum ia_css_buffer_type type,
11026 hrt_address kernel_ptr) {
11028 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11029 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11032 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
11033 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11034 assert(kernel_ptr != 0);
11036 buffer_record = &hmm_buffer_record[0];
11037 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11038 if (!buffer_record->in_use) {
11039 buffer_record->in_use = true;
11040 buffer_record->type = type;
11041 buffer_record->h_vbuf = h_vbuf;
11042 buffer_record->kernel_ptr = kernel_ptr;
11043 out_buffer_record = buffer_record;
11049 return out_buffer_record;
11052 static struct sh_css_hmm_buffer_record
11053 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
11054 enum ia_css_buffer_type type) {
11056 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11057 bool found_record = false;
11059 buffer_record = &hmm_buffer_record[0];
11060 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11061 if ((buffer_record->in_use) &&
11062 (buffer_record->type == type) &&
11063 (buffer_record->h_vbuf) &&
11064 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11065 found_record = true;
11072 return buffer_record;