2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include <linux/slab.h>
18 #include <linux/vmalloc.h>
23 #include "sh_css_hrt.h" /* only for file 2 MIPI */
24 #include "ia_css_buffer.h"
25 #include "ia_css_binary.h"
26 #include "sh_css_internal.h"
27 #include "sh_css_mipi.h"
28 #include "sh_css_sp.h" /* sh_css_sp_group */
29 #if !defined(HAS_NO_INPUT_SYSTEM)
30 #include "ia_css_isys.h"
32 #include "ia_css_frame.h"
33 #include "sh_css_defs.h"
34 #include "sh_css_firmware.h"
35 #include "sh_css_params.h"
36 #include "sh_css_params_internal.h"
37 #include "sh_css_param_shading.h"
38 #include "ia_css_refcount.h"
39 #include "ia_css_rmgr.h"
40 #include "ia_css_debug.h"
41 #include "ia_css_debug_pipe.h"
42 #include "ia_css_device_access.h"
43 #include "device_access.h"
44 #include "sh_css_legacy.h"
45 #include "ia_css_pipeline.h"
46 #include "ia_css_stream.h"
47 #include "sh_css_stream_format.h"
48 #include "ia_css_pipe.h"
49 #include "ia_css_util.h"
50 #include "ia_css_pipe_util.h"
51 #include "ia_css_pipe_binarydesc.h"
52 #include "ia_css_pipe_stagedesc.h"
53 #ifdef USE_INPUT_SYSTEM_VERSION_2
54 #include "ia_css_isys.h"
58 #include "assert_support.h"
59 #include "math_support.h"
60 #include "sw_event_global.h" /* Event IDs.*/
61 #if !defined(HAS_NO_INPUT_FORMATTER)
62 #include "ia_css_ifmtr.h"
64 #if !defined(HAS_NO_INPUT_SYSTEM)
65 #include "input_system.h"
67 #include "mmu_device.h" /* mmu_set_page_table_base_index(), ... */
68 #include "ia_css_mmu_private.h" /* sh_css_mmu_set_page_table_base_index() */
69 #include "gdc_device.h" /* HRT_GDC_N */
70 #include "dma.h" /* dma_set_max_burst_size() */
71 #include "irq.h" /* virq */
72 #include "sp.h" /* cnd_sp_irq_enable() */
73 #include "isp.h" /* cnd_isp_irq_enable, ISP_VEC_NELEMS */
74 #include "gp_device.h" /* gp_device_reg_store() */
75 #define __INLINE_GPIO__
77 #include "timed_ctrl.h"
78 #include "platform_support.h" /* hrt_sleep(), inline */
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;
185 static enum ia_css_err
186 allocate_delay_frames(struct ia_css_pipe *pipe);
188 static enum ia_css_err
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 * - IA_CSS_SUCCESS, 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
209 static enum ia_css_err
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);
228 static enum ia_css_err
229 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
230 enum ia_css_frame_format format);
233 static enum ia_css_err
234 check_pipe_resolutions(const struct ia_css_pipe *pipe);
236 static enum ia_css_err
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 enum ia_css_err 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 enum ia_css_err 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);
273 static enum ia_css_err
274 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe);
277 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
278 struct ia_css_pipe *pipe,
279 struct ia_css_frame_info *info,
282 static enum ia_css_err
283 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
284 struct ia_css_frame_info *info,
287 static enum ia_css_err
288 capture_start(struct ia_css_pipe *pipe);
290 static enum ia_css_err
291 video_start(struct ia_css_pipe *pipe);
293 static enum ia_css_err
294 preview_start(struct ia_css_pipe *pipe);
296 static enum ia_css_err
297 yuvpp_start(struct ia_css_pipe *pipe);
299 static bool copy_on_sp(struct ia_css_pipe *pipe);
301 static enum ia_css_err
302 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
303 struct ia_css_frame *vf_frame, unsigned int idx);
305 static enum ia_css_err
306 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
307 struct ia_css_frame *frame, enum ia_css_frame_format format);
309 static enum ia_css_err
310 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
311 struct ia_css_frame *out_frame, unsigned int idx);
313 static enum ia_css_err
314 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
317 static enum ia_css_err
318 alloc_continuous_frames(
319 struct ia_css_pipe *pipe, bool init_time);
322 pipe_global_init(void);
324 static enum ia_css_err
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);
331 static enum ia_css_err
332 create_host_pipeline_structure(struct ia_css_stream *stream);
334 static enum ia_css_err
335 create_host_pipeline(struct ia_css_stream *stream);
337 static enum ia_css_err
338 create_host_preview_pipeline(struct ia_css_pipe *pipe);
340 static enum ia_css_err
341 create_host_video_pipeline(struct ia_css_pipe *pipe);
343 static enum ia_css_err
344 create_host_copy_pipeline(struct ia_css_pipe *pipe,
345 unsigned int max_input_width,
346 struct ia_css_frame *out_frame);
348 static enum ia_css_err
349 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe);
351 static enum ia_css_err
352 create_host_capture_pipeline(struct ia_css_pipe *pipe);
354 static enum ia_css_err
355 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe);
357 static enum ia_css_err
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 enum ia_css_err 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);
407 static enum ia_css_err
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);
415 static enum ia_css_err
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.
462 static enum ia_css_err
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);
518 return IA_CSS_ERR_INVALID_ARGUMENTS;
519 return IA_CSS_SUCCESS;
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)
537 static enum ia_css_err
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;
542 enum ia_css_err err = IA_CSS_SUCCESS;
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,
557 if (err != IA_CSS_SUCCESS)
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,
568 if (err != IA_CSS_SUCCESS)
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,
586 if (!atomisp_hw_is_isp2401) {
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");
595 return IA_CSS_SUCCESS;
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,
890 if (err != IA_CSS_SUCCESS)
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,
903 if (err != IA_CSS_SUCCESS)
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,
913 if (err != IA_CSS_SUCCESS)
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;
1054 static enum ia_css_err
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;
1099 return IA_CSS_ERR_INTERNAL_ERROR;
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);
1117 return IA_CSS_ERR_INTERNAL_ERROR;
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));
1144 return IA_CSS_ERR_INTERNAL_ERROR;
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],
1154 return IA_CSS_ERR_INTERNAL_ERROR;
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]);
1164 return IA_CSS_ERR_INTERNAL_ERROR;
1168 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
1169 "sh_css_config_input_network() leave:\n");
1171 return IA_CSS_SUCCESS;
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 enum ia_css_err stream_csi_rx_helper(
1230 struct ia_css_stream *stream,
1231 enum ia_css_err (*func)(enum mipi_port_id, uint32_t))
1233 enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR;
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 == IA_CSS_SUCCESS) &&
1263 (stream_id < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH));
1269 static inline enum ia_css_err 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 enum ia_css_err 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 */
1408 static enum ia_css_err
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))
1416 return IA_CSS_ERR_INVALID_ARGUMENTS;
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)
1424 return IA_CSS_ERR_INTERNAL_ERROR;
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;
1436 return IA_CSS_SUCCESS;
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 */
1473 if (!atomisp_hw_is_isp2401) {
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 (virq_id_t)(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 (virq_id_t)(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 (virq_id_t)(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) {
1631 enum ia_css_err err;
1634 return IA_CSS_ERR_INVALID_ARGUMENTS;
1636 return IA_CSS_ERR_INVALID_ARGUMENTS;
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);
1649 if (err == IA_CSS_SUCCESS)
1651 err = ia_css_binary_init_infos();
1652 if (err == IA_CSS_SUCCESS)
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) {
1665 enum ia_css_err err;
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)
1708 return IA_CSS_ERR_INVALID_ARGUMENTS;
1710 return IA_CSS_ERR_INVALID_ARGUMENTS;
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();
1738 if (err != IA_CSS_SUCCESS)
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);
1775 if (err != IA_CSS_SUCCESS)
1777 IA_CSS_LEAVE_ERR(err);
1780 err = sh_css_params_init();
1781 if (err != IA_CSS_SUCCESS)
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);
1790 if (err != IA_CSS_SUCCESS) {
1791 IA_CSS_LEAVE_ERR(err);
1794 err = ia_css_binary_init_infos();
1795 if (err != IA_CSS_SUCCESS) {
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))
1805 return IA_CSS_ERR_INTERNAL_ERROR;
1807 err = ia_css_spctrl_load_fw(SP0_ID, &spctrl_cfg);
1808 if (err != IA_CSS_SUCCESS)
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(IA_CSS_ERR_SYSTEM_NOT_IDLE);
1826 return IA_CSS_ERR_SYSTEM_NOT_IDLE;
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)
1844 dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN,
1845 ISP_DMA_MAX_BURST_LENGTH);
1847 if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR)
1848 err = IA_CSS_ERR_INVALID_ARGUMENTS;
1851 sh_css_params_map_and_store_default_gdc_lut();
1853 IA_CSS_LEAVE_ERR(err);
1858 ia_css_enable_isys_event_queue(bool enable) {
1859 if (sh_css_sp_is_running())
1860 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
1861 sh_css_sp_enable_isys_event_queue(enable);
1862 return IA_CSS_SUCCESS;
1865 void sh_css_free(void *ptr)
1867 if (is_vmalloc_addr(ptr))
1873 /* For Acceleration API: Flush FW (shared buffer pointer) arguments */
1875 sh_css_flush(struct ia_css_acc_fw *fw)
1877 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_flush() enter:\n");
1878 if ((fw) && (my_css.flush))
1882 /* Mapping sp threads. Currently, this is done when a stream is created and
1883 * pipelines are ready to be converted to sp pipelines. Be careful if you are
1884 * doing it from stream_create since we could run out of sp threads due to
1885 * allocation on inactive pipelines. */
1886 static enum ia_css_err
1887 map_sp_threads(struct ia_css_stream *stream, bool map) {
1888 struct ia_css_pipe *main_pipe = NULL;
1889 struct ia_css_pipe *copy_pipe = NULL;
1890 struct ia_css_pipe *capture_pipe = NULL;
1891 struct ia_css_pipe *acc_pipe = NULL;
1892 enum ia_css_err err = IA_CSS_SUCCESS;
1893 enum ia_css_pipe_id pipe_id;
1896 IA_CSS_ENTER_PRIVATE("stream = %p, map = %s",
1897 stream, map ? "true" : "false");
1901 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1902 return IA_CSS_ERR_INVALID_ARGUMENTS;
1905 main_pipe = stream->last_pipe;
1906 pipe_id = main_pipe->mode;
1908 ia_css_pipeline_map(main_pipe->pipe_num, map);
1912 case IA_CSS_PIPE_ID_PREVIEW:
1913 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1914 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1915 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1918 case IA_CSS_PIPE_ID_VIDEO:
1919 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
1920 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
1923 case IA_CSS_PIPE_ID_CAPTURE:
1924 case IA_CSS_PIPE_ID_ACC:
1931 ia_css_pipeline_map(acc_pipe->pipe_num, map);
1936 ia_css_pipeline_map(capture_pipe->pipe_num, map);
1939 /* Firmware expects copy pipe to be the last pipe mapped. (if needed) */
1942 ia_css_pipeline_map(copy_pipe->pipe_num, map);
1944 /* DH regular multi pipe - not continuous mode: map the next pipes too */
1945 if (!stream->config.continuous)
1949 for (i = 1; i < stream->num_pipes; i++)
1950 ia_css_pipeline_map(stream->pipes[i]->pipe_num, map);
1953 IA_CSS_LEAVE_ERR_PRIVATE(err);
1957 /* creates a host pipeline skeleton for all pipes in a stream. Called during
1959 static enum ia_css_err
1960 create_host_pipeline_structure(struct ia_css_stream *stream) {
1961 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
1962 struct ia_css_pipe *acc_pipe = NULL;
1963 enum ia_css_pipe_id pipe_id;
1964 struct ia_css_pipe *main_pipe = NULL;
1965 enum ia_css_err err = IA_CSS_SUCCESS;
1966 unsigned int copy_pipe_delay = 0,
1967 capture_pipe_delay = 0;
1970 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
1974 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1975 return IA_CSS_ERR_INVALID_ARGUMENTS;
1978 main_pipe = stream->last_pipe;
1982 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
1983 return IA_CSS_ERR_INVALID_ARGUMENTS;
1986 pipe_id = main_pipe->mode;
1990 case IA_CSS_PIPE_ID_PREVIEW:
1991 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
1992 copy_pipe_delay = main_pipe->dvs_frame_delay;
1993 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
1994 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
1995 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
1996 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
1997 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2000 case IA_CSS_PIPE_ID_VIDEO:
2001 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2002 copy_pipe_delay = main_pipe->dvs_frame_delay;
2003 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2004 capture_pipe_delay = IA_CSS_FRAME_DELAY_0;
2005 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2006 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2009 case IA_CSS_PIPE_ID_CAPTURE:
2010 capture_pipe = main_pipe;
2011 capture_pipe_delay = main_pipe->dvs_frame_delay;
2014 case IA_CSS_PIPE_ID_YUVPP:
2015 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2016 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2019 case IA_CSS_PIPE_ID_ACC:
2020 err = ia_css_pipeline_create(&main_pipe->pipeline, main_pipe->mode,
2021 main_pipe->pipe_num, main_pipe->dvs_frame_delay);
2025 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2028 if ((err == IA_CSS_SUCCESS) && copy_pipe)
2030 err = ia_css_pipeline_create(©_pipe->pipeline,
2032 copy_pipe->pipe_num,
2036 if ((err == IA_CSS_SUCCESS) && capture_pipe)
2038 err = ia_css_pipeline_create(&capture_pipe->pipeline,
2040 capture_pipe->pipe_num,
2041 capture_pipe_delay);
2044 if ((err == IA_CSS_SUCCESS) && acc_pipe)
2046 err = ia_css_pipeline_create(&acc_pipe->pipeline, acc_pipe->mode,
2047 acc_pipe->pipe_num, main_pipe->dvs_frame_delay);
2050 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2051 if (!stream->config.continuous)
2055 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2056 main_pipe = stream->pipes[i];
2057 err = ia_css_pipeline_create(&main_pipe->pipeline,
2059 main_pipe->pipe_num,
2060 main_pipe->dvs_frame_delay);
2064 IA_CSS_LEAVE_ERR_PRIVATE(err);
2068 /* creates a host pipeline for all pipes in a stream. Called during
2070 static enum ia_css_err
2071 create_host_pipeline(struct ia_css_stream *stream) {
2072 struct ia_css_pipe *copy_pipe = NULL, *capture_pipe = NULL;
2073 struct ia_css_pipe *acc_pipe = NULL;
2074 enum ia_css_pipe_id pipe_id;
2075 struct ia_css_pipe *main_pipe = NULL;
2076 enum ia_css_err err = IA_CSS_SUCCESS;
2077 unsigned int max_input_width = 0;
2079 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
2082 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2083 return IA_CSS_ERR_INVALID_ARGUMENTS;
2086 main_pipe = stream->last_pipe;
2087 pipe_id = main_pipe->mode;
2089 /* No continuous frame allocation for capture pipe. It uses the
2090 * "main" pipe's frames. */
2091 if ((pipe_id == IA_CSS_PIPE_ID_PREVIEW) ||
2092 (pipe_id == IA_CSS_PIPE_ID_VIDEO))
2094 /* About pipe_id == IA_CSS_PIPE_ID_PREVIEW && stream->config.mode != IA_CSS_INPUT_MODE_MEMORY:
2095 * The original condition pipe_id == IA_CSS_PIPE_ID_PREVIEW is too strong. E.g. in SkyCam (with memory
2096 * based input frames) there is no continuous mode and thus no need for allocated continuous frames
2097 * This is not only for SkyCam but for all preview cases that use DDR based input frames. For this
2098 * reason the stream->config.mode != IA_CSS_INPUT_MODE_MEMORY has beed added.
2100 if (stream->config.continuous ||
2101 (pipe_id == IA_CSS_PIPE_ID_PREVIEW &&
2102 stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)) {
2103 err = alloc_continuous_frames(main_pipe, true);
2104 if (err != IA_CSS_SUCCESS)
2109 #if defined(USE_INPUT_SYSTEM_VERSION_2)
2110 /* old isys: need to allocate_mipi_frames() even in IA_CSS_PIPE_MODE_COPY */
2111 if (pipe_id != IA_CSS_PIPE_ID_ACC)
2113 err = allocate_mipi_frames(main_pipe, &stream->info);
2114 if (err != IA_CSS_SUCCESS)
2117 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
2118 if ((pipe_id != IA_CSS_PIPE_ID_ACC) &&
2119 (main_pipe->config.mode != IA_CSS_PIPE_MODE_COPY))
2121 err = allocate_mipi_frames(main_pipe, &stream->info);
2122 if (err != IA_CSS_SUCCESS)
2129 case IA_CSS_PIPE_ID_PREVIEW:
2130 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
2131 capture_pipe = main_pipe->pipe_settings.preview.capture_pipe;
2132 acc_pipe = main_pipe->pipe_settings.preview.acc_pipe;
2134 main_pipe->pipe_settings.preview.preview_binary.info->sp.input.max_width;
2136 err = create_host_preview_pipeline(main_pipe);
2137 if (err != IA_CSS_SUCCESS)
2142 case IA_CSS_PIPE_ID_VIDEO:
2143 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
2144 capture_pipe = main_pipe->pipe_settings.video.capture_pipe;
2146 main_pipe->pipe_settings.video.video_binary.info->sp.input.max_width;
2148 err = create_host_video_pipeline(main_pipe);
2149 if (err != IA_CSS_SUCCESS)
2154 case IA_CSS_PIPE_ID_CAPTURE:
2155 capture_pipe = main_pipe;
2159 case IA_CSS_PIPE_ID_YUVPP:
2160 err = create_host_yuvpp_pipeline(main_pipe);
2161 if (err != IA_CSS_SUCCESS)
2166 case IA_CSS_PIPE_ID_ACC:
2167 err = create_host_acc_pipeline(main_pipe);
2168 if (err != IA_CSS_SUCCESS)
2173 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2175 if (err != IA_CSS_SUCCESS)
2180 err = create_host_copy_pipeline(copy_pipe, max_input_width,
2181 main_pipe->continuous_frames[0]);
2182 if (err != IA_CSS_SUCCESS)
2188 err = create_host_capture_pipeline(capture_pipe);
2189 if (err != IA_CSS_SUCCESS)
2195 err = create_host_acc_pipeline(acc_pipe);
2196 if (err != IA_CSS_SUCCESS)
2200 /* DH regular multi pipe - not continuous mode: create the next pipelines too */
2201 if (!stream->config.continuous)
2205 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err; i++) {
2206 switch (stream->pipes[i]->mode) {
2207 case IA_CSS_PIPE_ID_PREVIEW:
2208 err = create_host_preview_pipeline(stream->pipes[i]);
2210 case IA_CSS_PIPE_ID_VIDEO:
2211 err = create_host_video_pipeline(stream->pipes[i]);
2213 case IA_CSS_PIPE_ID_CAPTURE:
2214 err = create_host_capture_pipeline(stream->pipes[i]);
2216 case IA_CSS_PIPE_ID_YUVPP:
2217 err = create_host_yuvpp_pipeline(stream->pipes[i]);
2219 case IA_CSS_PIPE_ID_ACC:
2220 err = create_host_acc_pipeline(stream->pipes[i]);
2223 err = IA_CSS_ERR_INVALID_ARGUMENTS;
2225 if (err != IA_CSS_SUCCESS)
2231 IA_CSS_LEAVE_ERR_PRIVATE(err);
2235 static enum ia_css_err
2236 init_pipe_defaults(enum ia_css_pipe_mode mode,
2237 struct ia_css_pipe *pipe,
2241 IA_CSS_ERROR("NULL pipe parameter");
2242 return IA_CSS_ERR_INVALID_ARGUMENTS;
2245 /* Initialize pipe to pre-defined defaults */
2246 *pipe = IA_CSS_DEFAULT_PIPE;
2248 /* TODO: JB should not be needed, but temporary backward reference */
2251 case IA_CSS_PIPE_MODE_PREVIEW:
2252 pipe->mode = IA_CSS_PIPE_ID_PREVIEW;
2253 pipe->pipe_settings.preview = IA_CSS_DEFAULT_PREVIEW_SETTINGS;
2255 case IA_CSS_PIPE_MODE_CAPTURE:
2257 pipe->mode = IA_CSS_PIPE_ID_COPY;
2259 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2261 pipe->pipe_settings.capture = IA_CSS_DEFAULT_CAPTURE_SETTINGS;
2263 case IA_CSS_PIPE_MODE_VIDEO:
2264 pipe->mode = IA_CSS_PIPE_ID_VIDEO;
2265 pipe->pipe_settings.video = IA_CSS_DEFAULT_VIDEO_SETTINGS;
2267 case IA_CSS_PIPE_MODE_ACC:
2268 pipe->mode = IA_CSS_PIPE_ID_ACC;
2270 case IA_CSS_PIPE_MODE_COPY:
2271 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
2273 case IA_CSS_PIPE_MODE_YUVPP:
2274 pipe->mode = IA_CSS_PIPE_ID_YUVPP;
2275 pipe->pipe_settings.yuvpp = IA_CSS_DEFAULT_YUVPP_SETTINGS;
2278 return IA_CSS_ERR_INVALID_ARGUMENTS;
2281 return IA_CSS_SUCCESS;
2285 pipe_global_init(void)
2289 my_css.pipe_counter = 0;
2290 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2291 my_css.all_pipes[i] = NULL;
2295 static enum ia_css_err
2296 pipe_generate_pipe_num(const struct ia_css_pipe *pipe,
2297 unsigned int *pipe_number) {
2298 const u8 INVALID_PIPE_NUM = (uint8_t)~(0);
2299 u8 pipe_num = INVALID_PIPE_NUM;
2304 IA_CSS_ERROR("NULL pipe parameter");
2305 return IA_CSS_ERR_INVALID_ARGUMENTS;
2308 /* Assign a new pipe_num .... search for empty place */
2309 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++)
2311 if (!my_css.all_pipes[i]) {
2312 /*position is reserved */
2313 my_css.all_pipes[i] = (struct ia_css_pipe *)pipe;
2318 if (pipe_num == INVALID_PIPE_NUM)
2320 /* Max number of pipes already allocated */
2321 IA_CSS_ERROR("Max number of pipes already created");
2322 return IA_CSS_ERR_RESOURCE_EXHAUSTED;
2325 my_css.pipe_counter++;
2327 IA_CSS_LOG("pipe_num (%d)", pipe_num);
2329 *pipe_number = pipe_num;
2330 return IA_CSS_SUCCESS;
2334 pipe_release_pipe_num(unsigned int pipe_num)
2336 my_css.all_pipes[pipe_num] = NULL;
2337 my_css.pipe_counter--;
2338 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2339 "pipe_release_pipe_num (%d)\n", pipe_num);
2342 static enum ia_css_err
2343 create_pipe(enum ia_css_pipe_mode mode,
2344 struct ia_css_pipe **pipe,
2346 enum ia_css_err err = IA_CSS_SUCCESS;
2347 struct ia_css_pipe *me;
2351 IA_CSS_ERROR("NULL pipe parameter");
2352 return IA_CSS_ERR_INVALID_ARGUMENTS;
2355 me = kmalloc(sizeof(*me), GFP_KERNEL);
2357 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
2359 err = init_pipe_defaults(mode, me, copy_pipe);
2360 if (err != IA_CSS_SUCCESS)
2366 err = pipe_generate_pipe_num(me, &me->pipe_num);
2367 if (err != IA_CSS_SUCCESS)
2374 return IA_CSS_SUCCESS;
2377 struct ia_css_pipe *
2378 find_pipe_by_num(uint32_t pipe_num)
2382 for (i = 0; i < IA_CSS_PIPELINE_NUM_MAX; i++) {
2383 if (my_css.all_pipes[i] &&
2384 ia_css_pipe_get_pipe_num(my_css.all_pipes[i]) == pipe_num) {
2385 return my_css.all_pipes[i];
2391 static void sh_css_pipe_free_acc_binaries(
2392 struct ia_css_pipe *pipe)
2394 struct ia_css_pipeline *pipeline;
2395 struct ia_css_pipeline_stage *stage;
2399 IA_CSS_ERROR("NULL input pointer");
2402 pipeline = &pipe->pipeline;
2404 /* loop through the stages and unload them */
2405 for (stage = pipeline->stages; stage; stage = stage->next) {
2406 struct ia_css_fw_info *firmware = (struct ia_css_fw_info *)
2409 ia_css_pipe_unload_extension(pipe, firmware);
2414 ia_css_pipe_destroy(struct ia_css_pipe *pipe) {
2415 enum ia_css_err err = IA_CSS_SUCCESS;
2417 IA_CSS_ENTER("pipe = %p", pipe);
2421 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2422 return IA_CSS_ERR_INVALID_ARGUMENTS;
2427 IA_CSS_LOG("ia_css_stream_destroy not called!");
2428 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2429 return IA_CSS_ERR_INVALID_ARGUMENTS;
2432 switch (pipe->config.mode)
2434 case IA_CSS_PIPE_MODE_PREVIEW:
2435 /* need to take into account that this function is also called
2436 on the internal copy pipe */
2437 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
2438 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2439 pipe->continuous_frames);
2440 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2441 pipe->cont_md_buffers);
2442 if (pipe->pipe_settings.preview.copy_pipe) {
2443 err = ia_css_pipe_destroy(pipe->pipe_settings.preview.copy_pipe);
2444 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2445 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2450 case IA_CSS_PIPE_MODE_VIDEO:
2451 if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
2452 ia_css_frame_free_multiple(NUM_CONTINUOUS_FRAMES,
2453 pipe->continuous_frames);
2454 ia_css_metadata_free_multiple(NUM_CONTINUOUS_FRAMES,
2455 pipe->cont_md_buffers);
2456 if (pipe->pipe_settings.video.copy_pipe) {
2457 err = ia_css_pipe_destroy(pipe->pipe_settings.video.copy_pipe);
2458 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2459 "ia_css_pipe_destroy(): destroyed internal copy pipe err=%d\n",
2464 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2465 pipe->pipe_settings.video.tnr_frames);
2467 ia_css_frame_free_multiple(NUM_TNR_FRAMES,
2468 pipe->pipe_settings.video.tnr_frames);
2470 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2471 pipe->pipe_settings.video.delay_frames);
2473 case IA_CSS_PIPE_MODE_CAPTURE:
2474 ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES,
2475 pipe->pipe_settings.capture.delay_frames);
2477 case IA_CSS_PIPE_MODE_ACC:
2478 sh_css_pipe_free_acc_binaries(pipe);
2480 case IA_CSS_PIPE_MODE_COPY:
2482 case IA_CSS_PIPE_MODE_YUVPP:
2486 sh_css_params_free_gdc_lut(pipe->scaler_pp_lut);
2487 pipe->scaler_pp_lut = mmgr_NULL;
2489 my_css.active_pipes[ia_css_pipe_get_pipe_num(pipe)] = NULL;
2490 sh_css_pipe_free_shading_table(pipe);
2492 ia_css_pipeline_destroy(&pipe->pipeline);
2493 pipe_release_pipe_num(ia_css_pipe_get_pipe_num(pipe));
2495 /* Temporarily, not every sh_css_pipe has an acc_extension. */
2496 if (pipe->config.acc_extension)
2498 ia_css_pipe_unload_extension(pipe, pipe->config.acc_extension);
2501 IA_CSS_LEAVE("err = %d", err);
2508 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() enter: void\n");
2509 #if WITH_PC_MONITORING
2510 sh_css_print("PC_MONITORING: %s() -- started\n", __func__);
2511 print_pc_histogram();
2514 sh_css_params_free_default_gdc_lut();
2516 /* TODO: JB: implement decent check and handling of freeing mipi frames */
2517 //assert(ref_count_mipi_allocation == 0); //mipi frames are not freed
2518 /* cleanup generic data */
2519 sh_css_params_uninit();
2520 ia_css_refcount_uninit();
2522 ia_css_rmgr_uninit();
2524 #if !defined(HAS_NO_INPUT_FORMATTER)
2525 /* needed for reprogramming the inputformatter after power cycle of css */
2526 ifmtr_set_if_blocking_mode_reset = true;
2529 if (!fw_explicitly_loaded) {
2530 ia_css_unload_firmware();
2532 ia_css_spctrl_unload_fw(SP0_ID);
2533 sh_css_sp_set_sp_running(false);
2534 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
2535 /* check and free any remaining mipi frames */
2536 free_mipi_frames(NULL);
2539 sh_css_sp_reset_global_vars();
2541 #if !defined(HAS_NO_INPUT_SYSTEM)
2542 ia_css_isys_uninit();
2545 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_uninit() leave: return_void\n");
2548 #if defined(HAS_IRQ_MAP_VERSION_2)
2549 enum ia_css_err ia_css_irq_translate(
2550 unsigned int *irq_infos)
2553 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_more_irqs;
2554 unsigned int infos = 0;
2556 /* irq_infos can be NULL, but that would make the function useless */
2557 /* assert(irq_infos != NULL); */
2558 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2559 "ia_css_irq_translate() enter: irq_infos=%p\n", irq_infos);
2561 while (status == hrt_isp_css_irq_status_more_irqs) {
2562 status = virq_get_channel_id(&irq);
2563 if (status == hrt_isp_css_irq_status_error)
2564 return IA_CSS_ERR_INTERNAL_ERROR;
2566 #if WITH_PC_MONITORING
2567 sh_css_print("PC_MONITORING: %s() irq = %d, sh_binary_running set to 0\n",
2569 sh_binary_running = 0;
2574 /* When SP goes to idle, info is available in the
2576 infos |= IA_CSS_IRQ_INFO_EVENTS_READY;
2580 #if !defined(HAS_NO_INPUT_SYSTEM)
2582 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF;
2585 infos |= IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF;
2588 infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR;
2591 #if !defined(HAS_NO_INPUT_FORMATTER)
2593 infos |= IA_CSS_IRQ_INFO_IF_ERROR;
2597 infos |= IA_CSS_IRQ_INFO_DMA_ERROR;
2600 infos |= sh_css_get_sw_interrupt_value(0);
2603 infos |= sh_css_get_sw_interrupt_value(1);
2604 /* pqiao TODO: also assumption here */
2614 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2615 "ia_css_irq_translate() leave: irq_infos=%u\n",
2618 return IA_CSS_SUCCESS;
2621 enum ia_css_err ia_css_irq_enable(
2622 enum ia_css_irq_info info,
2625 virq_id_t irq = N_virq_id;
2627 IA_CSS_ENTER("info=%d, enable=%d", info, enable);
2630 #if !defined(HAS_NO_INPUT_FORMATTER)
2631 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2632 irq = virq_isys_sof;
2634 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2635 irq = virq_isys_eof;
2637 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2638 irq = virq_isys_csi;
2640 case IA_CSS_IRQ_INFO_IF_ERROR:
2641 irq = virq_ifmt0_id;
2644 case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF:
2645 case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF:
2646 case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR:
2647 case IA_CSS_IRQ_INFO_IF_ERROR:
2648 /* Just ignore those unused IRQs without printing errors */
2649 return IA_CSS_SUCCESS;
2651 case IA_CSS_IRQ_INFO_DMA_ERROR:
2654 case IA_CSS_IRQ_INFO_SW_0:
2655 irq = virq_sw_pin_0;
2657 case IA_CSS_IRQ_INFO_SW_1:
2658 irq = virq_sw_pin_1;
2661 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
2662 return IA_CSS_ERR_INVALID_ARGUMENTS;
2665 cnd_virq_enable_channel(irq, enable);
2667 IA_CSS_LEAVE_ERR(IA_CSS_SUCCESS);
2668 return IA_CSS_SUCCESS;
2672 #error "sh_css.c: IRQ MAP must be one of { IRQ_MAP_VERSION_2 }"
2676 sh_css_get_sw_interrupt_value(unsigned int irq)
2678 unsigned int irq_value;
2680 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2681 "sh_css_get_sw_interrupt_value() enter: irq=%d\n", irq);
2682 irq_value = sh_css_sp_get_sw_interrupt_value(irq);
2683 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2684 "sh_css_get_sw_interrupt_value() leave: irq_value=%d\n", irq_value);
2688 /* configure and load the copy binary, the next binary is used to
2689 determine whether the copy binary needs to do left padding. */
2690 static enum ia_css_err load_copy_binary(
2691 struct ia_css_pipe *pipe,
2692 struct ia_css_binary *copy_binary,
2693 struct ia_css_binary *next_binary)
2695 struct ia_css_frame_info copy_out_info, copy_in_info, copy_vf_info;
2696 unsigned int left_padding;
2697 enum ia_css_err err;
2698 struct ia_css_binary_descr copy_descr;
2700 /* next_binary can be NULL */
2702 assert(copy_binary);
2703 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2704 "load_copy_binary() enter:\n");
2707 copy_out_info = next_binary->in_frame_info;
2708 left_padding = next_binary->left_padding;
2710 copy_out_info = pipe->output_info[0];
2711 copy_vf_info = pipe->vf_output_info[0];
2712 ia_css_frame_info_set_format(©_vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
2716 ia_css_pipe_get_copy_binarydesc(pipe, ©_descr,
2717 ©_in_info, ©_out_info,
2718 (next_binary) ? NULL : NULL/*TODO: ©_vf_info*/);
2719 err = ia_css_binary_find(©_descr, copy_binary);
2720 if (err != IA_CSS_SUCCESS)
2722 copy_binary->left_padding = left_padding;
2723 return IA_CSS_SUCCESS;
2726 static enum ia_css_err
2727 alloc_continuous_frames(
2728 struct ia_css_pipe *pipe, bool init_time) {
2729 enum ia_css_err err = IA_CSS_SUCCESS;
2730 struct ia_css_frame_info ref_info;
2731 enum ia_css_pipe_id pipe_id;
2733 unsigned int i, idx;
2734 unsigned int num_frames;
2735 struct ia_css_pipe *capture_pipe = NULL;
2737 IA_CSS_ENTER_PRIVATE("pipe = %p, init_time = %d", pipe, init_time);
2739 if ((!pipe) || (!pipe->stream))
2741 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
2742 return IA_CSS_ERR_INVALID_ARGUMENTS;
2745 pipe_id = pipe->mode;
2746 continuous = pipe->stream->config.continuous;
2751 num_frames = pipe->stream->config.init_num_cont_raw_buf;
2752 pipe->stream->continuous_pipe = pipe;
2754 num_frames = pipe->stream->config.target_num_cont_raw_buf;
2757 num_frames = NUM_ONLINE_INIT_CONTINUOUS_FRAMES;
2760 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2762 ref_info = pipe->pipe_settings.preview.preview_binary.in_frame_info;
2763 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2765 ref_info = pipe->pipe_settings.video.video_binary.in_frame_info;
2768 /* should not happen */
2769 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2770 return IA_CSS_ERR_INTERNAL_ERROR;
2773 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
2774 /* For CSI2+, the continuous frame will hold the full input frame */
2775 ref_info.res.width = pipe->stream->config.input_config.input_res.width;
2776 ref_info.res.height = pipe->stream->config.input_config.input_res.height;
2778 /* Ensure padded width is aligned for 2401 */
2779 ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS);
2782 #if !defined(HAS_NO_PACKED_RAW_PIXELS)
2783 if (pipe->stream->config.pack_raw_pixels)
2785 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2786 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW_PACKED\n");
2787 ref_info.format = IA_CSS_FRAME_FORMAT_RAW_PACKED;
2791 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
2792 "alloc_continuous_frames() IA_CSS_FRAME_FORMAT_RAW\n");
2793 ref_info.format = IA_CSS_FRAME_FORMAT_RAW;
2796 /* Write format back to binary */
2797 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
2799 pipe->pipe_settings.preview.preview_binary.in_frame_info.format =
2801 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
2802 } else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
2804 pipe->pipe_settings.video.video_binary.in_frame_info.format = ref_info.format;
2805 capture_pipe = pipe->pipe_settings.video.capture_pipe;
2808 /* should not happen */
2809 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
2810 return IA_CSS_ERR_INTERNAL_ERROR;
2816 idx = pipe->stream->config.init_num_cont_raw_buf;
2818 for (i = idx; i < NUM_CONTINUOUS_FRAMES; i++)
2820 /* free previous frame */
2821 if (pipe->continuous_frames[i]) {
2822 ia_css_frame_free(pipe->continuous_frames[i]);
2823 pipe->continuous_frames[i] = NULL;
2825 /* free previous metadata buffer */
2826 ia_css_metadata_free(pipe->cont_md_buffers[i]);
2827 pipe->cont_md_buffers[i] = NULL;
2829 /* check if new frame needed */
2830 if (i < num_frames) {
2831 /* allocate new frame */
2832 err = ia_css_frame_allocate_from_info(
2833 &pipe->continuous_frames[i],
2835 if (err != IA_CSS_SUCCESS) {
2836 IA_CSS_LEAVE_ERR_PRIVATE(err);
2839 /* allocate metadata buffer */
2840 pipe->cont_md_buffers[i] = ia_css_metadata_allocate(
2841 &pipe->stream->info.metadata_info);
2844 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
2845 return IA_CSS_SUCCESS;
2849 ia_css_alloc_continuous_frame_remain(struct ia_css_stream *stream) {
2851 return IA_CSS_ERR_INVALID_ARGUMENTS;
2852 return alloc_continuous_frames(stream->continuous_pipe, false);
2855 static enum ia_css_err
2856 load_preview_binaries(struct ia_css_pipe *pipe) {
2857 struct ia_css_frame_info prev_in_info,
2861 struct ia_css_binary_descr preview_descr;
2863 enum ia_css_err err = IA_CSS_SUCCESS;
2864 bool continuous, need_vf_pp = false;
2865 bool need_isp_copy_binary = false;
2866 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2867 bool sensor = false;
2869 /* preview only have 1 output pin now */
2870 struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0];
2871 struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview;
2873 IA_CSS_ENTER_PRIVATE("");
2875 assert(pipe->stream);
2876 assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW);
2878 online = pipe->stream->config.online;
2879 continuous = pipe->stream->config.continuous;
2880 #ifdef USE_INPUT_SYSTEM_VERSION_2401
2881 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
2884 if (mycs->preview_binary.info)
2885 return IA_CSS_SUCCESS;
2887 err = ia_css_util_check_input(&pipe->stream->config, false, false);
2888 if (err != IA_CSS_SUCCESS)
2890 err = ia_css_frame_check_info(pipe_out_info);
2891 if (err != IA_CSS_SUCCESS)
2894 /* Note: the current selection of vf_pp binary and
2895 * parameterization of the preview binary contains a few pieces
2896 * of hardcoded knowledge. This needs to be cleaned up such that
2897 * the binary selection becomes more generic.
2898 * The vf_pp binary is needed if one or more of the following features
2900 * 1. YUV downscaling.
2902 * 3. An output format that is not supported by the preview binary.
2903 * In practice this means something other than yuv_line or nv12.
2904 * The decision if the vf_pp binary is needed for YUV downscaling is
2905 * made after the preview binary selection, since some preview binaries
2906 * can perform the requested YUV downscaling.
2908 need_vf_pp = pipe->config.enable_dz;
2909 need_vf_pp |= pipe_out_info->format != IA_CSS_FRAME_FORMAT_YUV_LINE &&
2910 !(pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12 ||
2911 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_16 ||
2912 pipe_out_info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY);
2914 /* Preview step 1 */
2915 if (pipe->vf_yuv_ds_input_info.res.width)
2916 prev_vf_info = pipe->vf_yuv_ds_input_info;
2918 prev_vf_info = *pipe_out_info;
2919 /* If vf_pp is needed, then preview must output yuv_line.
2920 * The exception is when vf_pp is manually disabled, that is only
2921 * used in combination with a pipeline extension that requires
2922 * yuv_line as input.
2925 ia_css_frame_info_set_format(&prev_vf_info,
2926 IA_CSS_FRAME_FORMAT_YUV_LINE);
2928 err = ia_css_pipe_get_preview_binarydesc(
2935 if (err != IA_CSS_SUCCESS)
2937 err = ia_css_binary_find(&preview_descr, &mycs->preview_binary);
2938 if (err != IA_CSS_SUCCESS)
2941 if (atomisp_hw_is_isp2401) {
2942 /* The delay latency determines the number of invalid frames after
2943 * a stream is started. */
2944 pipe->num_invalid_frames = pipe->dvs_frame_delay;
2945 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
2947 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
2948 "load_preview_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
2949 pipe->num_invalid_frames, pipe->dvs_frame_delay);
2952 /* The vf_pp binary is needed when (further) YUV downscaling is required */
2953 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.width != pipe_out_info->res.width;
2954 need_vf_pp |= mycs->preview_binary.out_frame_info[0].res.height != pipe_out_info->res.height;
2956 /* When vf_pp is needed, then the output format of the selected
2957 * preview binary must be yuv_line. If this is not the case,
2958 * then the preview binary selection is done again.
2961 (mycs->preview_binary.out_frame_info[0].format != IA_CSS_FRAME_FORMAT_YUV_LINE))
2963 /* Preview step 2 */
2964 if (pipe->vf_yuv_ds_input_info.res.width)
2965 prev_vf_info = pipe->vf_yuv_ds_input_info;
2967 prev_vf_info = *pipe_out_info;
2969 ia_css_frame_info_set_format(&prev_vf_info,
2970 IA_CSS_FRAME_FORMAT_YUV_LINE);
2972 err = ia_css_pipe_get_preview_binarydesc(
2979 if (err != IA_CSS_SUCCESS)
2981 err = ia_css_binary_find(&preview_descr,
2982 &mycs->preview_binary);
2983 if (err != IA_CSS_SUCCESS)
2989 struct ia_css_binary_descr vf_pp_descr;
2991 /* Viewfinder post-processing */
2992 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
2993 &mycs->preview_binary.out_frame_info[0],
2995 err = ia_css_binary_find(&vf_pp_descr,
2996 &mycs->vf_pp_binary);
2997 if (err != IA_CSS_SUCCESS)
3001 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3002 /* When the input system is 2401, only the Direct Sensor Mode
3003 * Offline Preview uses the ISP copy binary.
3005 need_isp_copy_binary = !online && sensor;
3007 /* About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY:
3008 * This is typical the case with SkyCam (which has no input system) but it also applies to all cases
3009 * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical
3010 * copies sensor data to DDR) does not have much use.
3012 if (!atomisp_hw_is_isp2401)
3013 need_isp_copy_binary = !online && !continuous;
3015 need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY);
3019 if (need_isp_copy_binary)
3021 err = load_copy_binary(pipe,
3023 &mycs->preview_binary);
3024 if (err != IA_CSS_SUCCESS)
3028 if (pipe->shading_table)
3030 ia_css_shading_table_free(pipe->shading_table);
3031 pipe->shading_table = NULL;
3034 return IA_CSS_SUCCESS;
3038 ia_css_binary_unload(struct ia_css_binary *binary)
3040 ia_css_binary_destroy_isp_parameters(binary);
3043 static enum ia_css_err
3044 unload_preview_binaries(struct ia_css_pipe *pipe) {
3045 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3047 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3049 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3050 return IA_CSS_ERR_INVALID_ARGUMENTS;
3052 ia_css_binary_unload(&pipe->pipe_settings.preview.copy_binary);
3053 ia_css_binary_unload(&pipe->pipe_settings.preview.preview_binary);
3054 ia_css_binary_unload(&pipe->pipe_settings.preview.vf_pp_binary);
3056 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
3057 return IA_CSS_SUCCESS;
3060 static const struct ia_css_fw_info *last_output_firmware(
3061 const struct ia_css_fw_info *fw)
3063 const struct ia_css_fw_info *last_fw = NULL;
3064 /* fw can be NULL */
3065 IA_CSS_ENTER_LEAVE_PRIVATE("");
3067 for (; fw; fw = fw->next) {
3068 const struct ia_css_fw_info *info = fw;
3070 if (info->info.isp.sp.enable.output)
3076 static enum ia_css_err add_firmwares(
3077 struct ia_css_pipeline *me,
3078 struct ia_css_binary *binary,
3079 const struct ia_css_fw_info *fw,
3080 const struct ia_css_fw_info *last_fw,
3081 unsigned int binary_mode,
3082 struct ia_css_frame *in_frame,
3083 struct ia_css_frame *out_frame,
3084 struct ia_css_frame *vf_frame,
3085 struct ia_css_pipeline_stage **my_stage,
3086 struct ia_css_pipeline_stage **vf_stage)
3088 enum ia_css_err err = IA_CSS_SUCCESS;
3089 struct ia_css_pipeline_stage *extra_stage = NULL;
3090 struct ia_css_pipeline_stage_desc stage_desc;
3092 /* all args can be NULL ??? */
3093 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3094 "add_firmwares() enter:\n");
3096 for (; fw; fw = fw->next) {
3097 struct ia_css_frame *out[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL};
3098 struct ia_css_frame *in = NULL;
3099 struct ia_css_frame *vf = NULL;
3101 if ((fw == last_fw) && (fw->info.isp.sp.enable.out_frame != 0)) {
3104 if (fw->info.isp.sp.enable.in_frame != 0) {
3107 if (fw->info.isp.sp.enable.out_frame != 0) {
3110 ia_css_pipe_get_firmwares_stage_desc(&stage_desc, binary,
3111 out, in, vf, fw, binary_mode);
3112 err = ia_css_pipeline_create_and_add_stage(me,
3115 if (err != IA_CSS_SUCCESS)
3117 if (fw->info.isp.sp.enable.output != 0)
3118 in_frame = extra_stage->args.out_frame[0];
3119 if (my_stage && !*my_stage && extra_stage)
3120 *my_stage = extra_stage;
3121 if (vf_stage && !*vf_stage && extra_stage &&
3122 fw->info.isp.sp.enable.vf_veceven)
3123 *vf_stage = extra_stage;
3128 static enum ia_css_err add_vf_pp_stage(
3129 struct ia_css_pipe *pipe,
3130 struct ia_css_frame *in_frame,
3131 struct ia_css_frame *out_frame,
3132 struct ia_css_binary *vf_pp_binary,
3133 struct ia_css_pipeline_stage **vf_pp_stage)
3135 struct ia_css_pipeline *me = NULL;
3136 const struct ia_css_fw_info *last_fw = NULL;
3137 enum ia_css_err err = IA_CSS_SUCCESS;
3138 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3139 struct ia_css_pipeline_stage_desc stage_desc;
3141 /* out_frame can be NULL ??? */
3144 return IA_CSS_ERR_INVALID_ARGUMENTS;
3146 return IA_CSS_ERR_INVALID_ARGUMENTS;
3148 return IA_CSS_ERR_INVALID_ARGUMENTS;
3150 return IA_CSS_ERR_INVALID_ARGUMENTS;
3152 ia_css_pipe_util_create_output_frames(out_frames);
3153 me = &pipe->pipeline;
3155 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3156 "add_vf_pp_stage() enter:\n");
3158 *vf_pp_stage = NULL;
3160 last_fw = last_output_firmware(pipe->vf_stage);
3161 if (!pipe->extra_config.disable_vf_pp) {
3163 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3164 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3165 out_frames, in_frame, NULL);
3167 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3168 ia_css_pipe_get_generic_stage_desc(&stage_desc, vf_pp_binary,
3169 out_frames, in_frame, NULL);
3171 err = ia_css_pipeline_create_and_add_stage(me, &stage_desc, vf_pp_stage);
3172 if (err != IA_CSS_SUCCESS)
3174 in_frame = (*vf_pp_stage)->args.out_frame[0];
3176 err = add_firmwares(me, vf_pp_binary, pipe->vf_stage, last_fw,
3177 IA_CSS_BINARY_MODE_VF_PP,
3178 in_frame, out_frame, NULL,
3183 static enum ia_css_err add_yuv_scaler_stage(
3184 struct ia_css_pipe *pipe,
3185 struct ia_css_pipeline *me,
3186 struct ia_css_frame *in_frame,
3187 struct ia_css_frame *out_frame,
3188 struct ia_css_frame *internal_out_frame,
3189 struct ia_css_binary *yuv_scaler_binary,
3190 struct ia_css_pipeline_stage **pre_vf_pp_stage)
3192 const struct ia_css_fw_info *last_fw;
3193 enum ia_css_err err = IA_CSS_SUCCESS;
3194 struct ia_css_frame *vf_frame = NULL;
3195 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3196 struct ia_css_pipeline_stage_desc stage_desc;
3198 /* out_frame can be NULL ??? */
3202 assert(yuv_scaler_binary);
3203 assert(pre_vf_pp_stage);
3204 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3205 "add_yuv_scaler_stage() enter:\n");
3207 *pre_vf_pp_stage = NULL;
3208 ia_css_pipe_util_create_output_frames(out_frames);
3210 last_fw = last_output_firmware(pipe->output_stage);
3213 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3214 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3215 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3217 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3218 ia_css_pipe_util_set_output_frames(out_frames, 1, internal_out_frame);
3219 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3220 yuv_scaler_binary, out_frames, in_frame, vf_frame);
3222 err = ia_css_pipeline_create_and_add_stage(me,
3225 if (err != IA_CSS_SUCCESS)
3227 in_frame = (*pre_vf_pp_stage)->args.out_frame[0];
3229 err = add_firmwares(me, yuv_scaler_binary, pipe->output_stage, last_fw,
3230 IA_CSS_BINARY_MODE_CAPTURE_PP,
3231 in_frame, out_frame, vf_frame,
3232 NULL, pre_vf_pp_stage);
3233 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3234 (*pre_vf_pp_stage)->args.vf_downscale_log2 =
3235 yuv_scaler_binary->vf_downscale_log2;
3237 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3238 "add_yuv_scaler_stage() leave:\n");
3242 static enum ia_css_err add_capture_pp_stage(
3243 struct ia_css_pipe *pipe,
3244 struct ia_css_pipeline *me,
3245 struct ia_css_frame *in_frame,
3246 struct ia_css_frame *out_frame,
3247 struct ia_css_binary *capture_pp_binary,
3248 struct ia_css_pipeline_stage **capture_pp_stage)
3250 const struct ia_css_fw_info *last_fw = NULL;
3251 enum ia_css_err err = IA_CSS_SUCCESS;
3252 struct ia_css_frame *vf_frame = NULL;
3253 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3254 struct ia_css_pipeline_stage_desc stage_desc;
3256 /* out_frame can be NULL ??? */
3260 assert(capture_pp_binary);
3261 assert(capture_pp_stage);
3262 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3263 "add_capture_pp_stage() enter:\n");
3265 *capture_pp_stage = NULL;
3266 ia_css_pipe_util_create_output_frames(out_frames);
3268 last_fw = last_output_firmware(pipe->output_stage);
3269 err = ia_css_frame_allocate_from_info(&vf_frame,
3270 &capture_pp_binary->vf_frame_info);
3271 if (err != IA_CSS_SUCCESS)
3274 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3275 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3276 capture_pp_binary, out_frames, NULL, vf_frame);
3278 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3279 ia_css_pipe_get_generic_stage_desc(&stage_desc,
3280 capture_pp_binary, out_frames, NULL, vf_frame);
3282 err = ia_css_pipeline_create_and_add_stage(me,
3285 if (err != IA_CSS_SUCCESS)
3287 err = add_firmwares(me, capture_pp_binary, pipe->output_stage, last_fw,
3288 IA_CSS_BINARY_MODE_CAPTURE_PP,
3289 in_frame, out_frame, vf_frame,
3290 NULL, capture_pp_stage);
3291 /* If a firmware produce vf_pp output, we set that as vf_pp input */
3292 if (*capture_pp_stage) {
3293 (*capture_pp_stage)->args.vf_downscale_log2 =
3294 capture_pp_binary->vf_downscale_log2;
3299 static void sh_css_setup_queues(void)
3301 const struct ia_css_fw_info *fw;
3302 unsigned int HIVE_ADDR_host_sp_queues_initialized;
3304 sh_css_hmm_buffer_record_init();
3306 sh_css_event_init_irq_mask();
3309 HIVE_ADDR_host_sp_queues_initialized =
3310 fw->info.sp.host_sp_queues_initialized;
3314 /* set "host_sp_queues_initialized" to "true" */
3315 sp_dmem_store_uint32(SP0_ID,
3316 (unsigned int)sp_address_of(host_sp_queues_initialized),
3318 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "sh_css_setup_queues() leave:\n");
3321 static enum ia_css_err
3322 init_vf_frameinfo_defaults(struct ia_css_pipe *pipe,
3323 struct ia_css_frame *vf_frame, unsigned int idx) {
3324 enum ia_css_err err = IA_CSS_SUCCESS;
3325 unsigned int thread_id;
3326 enum sh_css_queue_id queue_id;
3330 sh_css_pipe_get_viewfinder_frame_info(pipe, &vf_frame->info, idx);
3331 vf_frame->contiguous = false;
3332 vf_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3333 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3334 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, thread_id, &queue_id);
3335 vf_frame->dynamic_queue_id = queue_id;
3336 vf_frame->buf_type = IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx;
3338 err = ia_css_frame_init_planes(vf_frame);
3342 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3344 get_crop_lines_for_bayer_order(
3345 const struct ia_css_stream_config *config)
3348 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR)
3349 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3356 get_crop_columns_for_bayer_order(
3357 const struct ia_css_stream_config *config)
3360 if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB)
3361 || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG))
3367 /* This function is to get the sum of all extra pixels in addition to the effective
3368 * input, it includes dvs envelop and filter run-in */
3369 static void get_pipe_extra_pixel(struct ia_css_pipe *pipe,
3370 unsigned int *extra_row, unsigned int *extra_column)
3372 enum ia_css_pipe_id pipe_id = pipe->mode;
3373 unsigned int left_cropping = 0, top_cropping = 0;
3375 struct ia_css_resolution dvs_env = pipe->config.dvs_envelope;
3377 /* The dvs envelope info may not be correctly sent down via pipe config
3378 * The check is made and the correct value is populated in the binary info
3379 * Use this value when computing crop, else excess lines may get trimmed
3382 case IA_CSS_PIPE_ID_PREVIEW:
3383 if (pipe->pipe_settings.preview.preview_binary.info) {
3385 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.left_cropping;
3387 pipe->pipe_settings.preview.preview_binary.info->sp.pipeline.top_cropping;
3389 dvs_env = pipe->pipe_settings.preview.preview_binary.dvs_envelope;
3391 case IA_CSS_PIPE_ID_VIDEO:
3392 if (pipe->pipe_settings.video.video_binary.info) {
3394 pipe->pipe_settings.video.video_binary.info->sp.pipeline.left_cropping;
3396 pipe->pipe_settings.video.video_binary.info->sp.pipeline.top_cropping;
3398 dvs_env = pipe->pipe_settings.video.video_binary.dvs_envelope;
3400 case IA_CSS_PIPE_ID_CAPTURE:
3401 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
3402 if (pipe->pipe_settings.capture.primary_binary[i].info) {
3404 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.left_cropping;
3406 pipe->pipe_settings.capture.primary_binary[i].info->sp.pipeline.top_cropping;
3409 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.width;
3411 pipe->pipe_settings.capture.primary_binary[i].dvs_envelope.height;
3418 *extra_row = top_cropping + dvs_env.height;
3419 *extra_column = left_cropping + dvs_env.width;
3423 ia_css_get_crop_offsets(
3424 struct ia_css_pipe *pipe,
3425 struct ia_css_frame_info *in_frame)
3427 unsigned int row = 0;
3428 unsigned int column = 0;
3429 struct ia_css_resolution *input_res;
3430 struct ia_css_resolution *effective_res;
3431 unsigned int extra_row = 0, extra_col = 0;
3432 unsigned int min_reqd_height, min_reqd_width;
3435 assert(pipe->stream);
3438 IA_CSS_ENTER_PRIVATE("pipe = %p effective_wd = %u effective_ht = %u",
3439 pipe, pipe->config.input_effective_res.width,
3440 pipe->config.input_effective_res.height);
3442 input_res = &pipe->stream->config.input_config.input_res;
3444 effective_res = &pipe->stream->config.input_config.effective_res;
3446 effective_res = &pipe->config.input_effective_res;
3449 get_pipe_extra_pixel(pipe, &extra_row, &extra_col);
3451 in_frame->raw_bayer_order = pipe->stream->config.input_config.bayer_order;
3453 min_reqd_height = effective_res->height + extra_row;
3454 min_reqd_width = effective_res->width + extra_col;
3456 if (input_res->height > min_reqd_height) {
3457 row = (input_res->height - min_reqd_height) / 2;
3460 if (input_res->width > min_reqd_width) {
3461 column = (input_res->width - min_reqd_width) / 2;
3467 * 1. Require the special support for RAW10 packed mode.
3468 * 2. Require the special support for the online use cases.
3471 /* ISP expects GRBG bayer order, we skip one line and/or one row
3472 * to correct in case the input bayer order is different.
3474 column += get_crop_columns_for_bayer_order(&pipe->stream->config);
3475 row += get_crop_lines_for_bayer_order(&pipe->stream->config);
3477 in_frame->crop_info.start_column = column;
3478 in_frame->crop_info.start_line = row;
3480 IA_CSS_LEAVE_PRIVATE("void start_col: %u start_row: %u", column, row);
3486 static enum ia_css_err
3487 init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe,
3488 struct ia_css_frame *frame, enum ia_css_frame_format format) {
3489 struct ia_css_frame *in_frame;
3490 enum ia_css_err err = IA_CSS_SUCCESS;
3491 unsigned int thread_id;
3492 enum sh_css_queue_id queue_id;
3497 in_frame->info.format = format;
3499 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3500 if (format == IA_CSS_FRAME_FORMAT_RAW)
3501 in_frame->info.format = (pipe->stream->config.pack_raw_pixels) ?
3502 IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW;
3505 in_frame->info.res.width = pipe->stream->config.input_config.input_res.width;
3506 in_frame->info.res.height = pipe->stream->config.input_config.input_res.height;
3507 in_frame->info.raw_bit_depth =
3508 ia_css_pipe_util_pipe_input_format_bpp(pipe);
3509 ia_css_frame_info_set_width(&in_frame->info, pipe->stream->config.input_config.input_res.width, 0);
3510 in_frame->contiguous = false;
3511 in_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3512 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3513 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_INPUT_FRAME, thread_id, &queue_id);
3514 in_frame->dynamic_queue_id = queue_id;
3515 in_frame->buf_type = IA_CSS_BUFFER_TYPE_INPUT_FRAME;
3516 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3517 ia_css_get_crop_offsets(pipe, &in_frame->info);
3519 err = ia_css_frame_init_planes(in_frame);
3521 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
3522 "init_in_frameinfo_memory_defaults() bayer_order = %d:\n", in_frame->info.raw_bayer_order);
3527 static enum ia_css_err
3528 init_out_frameinfo_defaults(struct ia_css_pipe *pipe,
3529 struct ia_css_frame *out_frame, unsigned int idx) {
3530 enum ia_css_err err = IA_CSS_SUCCESS;
3531 unsigned int thread_id;
3532 enum sh_css_queue_id queue_id;
3536 sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, idx);
3537 out_frame->contiguous = false;
3538 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
3539 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
3540 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, thread_id, &queue_id);
3541 out_frame->dynamic_queue_id = queue_id;
3542 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx;
3543 err = ia_css_frame_init_planes(out_frame);
3548 /* Create stages for video pipe */
3549 static enum ia_css_err create_host_video_pipeline(struct ia_css_pipe *pipe)
3551 struct ia_css_pipeline_stage_desc stage_desc;
3552 struct ia_css_binary *copy_binary, *video_binary,
3553 *yuv_scaler_binary, *vf_pp_binary;
3554 struct ia_css_pipeline_stage *copy_stage = NULL;
3555 struct ia_css_pipeline_stage *video_stage = NULL;
3556 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
3557 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3558 struct ia_css_pipeline *me;
3559 struct ia_css_frame *in_frame = NULL;
3560 struct ia_css_frame *out_frame;
3561 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3562 struct ia_css_frame *vf_frame = NULL;
3563 enum ia_css_err err = IA_CSS_SUCCESS;
3564 bool need_copy = false;
3565 bool need_vf_pp = false;
3566 bool need_yuv_pp = false;
3567 unsigned int num_output_pins;
3568 bool need_in_frameinfo_memory = false;
3570 unsigned int i, num_yuv_scaler;
3571 bool *is_output_stage = NULL;
3573 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3574 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
3575 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3576 return IA_CSS_ERR_INVALID_ARGUMENTS;
3578 ia_css_pipe_util_create_output_frames(out_frames);
3579 out_frame = &pipe->out_frame_struct;
3581 /* pipeline already created as part of create_host_pipeline_structure */
3582 me = &pipe->pipeline;
3583 ia_css_pipeline_clean(me);
3585 me->dvs_frame_delay = pipe->dvs_frame_delay;
3587 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3588 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3589 * except for the following: online or continuous
3591 need_in_frameinfo_memory = !(pipe->stream->config.online ||
3592 pipe->stream->config.continuous);
3594 /* Construct in_frame info (only in case we have dynamic input */
3595 need_in_frameinfo_memory = pipe->stream->config.mode ==
3596 IA_CSS_INPUT_MODE_MEMORY;
3599 /* Construct in_frame info (only in case we have dynamic input */
3600 if (need_in_frameinfo_memory) {
3601 in_frame = &pipe->in_frame_struct;
3602 err = init_in_frameinfo_memory_defaults(pipe, in_frame,
3603 IA_CSS_FRAME_FORMAT_RAW);
3604 if (err != IA_CSS_SUCCESS)
3608 out_frame->data = 0;
3609 err = init_out_frameinfo_defaults(pipe, out_frame, 0);
3610 if (err != IA_CSS_SUCCESS)
3613 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
3614 vf_frame = &pipe->vf_frame_struct;
3616 err = init_vf_frameinfo_defaults(pipe, vf_frame, 0);
3617 if (err != IA_CSS_SUCCESS)
3621 copy_binary = &pipe->pipe_settings.video.copy_binary;
3622 video_binary = &pipe->pipe_settings.video.video_binary;
3623 vf_pp_binary = &pipe->pipe_settings.video.vf_pp_binary;
3624 num_output_pins = video_binary->info->num_output_pins;
3626 yuv_scaler_binary = pipe->pipe_settings.video.yuv_scaler_binary;
3627 num_yuv_scaler = pipe->pipe_settings.video.num_yuv_scaler;
3628 is_output_stage = pipe->pipe_settings.video.is_output_stage;
3630 need_copy = (copy_binary && copy_binary->info);
3631 need_vf_pp = (vf_pp_binary && vf_pp_binary->info);
3632 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
3635 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3636 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3637 out_frames, NULL, NULL);
3638 err = ia_css_pipeline_create_and_add_stage(me,
3641 if (err != IA_CSS_SUCCESS)
3643 in_frame = me->stages->args.out_frame[0];
3644 } else if (pipe->stream->config.continuous) {
3645 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3646 /* When continuous is enabled, configure in_frame with the
3647 * last pipe, which is the copy pipe.
3649 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3651 in_frame = pipe->continuous_frames[0];
3655 ia_css_pipe_util_set_output_frames(out_frames, 0,
3656 need_yuv_pp ? NULL : out_frame);
3658 /* when the video binary supports a second output pin,
3659 it can directly produce the vf_frame. */
3661 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3662 out_frames, in_frame, NULL);
3664 ia_css_pipe_get_generic_stage_desc(&stage_desc, video_binary,
3665 out_frames, in_frame, vf_frame);
3667 err = ia_css_pipeline_create_and_add_stage(me,
3670 if (err != IA_CSS_SUCCESS)
3673 /* If we use copy iso video, the input must be yuv iso raw */
3675 video_stage->args.copy_vf =
3676 video_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3677 video_stage->args.copy_output = video_stage->args.copy_vf;
3680 /* when the video binary supports only 1 output pin, vf_pp is needed to
3681 produce the vf_frame.*/
3682 if (need_vf_pp && video_stage) {
3683 in_frame = video_stage->args.out_vf_frame;
3684 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
3686 if (err != IA_CSS_SUCCESS)
3691 for (frm = 0; frm < NUM_TNR_FRAMES; frm++) {
3692 video_stage->args.tnr_frames[frm] =
3693 pipe->pipe_settings.video.tnr_frames[frm];
3695 for (frm = 0; frm < MAX_NUM_VIDEO_DELAY_FRAMES; frm++) {
3696 video_stage->args.delay_frames[frm] =
3697 pipe->pipe_settings.video.delay_frames[frm];
3701 /* Append Extension on Video out, if enabled */
3702 if (!need_vf_pp && video_stage && pipe->config.acc_extension &&
3703 (pipe->config.acc_extension->info.isp.type == IA_CSS_ACC_OUTPUT)) {
3704 struct ia_css_frame *out = NULL;
3705 struct ia_css_frame *in = NULL;
3707 if ((pipe->config.acc_extension->info.isp.sp.enable.output) &&
3708 (pipe->config.acc_extension->info.isp.sp.enable.in_frame) &&
3709 (pipe->config.acc_extension->info.isp.sp.enable.out_frame)) {
3710 /* In/Out Frame mapping to support output frame extension.*/
3711 out = video_stage->args.out_frame[0];
3712 err = ia_css_frame_allocate_from_info(&in, &pipe->output_info[0]);
3713 if (err != IA_CSS_SUCCESS)
3715 video_stage->args.out_frame[0] = in;
3718 err = add_firmwares(me, video_binary, pipe->output_stage,
3719 last_output_firmware(pipe->output_stage),
3720 IA_CSS_BINARY_MODE_VIDEO,
3721 in, out, NULL, &video_stage, NULL);
3722 if (err != IA_CSS_SUCCESS)
3726 if (need_yuv_pp && video_stage) {
3727 struct ia_css_frame *tmp_in_frame = video_stage->args.out_frame[0];
3728 struct ia_css_frame *tmp_out_frame = NULL;
3730 for (i = 0; i < num_yuv_scaler; i++) {
3731 if (is_output_stage[i] == true) {
3732 tmp_out_frame = out_frame;
3734 tmp_out_frame = NULL;
3736 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
3738 &yuv_scaler_binary[i],
3741 if (err != IA_CSS_SUCCESS) {
3742 IA_CSS_LEAVE_ERR_PRIVATE(err);
3745 /* we use output port 1 as internal output port */
3746 if (yuv_scaler_stage)
3747 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
3751 pipe->pipeline.acquire_isp_each_stage = false;
3752 ia_css_pipeline_finalize_stages(&pipe->pipeline,
3753 pipe->stream->config.continuous);
3756 IA_CSS_LEAVE_ERR_PRIVATE(err);
3760 static enum ia_css_err
3761 create_host_acc_pipeline(struct ia_css_pipe *pipe) {
3762 enum ia_css_err err = IA_CSS_SUCCESS;
3763 const struct ia_css_fw_info *fw;
3766 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3767 if ((!pipe) || (!pipe->stream))
3769 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3770 return IA_CSS_ERR_INVALID_ARGUMENTS;
3773 pipe->pipeline.num_execs = pipe->config.acc_num_execs;
3774 /* Reset pipe_qos_config to default disable all QOS extension stages */
3775 if (pipe->config.acc_extension)
3776 pipe->pipeline.pipe_qos_config = 0;
3778 fw = pipe->vf_stage;
3779 for (i = 0; fw; fw = fw->next)
3781 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3782 if (err != IA_CSS_SUCCESS)
3786 for (i = 0; i < pipe->config.num_acc_stages; i++)
3788 struct ia_css_fw_info *fw = pipe->config.acc_stages[i];
3790 err = sh_css_pipeline_add_acc_stage(&pipe->pipeline, fw);
3791 if (err != IA_CSS_SUCCESS)
3795 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3798 IA_CSS_LEAVE_ERR_PRIVATE(err);
3802 /* Create stages for preview */
3803 static enum ia_css_err
3804 create_host_preview_pipeline(struct ia_css_pipe *pipe) {
3805 struct ia_css_pipeline_stage *copy_stage = NULL;
3806 struct ia_css_pipeline_stage *preview_stage = NULL;
3807 struct ia_css_pipeline_stage *vf_pp_stage = NULL;
3808 struct ia_css_pipeline_stage_desc stage_desc;
3809 struct ia_css_pipeline *me = NULL;
3810 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3811 struct ia_css_frame *in_frame = NULL;
3812 enum ia_css_err err = IA_CSS_SUCCESS;
3813 struct ia_css_frame *out_frame;
3814 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
3815 bool need_in_frameinfo_memory = false;
3816 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3817 bool sensor = false;
3818 bool buffered_sensor = false;
3819 bool online = false;
3820 bool continuous = false;
3823 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3824 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3826 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3827 return IA_CSS_ERR_INVALID_ARGUMENTS;
3830 ia_css_pipe_util_create_output_frames(out_frames);
3831 /* pipeline already created as part of create_host_pipeline_structure */
3832 me = &pipe->pipeline;
3833 ia_css_pipeline_clean(me);
3835 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3836 /* When the input system is 2401, always enable 'in_frameinfo_memory'
3837 * except for the following:
3838 * - Direct Sensor Mode Online Preview
3839 * - Buffered Sensor Mode Online Preview
3840 * - Direct Sensor Mode Continuous Preview
3841 * - Buffered Sensor Mode Continuous Preview
3843 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
3844 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
3845 online = pipe->stream->config.online;
3846 continuous = pipe->stream->config.continuous;
3847 need_in_frameinfo_memory =
3848 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
3850 /* Construct in_frame info (only in case we have dynamic input */
3851 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
3853 if (need_in_frameinfo_memory)
3855 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
3856 IA_CSS_FRAME_FORMAT_RAW);
3857 if (err != IA_CSS_SUCCESS)
3860 in_frame = &me->in_frame;
3866 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
3867 if (err != IA_CSS_SUCCESS)
3869 out_frame = &me->out_frame[0];
3871 copy_binary = &pipe->pipe_settings.preview.copy_binary;
3872 preview_binary = &pipe->pipe_settings.preview.preview_binary;
3873 if (pipe->pipe_settings.preview.vf_pp_binary.info)
3874 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
3876 if (pipe->pipe_settings.preview.copy_binary.info)
3878 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3879 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
3880 out_frames, NULL, NULL);
3881 err = ia_css_pipeline_create_and_add_stage(me,
3884 if (err != IA_CSS_SUCCESS)
3886 in_frame = me->stages->args.out_frame[0];
3891 } else if (pipe->stream->config.continuous)
3894 #ifdef USE_INPUT_SYSTEM_VERSION_2401
3895 /* When continuous is enabled, configure in_frame with the
3896 * last pipe, which is the copy pipe.
3898 if (continuous || !online) {
3899 in_frame = pipe->stream->last_pipe->continuous_frames[0];
3902 in_frame = pipe->continuous_frames[0];
3908 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
3909 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3910 out_frames, in_frame, NULL);
3913 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
3914 ia_css_pipe_get_generic_stage_desc(&stage_desc, preview_binary,
3915 out_frames, in_frame, NULL);
3917 err = ia_css_pipeline_create_and_add_stage(me,
3920 if (err != IA_CSS_SUCCESS)
3922 /* If we use copy iso preview, the input must be yuv iso raw */
3923 preview_stage->args.copy_vf =
3924 preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY;
3925 preview_stage->args.copy_output = !preview_stage->args.copy_vf;
3926 if (preview_stage->args.copy_vf && !preview_stage->args.out_vf_frame)
3928 /* in case of copy, use the vf frame as output frame */
3929 preview_stage->args.out_vf_frame =
3930 preview_stage->args.out_frame[0];
3934 if (preview_binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_COPY)
3935 in_frame = preview_stage->args.out_vf_frame;
3937 in_frame = preview_stage->args.out_frame[0];
3938 err = add_vf_pp_stage(pipe, in_frame, out_frame, vf_pp_binary,
3940 if (err != IA_CSS_SUCCESS)
3944 pipe->pipeline.acquire_isp_each_stage = false;
3945 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
3948 IA_CSS_LEAVE_ERR_PRIVATE(err);
3952 static void send_raw_frames(struct ia_css_pipe *pipe)
3954 if (pipe->stream->config.continuous) {
3957 sh_css_update_host2sp_cont_num_raw_frames
3958 (pipe->stream->config.init_num_cont_raw_buf, true);
3959 sh_css_update_host2sp_cont_num_raw_frames
3960 (pipe->stream->config.target_num_cont_raw_buf, false);
3962 /* Hand-over all the SP-internal buffers */
3963 for (i = 0; i < pipe->stream->config.init_num_cont_raw_buf; i++) {
3964 sh_css_update_host2sp_offline_frame(i,
3965 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
3972 static enum ia_css_err
3973 preview_start(struct ia_css_pipe *pipe) {
3974 struct ia_css_pipeline *me;
3975 struct ia_css_binary *copy_binary, *preview_binary, *vf_pp_binary = NULL;
3976 enum ia_css_err err = IA_CSS_SUCCESS;
3977 struct ia_css_pipe *copy_pipe, *capture_pipe;
3978 struct ia_css_pipe *acc_pipe;
3979 enum sh_css_pipe_config_override copy_ovrd;
3980 enum ia_css_input_mode preview_pipe_input_mode;
3981 const struct ia_css_coordinate *coord = NULL;
3982 const struct ia_css_isp_parameters *params = NULL;
3984 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
3985 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW))
3987 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
3988 return IA_CSS_ERR_INVALID_ARGUMENTS;
3991 me = &pipe->pipeline;
3993 preview_pipe_input_mode = pipe->stream->config.mode;
3995 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
3996 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
3997 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
3999 copy_binary = &pipe->pipe_settings.preview.copy_binary;
4000 preview_binary = &pipe->pipe_settings.preview.preview_binary;
4001 if (pipe->pipe_settings.preview.vf_pp_binary.info)
4002 vf_pp_binary = &pipe->pipe_settings.preview.vf_pp_binary;
4004 sh_css_metrics_start_frame();
4006 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
4007 /* multi stream video needs mipi buffers */
4008 err = send_mipi_frames(pipe);
4009 if (err != IA_CSS_SUCCESS) {
4010 IA_CSS_LEAVE_ERR_PRIVATE(err);
4014 send_raw_frames(pipe);
4017 unsigned int thread_id;
4019 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4020 copy_ovrd = 1 << thread_id;
4022 if (pipe->stream->cont_capt)
4024 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
4026 copy_ovrd |= 1 << thread_id;
4030 if (atomisp_hw_is_isp2401) {
4031 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
4032 params = pipe->stream->isp_params_configs;
4035 /* Construct and load the copy pipe */
4036 if (pipe->stream->config.continuous)
4038 sh_css_sp_init_pipeline(©_pipe->pipeline,
4039 IA_CSS_PIPE_ID_COPY,
4040 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
4042 pipe->stream->config.pixels_per_clock == 2, false,
4043 false, pipe->required_bds_factor,
4045 pipe->stream->config.mode,
4046 &pipe->stream->config.metadata_config,
4047 &pipe->stream->info.metadata_info,
4048 #if !defined(HAS_NO_INPUT_SYSTEM)
4049 pipe->stream->config.source.port.port,
4054 /* make the preview pipe start with mem mode input, copy handles
4056 preview_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
4059 /* Construct and load the capture pipe */
4060 if (pipe->stream->cont_capt)
4062 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
4063 IA_CSS_PIPE_ID_CAPTURE,
4064 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
4065 capture_pipe->config.default_capture_config.enable_xnr != 0,
4066 capture_pipe->stream->config.pixels_per_clock == 2,
4067 true, /* continuous */
4068 false, /* offline */
4069 capture_pipe->required_bds_factor,
4071 IA_CSS_INPUT_MODE_MEMORY,
4072 &pipe->stream->config.metadata_config,
4073 &pipe->stream->info.metadata_info,
4074 #if !defined(HAS_NO_INPUT_SYSTEM)
4075 (enum mipi_port_id)0,
4083 sh_css_sp_init_pipeline(&acc_pipe->pipeline,
4085 (uint8_t)ia_css_pipe_get_pipe_num(acc_pipe),
4087 pipe->stream->config.pixels_per_clock == 2,
4088 false, /* continuous */
4089 false, /* offline */
4090 pipe->required_bds_factor,
4092 IA_CSS_INPUT_MODE_MEMORY,
4095 #if !defined(HAS_NO_INPUT_SYSTEM)
4096 (enum mipi_port_id)0,
4102 start_pipe(pipe, copy_ovrd, preview_pipe_input_mode);
4104 IA_CSS_LEAVE_ERR_PRIVATE(err);
4109 ia_css_pipe_enqueue_buffer(struct ia_css_pipe *pipe,
4110 const struct ia_css_buffer *buffer) {
4111 enum ia_css_err return_err = IA_CSS_SUCCESS;
4112 unsigned int thread_id;
4113 enum sh_css_queue_id queue_id;
4114 struct ia_css_pipeline *pipeline;
4115 struct ia_css_pipeline_stage *stage;
4116 struct ia_css_rmgr_vbuf_handle p_vbuf;
4117 struct ia_css_rmgr_vbuf_handle *h_vbuf;
4118 struct sh_css_hmm_buffer ddr_buffer;
4119 enum ia_css_buffer_type buf_type;
4120 enum ia_css_pipe_id pipe_id;
4123 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4125 if ((!pipe) || (!buffer))
4127 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4128 return IA_CSS_ERR_INVALID_ARGUMENTS;
4131 buf_type = buffer->type;
4132 /* following code will be enabled when IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME
4135 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4137 bool found_pipe = false;
4139 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4140 if ((buffer->data.frame->info.res.width == pipe->output_info[i].res.width) &&
4141 (buffer->data.frame->info.res.height == pipe->output_info[i].res.height)) {
4148 return IA_CSS_ERR_INVALID_ARGUMENTS;
4150 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4152 bool found_pipe = false;
4154 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
4155 if ((buffer->data.frame->info.res.width == pipe->vf_output_info[i].res.width) &&
4156 (buffer->data.frame->info.res.height == pipe->vf_output_info[i].res.height)) {
4163 return IA_CSS_ERR_INVALID_ARGUMENTS;
4166 pipe_id = pipe->mode;
4168 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4170 assert(pipe_id < IA_CSS_PIPE_ID_NUM);
4171 assert(buf_type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE);
4172 if ((buf_type == IA_CSS_BUFFER_TYPE_INVALID) ||
4173 (buf_type >= IA_CSS_NUM_DYNAMIC_BUFFER_TYPE) ||
4174 (pipe_id >= IA_CSS_PIPE_ID_NUM))
4176 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4177 return IA_CSS_ERR_INTERNAL_ERROR;
4180 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4183 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4184 return IA_CSS_ERR_INVALID_ARGUMENTS;
4187 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4190 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4191 return IA_CSS_ERR_INVALID_ARGUMENTS;
4194 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4196 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4197 return IA_CSS_ERR_INVALID_ARGUMENTS;
4200 if (!sh_css_sp_is_running())
4202 IA_CSS_LOG("SP is not running!");
4203 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4204 /* SP is not running. The queues are not valid */
4205 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4208 pipeline = &pipe->pipeline;
4211 pipe_id == IA_CSS_PIPE_ID_COPY ||
4212 pipe_id == IA_CSS_PIPE_ID_ACC);
4214 assert(sizeof(NULL) <= sizeof(ddr_buffer.kernel_ptr));
4215 ddr_buffer.kernel_ptr = HOST_ADDRESS(NULL);
4216 ddr_buffer.cookie_ptr = buffer->driver_cookie;
4217 ddr_buffer.timing_data = buffer->timing_data;
4219 if (buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4221 if (!buffer->data.stats_3a) {
4222 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4223 return IA_CSS_ERR_INVALID_ARGUMENTS;
4225 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_3a);
4226 ddr_buffer.payload.s3a = *buffer->data.stats_3a;
4227 } else if (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4229 if (!buffer->data.stats_dvs) {
4230 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4231 return IA_CSS_ERR_INVALID_ARGUMENTS;
4233 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.stats_dvs);
4234 ddr_buffer.payload.dis = *buffer->data.stats_dvs;
4235 } else if (buf_type == IA_CSS_BUFFER_TYPE_METADATA)
4237 if (!buffer->data.metadata) {
4238 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4239 return IA_CSS_ERR_INVALID_ARGUMENTS;
4241 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.metadata);
4242 ddr_buffer.payload.metadata = *buffer->data.metadata;
4243 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4244 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4245 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4246 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4247 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME))
4249 if (!buffer->data.frame) {
4250 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4251 return IA_CSS_ERR_INVALID_ARGUMENTS;
4253 ddr_buffer.kernel_ptr = HOST_ADDRESS(buffer->data.frame);
4254 ddr_buffer.payload.frame.frame_data = buffer->data.frame->data;
4255 ddr_buffer.payload.frame.flashed = 0;
4257 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4258 "ia_css_pipe_enqueue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4259 buf_type, buffer->data.frame->data);
4261 #if CONFIG_ON_FRAME_ENQUEUE()
4262 return_err = set_config_on_frame_enqueue(
4263 &buffer->data.frame->info,
4264 &ddr_buffer.payload.frame);
4265 if (return_err != IA_CSS_SUCCESS) {
4266 IA_CSS_LEAVE_ERR(return_err);
4272 /* start of test for using rmgr for acq/rel memory */
4275 p_vbuf.size = sizeof(struct sh_css_hmm_buffer);
4277 /* TODO: change next to correct pool for optimization */
4278 ia_css_rmgr_acq_vbuf(hmm_buffer_pool, &h_vbuf);
4281 assert(h_vbuf->vptr != 0x0);
4283 if ((!h_vbuf) || (h_vbuf->vptr == 0x0))
4285 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4286 return IA_CSS_ERR_INTERNAL_ERROR;
4289 hmm_store(h_vbuf->vptr,
4290 (void *)(&ddr_buffer),
4291 sizeof(struct sh_css_hmm_buffer));
4292 if ((buf_type == IA_CSS_BUFFER_TYPE_3A_STATISTICS)
4293 || (buf_type == IA_CSS_BUFFER_TYPE_DIS_STATISTICS)
4294 || (buf_type == IA_CSS_BUFFER_TYPE_LACE_STATISTICS))
4297 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4298 IA_CSS_LOG("pipeline is empty!");
4299 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4300 return IA_CSS_ERR_INTERNAL_ERROR;
4303 for (stage = pipeline->stages; stage; stage = stage->next) {
4304 /* The SP will read the params
4305 after it got empty 3a and dis */
4306 if (STATS_ENABLED(stage)) {
4307 /* there is a stage that needs it */
4308 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4310 (uint32_t)h_vbuf->vptr);
4313 } else if ((buf_type == IA_CSS_BUFFER_TYPE_INPUT_FRAME)
4314 || (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)
4315 || (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)
4316 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME)
4317 || (buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME)
4318 || (buf_type == IA_CSS_BUFFER_TYPE_METADATA))
4320 return_err = ia_css_bufq_enqueue_buffer(thread_id,
4322 (uint32_t)h_vbuf->vptr);
4323 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4324 if ((return_err == IA_CSS_SUCCESS) &&
4325 (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME)) {
4326 IA_CSS_LOG("pfp: enqueued OF %d to q %d thread %d",
4327 ddr_buffer.payload.frame.frame_data,
4328 queue_id, thread_id);
4333 if (return_err == IA_CSS_SUCCESS)
4335 if (sh_css_hmm_buffer_record_acquire(
4337 HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4338 IA_CSS_LOG("send vbuf=%p", h_vbuf);
4340 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4341 IA_CSS_ERROR("hmm_buffer_record[]: no available slots\n");
4346 * Tell the SP which queues are not empty,
4347 * by sending the software event.
4349 if (return_err == IA_CSS_SUCCESS)
4351 if (!sh_css_sp_is_running()) {
4352 /* SP is not running. The queues are not valid */
4353 IA_CSS_LOG("SP is not running!");
4354 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4355 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4357 return_err = ia_css_bufq_enqueue_psys_event(
4358 IA_CSS_PSYS_SW_EVENT_BUFFER_ENQUEUED,
4364 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &h_vbuf);
4365 IA_CSS_ERROR("buffer not enqueued");
4368 IA_CSS_LEAVE("return value = %d", return_err);
4374 * TODO: Free up the hmm memory space.
4377 ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe,
4378 struct ia_css_buffer *buffer) {
4379 enum ia_css_err return_err;
4380 enum sh_css_queue_id queue_id;
4381 ia_css_ptr ddr_buffer_addr = (ia_css_ptr)0;
4382 struct sh_css_hmm_buffer ddr_buffer;
4383 enum ia_css_buffer_type buf_type;
4384 enum ia_css_pipe_id pipe_id;
4385 unsigned int thread_id;
4386 hrt_address kernel_ptr = 0;
4389 IA_CSS_ENTER("pipe=%p, buffer=%p", pipe, buffer);
4391 if ((!pipe) || (!buffer))
4393 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4394 return IA_CSS_ERR_INVALID_ARGUMENTS;
4397 pipe_id = pipe->mode;
4399 buf_type = buffer->type;
4401 IA_CSS_LOG("pipe_id=%d, buf_type=%d", pipe_id, buf_type);
4403 ddr_buffer.kernel_ptr = 0;
4405 ret_err = ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4408 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4409 return IA_CSS_ERR_INVALID_ARGUMENTS;
4412 ret_err = ia_css_query_internal_queue_id(buf_type, thread_id, &queue_id);
4415 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4416 return IA_CSS_ERR_INVALID_ARGUMENTS;
4419 if ((queue_id <= SH_CSS_INVALID_QUEUE_ID) || (queue_id >= SH_CSS_MAX_NUM_QUEUES))
4421 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4422 return IA_CSS_ERR_INVALID_ARGUMENTS;
4425 if (!sh_css_sp_is_running())
4427 IA_CSS_LOG("SP is not running!");
4428 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4429 /* SP is not running. The queues are not valid */
4430 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4433 return_err = ia_css_bufq_dequeue_buffer(queue_id,
4434 (uint32_t *)&ddr_buffer_addr);
4436 if (return_err == IA_CSS_SUCCESS)
4438 struct ia_css_frame *frame;
4439 struct sh_css_hmm_buffer_record *hmm_buffer_record = NULL;
4441 IA_CSS_LOG("receive vbuf=%x", (int)ddr_buffer_addr);
4443 /* Validate the ddr_buffer_addr and buf_type */
4444 hmm_buffer_record = sh_css_hmm_buffer_record_validate(
4445 ddr_buffer_addr, buf_type);
4446 if (hmm_buffer_record) {
4447 /* valid hmm_buffer_record found. Save the kernel_ptr
4448 * for validation after performing hmm_load. The
4449 * vbuf handle and buffer_record can be released.
4451 kernel_ptr = hmm_buffer_record->kernel_ptr;
4452 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &hmm_buffer_record->h_vbuf);
4453 sh_css_hmm_buffer_record_reset(hmm_buffer_record);
4455 IA_CSS_ERROR("hmm_buffer_record not found (0x%x) buf_type(%d)",
4456 ddr_buffer_addr, buf_type);
4457 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4458 return IA_CSS_ERR_INTERNAL_ERROR;
4461 hmm_load(ddr_buffer_addr,
4463 sizeof(struct sh_css_hmm_buffer));
4465 /* if the kernel_ptr is 0 or an invalid, return an error.
4466 * do not access the buffer via the kernal_ptr.
4468 if ((ddr_buffer.kernel_ptr == 0) ||
4469 (kernel_ptr != HOST_ADDRESS(ddr_buffer.kernel_ptr))) {
4470 IA_CSS_ERROR("kernel_ptr invalid");
4471 IA_CSS_ERROR("expected: (0x%llx)", (u64)kernel_ptr);
4472 IA_CSS_ERROR("actual: (0x%llx)", (u64)HOST_ADDRESS(ddr_buffer.kernel_ptr));
4473 IA_CSS_ERROR("buf_type: %d\n", buf_type);
4474 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INTERNAL_ERROR);
4475 return IA_CSS_ERR_INTERNAL_ERROR;
4478 if (ddr_buffer.kernel_ptr != 0) {
4479 /* buffer->exp_id : all instances to be removed later once the driver change
4480 * is completed. See patch #5758 for reference */
4482 buffer->driver_cookie = ddr_buffer.cookie_ptr;
4483 buffer->timing_data = ddr_buffer.timing_data;
4485 if ((buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) ||
4486 (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME)) {
4487 buffer->isys_eof_clock_tick.ticks = ddr_buffer.isys_eof_clock_tick;
4491 case IA_CSS_BUFFER_TYPE_INPUT_FRAME:
4492 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME:
4493 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME:
4494 if ((pipe) && (pipe->stop_requested == true)) {
4495 #if defined(USE_INPUT_SYSTEM_VERSION_2)
4496 /* free mipi frames only for old input system
4497 * for 2401 it is done in ia_css_stream_destroy call
4499 return_err = free_mipi_frames(pipe);
4500 if (return_err != IA_CSS_SUCCESS) {
4501 IA_CSS_LOG("free_mipi_frames() failed");
4502 IA_CSS_LEAVE_ERR(return_err);
4506 pipe->stop_requested = false;
4508 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME:
4509 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME:
4510 frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4511 buffer->data.frame = frame;
4512 buffer->exp_id = ddr_buffer.payload.frame.exp_id;
4513 frame->exp_id = ddr_buffer.payload.frame.exp_id;
4514 frame->isp_config_id = ddr_buffer.payload.frame.isp_parameters_id;
4515 if (ddr_buffer.payload.frame.flashed == 1)
4516 frame->flash_state =
4517 IA_CSS_FRAME_FLASH_STATE_PARTIAL;
4518 if (ddr_buffer.payload.frame.flashed == 2)
4519 frame->flash_state =
4520 IA_CSS_FRAME_FLASH_STATE_FULL;
4521 frame->valid = pipe->num_invalid_frames == 0;
4523 pipe->num_invalid_frames--;
4525 if (frame->info.format == IA_CSS_FRAME_FORMAT_BINARY_8) {
4526 #ifdef USE_INPUT_SYSTEM_VERSION_2401
4527 frame->planes.binary.size = frame->data_bytes;
4529 frame->planes.binary.size =
4530 sh_css_sp_get_binary_copy_size();
4533 #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS)
4534 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) {
4535 IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d",
4536 frame->data, frame->isp_config_id, thread_id);
4540 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
4541 "ia_css_pipe_dequeue_buffer() buf_type=%d, data(DDR address)=0x%x\n",
4542 buf_type, buffer->data.frame->data);
4545 case IA_CSS_BUFFER_TYPE_3A_STATISTICS:
4546 buffer->data.stats_3a =
4547 (struct ia_css_isp_3a_statistics *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4548 buffer->exp_id = ddr_buffer.payload.s3a.exp_id;
4549 buffer->data.stats_3a->exp_id = ddr_buffer.payload.s3a.exp_id;
4550 buffer->data.stats_3a->isp_config_id = ddr_buffer.payload.s3a.isp_config_id;
4552 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS:
4553 buffer->data.stats_dvs =
4554 (struct ia_css_isp_dvs_statistics *)
4555 HOST_ADDRESS(ddr_buffer.kernel_ptr);
4556 buffer->exp_id = ddr_buffer.payload.dis.exp_id;
4557 buffer->data.stats_dvs->exp_id = ddr_buffer.payload.dis.exp_id;
4559 case IA_CSS_BUFFER_TYPE_LACE_STATISTICS:
4561 case IA_CSS_BUFFER_TYPE_METADATA:
4562 buffer->data.metadata =
4563 (struct ia_css_metadata *)HOST_ADDRESS(ddr_buffer.kernel_ptr);
4564 buffer->exp_id = ddr_buffer.payload.metadata.exp_id;
4565 buffer->data.metadata->exp_id = ddr_buffer.payload.metadata.exp_id;
4568 return_err = IA_CSS_ERR_INTERNAL_ERROR;
4575 * Tell the SP which queues are not full,
4576 * by sending the software event.
4578 if (return_err == IA_CSS_SUCCESS)
4580 if (!sh_css_sp_is_running()) {
4581 IA_CSS_LOG("SP is not running!");
4582 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4583 /* SP is not running. The queues are not valid */
4584 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4586 ia_css_bufq_enqueue_psys_event(
4587 IA_CSS_PSYS_SW_EVENT_BUFFER_DEQUEUED,
4592 IA_CSS_LEAVE("buffer=%p", buffer);
4598 * Cannot Move this to event module as it is of ia_css_event_type which is declared in ia_css.h
4599 * TODO: modify and move it if possible.
4601 * !!!IMPORTANT!!! KEEP THE FOLLOWING IN SYNC:
4602 * 1) "enum ia_css_event_type" (ia_css_event_public.h)
4603 * 2) "enum sh_css_sp_event_type" (sh_css_internal.h)
4604 * 3) "enum ia_css_event_type event_id_2_event_mask" (event_handler.sp.c)
4605 * 4) "enum ia_css_event_type convert_event_sp_to_host_domain" (sh_css.c)
4607 static enum ia_css_event_type convert_event_sp_to_host_domain[] = {
4608 IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE, /** Output frame ready. */
4609 IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE, /** Second output frame ready. */
4610 IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE, /** Viewfinder Output frame ready. */
4611 IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE, /** Second viewfinder Output frame ready. */
4612 IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE, /** Indication that 3A statistics are available. */
4613 IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE, /** Indication that DIS statistics are available. */
4614 IA_CSS_EVENT_TYPE_PIPELINE_DONE, /** Pipeline Done event, sent after last pipeline stage. */
4615 IA_CSS_EVENT_TYPE_FRAME_TAGGED, /** Frame tagged. */
4616 IA_CSS_EVENT_TYPE_INPUT_FRAME_DONE, /** Input frame ready. */
4617 IA_CSS_EVENT_TYPE_METADATA_DONE, /** Metadata ready. */
4618 IA_CSS_EVENT_TYPE_LACE_STATISTICS_DONE, /** Indication that LACE statistics are available. */
4619 IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE, /** Extension stage executed. */
4620 IA_CSS_EVENT_TYPE_TIMER, /** Timing measurement data. */
4621 IA_CSS_EVENT_TYPE_PORT_EOF, /** End Of Frame event, sent when in buffered sensor mode. */
4622 IA_CSS_EVENT_TYPE_FW_WARNING, /** Performance warning encountered by FW */
4623 IA_CSS_EVENT_TYPE_FW_ASSERT, /** Assertion hit by FW */
4624 0, /* error if sp passes SH_CSS_SP_EVENT_NR_OF_TYPES as a valid event. */
4628 ia_css_dequeue_event(struct ia_css_event *event) {
4629 return ia_css_dequeue_psys_event(event);
4633 ia_css_dequeue_psys_event(struct ia_css_event *event) {
4634 enum ia_css_pipe_id pipe_id = 0;
4635 u8 payload[4] = {0, 0, 0, 0};
4636 enum ia_css_err ret_err;
4639 * a) use generic decoding function , same as the one used by sp.
4640 * b) group decode and dequeue into eventQueue module
4642 * We skip the IA_CSS_ENTER logging call
4643 * to avoid flooding the logs when the host application
4646 return IA_CSS_ERR_INVALID_ARGUMENTS;
4648 if (!sh_css_sp_is_running())
4650 /* SP is not running. The queues are not valid */
4651 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4654 /* dequeue the event (if any) from the psys event queue */
4655 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4656 if (ret_err != IA_CSS_SUCCESS)
4659 IA_CSS_LOG("event dequeued from psys event queue");
4661 /* Tell the SP that we dequeued an event from the event queue. */
4662 ia_css_bufq_enqueue_psys_event(
4663 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4665 /* Events are decoded into 4 bytes of payload, the first byte
4666 * contains the sp event type. This is converted to a host enum.
4667 * TODO: can this enum conversion be eliminated */
4668 event->type = convert_event_sp_to_host_domain[payload[0]];
4669 /* Some sane default values since not all events use all fields. */
4671 event->port = MIPI_PORT0_ID;
4673 event->fw_warning = IA_CSS_FW_WARNING_NONE;
4674 event->fw_handle = 0;
4675 event->timer_data = 0;
4676 event->timer_code = 0;
4677 event->timer_subcode = 0;
4679 if (event->type == IA_CSS_EVENT_TYPE_TIMER)
4681 /* timer event ??? get the 2nd event and decode the data into the event struct */
4683 /* 1st event: LSB 16-bit timer data and code */
4684 event->timer_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4685 event->timer_code = payload[2];
4686 payload[0] = payload[1] = payload[2] = payload[3] = 0;
4687 ret_err = ia_css_bufq_dequeue_psys_event(payload);
4688 if (ret_err != IA_CSS_SUCCESS) {
4689 /* no 2nd event ??? an error */
4690 /* Putting IA_CSS_ERROR is resulting in failures in
4691 * Merrifield smoke testing */
4692 IA_CSS_WARNING("Timer: Error de-queuing the 2nd TIMER event!!!\n");
4695 ia_css_bufq_enqueue_psys_event(
4696 IA_CSS_PSYS_SW_EVENT_EVENT_DEQUEUED, 0, 0, 0);
4697 event->type = convert_event_sp_to_host_domain[payload[0]];
4699 if (event->type == IA_CSS_EVENT_TYPE_TIMER) {
4700 /* 2nd event data: MSB 16-bit timer and subcode */
4701 tmp_data = ((payload[1] & 0xFF) | ((payload[3] & 0xFF) << 8));
4702 event->timer_data |= (tmp_data << 16);
4703 event->timer_subcode = payload[2];
4705 /* It's a non timer event. So clear first half of the timer event data.
4706 * If the second part of the TIMER event is not received, we discard
4707 * the first half of the timer data and process the non timer event without
4708 * affecting the flow. So the non timer event falls through
4711 event->timer_data = 0;
4712 event->timer_code = 0;
4713 event->timer_subcode = 0;
4714 IA_CSS_ERROR("Missing 2nd timer event. Timer event discarded");
4717 if (event->type == IA_CSS_EVENT_TYPE_PORT_EOF)
4719 event->port = (enum mipi_port_id)payload[1];
4720 event->exp_id = payload[3];
4721 } else if (event->type == IA_CSS_EVENT_TYPE_FW_WARNING)
4723 event->fw_warning = (enum ia_css_fw_warning)payload[1];
4724 /* exp_id is only available in these warning types */
4725 if (event->fw_warning == IA_CSS_FW_WARNING_EXP_ID_LOCKED ||
4726 event->fw_warning == IA_CSS_FW_WARNING_TAG_EXP_ID_FAILED)
4727 event->exp_id = payload[3];
4728 } else if (event->type == IA_CSS_EVENT_TYPE_FW_ASSERT)
4730 event->fw_assert_module_id = payload[1]; /* module */
4731 event->fw_assert_line_no = (payload[2] << 8) + payload[3];
4732 /* payload[2] is line_no>>8, payload[3] is line_no&0xff */
4733 } else if (event->type != IA_CSS_EVENT_TYPE_TIMER)
4735 /* pipe related events.
4736 * payload[1] contains the pipe_num,
4737 * payload[2] contains the pipe_id. These are different. */
4738 event->pipe = find_pipe_by_num(payload[1]);
4739 pipe_id = (enum ia_css_pipe_id)payload[2];
4740 /* Check to see if pipe still exists */
4742 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4744 if (event->type == IA_CSS_EVENT_TYPE_FRAME_TAGGED) {
4745 /* find the capture pipe that goes with this */
4748 n = event->pipe->stream->num_pipes;
4749 for (i = 0; i < n; i++) {
4750 struct ia_css_pipe *p =
4751 event->pipe->stream->pipes[i];
4752 if (p->config.mode == IA_CSS_PIPE_MODE_CAPTURE) {
4757 event->exp_id = payload[3];
4759 if (event->type == IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE) {
4760 /* payload[3] contains the acc fw handle. */
4761 u32 stage_num = (uint32_t)payload[3];
4763 ret_err = ia_css_pipeline_get_fw_from_stage(
4764 &event->pipe->pipeline,
4767 if (ret_err != IA_CSS_SUCCESS) {
4768 IA_CSS_ERROR("Invalid stage num received for ACC event. stage_num:%u",
4776 IA_CSS_LEAVE("event_id=%d, pipe_id=%d", event->type, pipe_id);
4778 IA_CSS_LEAVE("event_id=%d", event->type);
4780 return IA_CSS_SUCCESS;
4784 ia_css_dequeue_isys_event(struct ia_css_event *event) {
4785 u8 payload[4] = {0, 0, 0, 0};
4786 enum ia_css_err err = IA_CSS_SUCCESS;
4788 /* We skip the IA_CSS_ENTER logging call
4789 * to avoid flooding the logs when the host application
4792 return IA_CSS_ERR_INVALID_ARGUMENTS;
4794 if (!sh_css_sp_is_running())
4796 /* SP is not running. The queues are not valid */
4797 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4800 err = ia_css_bufq_dequeue_isys_event(payload);
4801 if (err != IA_CSS_SUCCESS)
4804 IA_CSS_LOG("event dequeued from isys event queue");
4806 /* Update SP state to indicate that element was dequeued. */
4807 ia_css_bufq_enqueue_isys_event(IA_CSS_ISYS_SW_EVENT_EVENT_DEQUEUED);
4809 /* Fill return struct with appropriate info */
4810 event->type = IA_CSS_EVENT_TYPE_PORT_EOF;
4811 /* EOF events are associated with a CSI port, not with a pipe */
4813 event->port = payload[1];
4814 event->exp_id = payload[3];
4816 IA_CSS_LEAVE_ERR(err);
4821 acc_start(struct ia_css_pipe *pipe)
4824 assert(pipe->stream);
4826 start_pipe(pipe, SH_CSS_PIPE_CONFIG_OVRD_NO_OVRD,
4827 pipe->stream->config.mode);
4830 static enum ia_css_err
4831 sh_css_pipe_start(struct ia_css_stream *stream) {
4832 enum ia_css_err err = IA_CSS_SUCCESS;
4834 struct ia_css_pipe *pipe;
4835 enum ia_css_pipe_id pipe_id;
4836 unsigned int thread_id;
4838 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
4842 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4843 return IA_CSS_ERR_INVALID_ARGUMENTS;
4845 pipe = stream->last_pipe;
4848 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
4849 return IA_CSS_ERR_INVALID_ARGUMENTS;
4852 pipe_id = pipe->mode;
4854 if (stream->started == true)
4856 IA_CSS_WARNING("Cannot start stream that is already started");
4857 IA_CSS_LEAVE_ERR(err);
4861 pipe->stop_requested = false;
4865 case IA_CSS_PIPE_ID_PREVIEW:
4866 err = preview_start(pipe);
4868 case IA_CSS_PIPE_ID_VIDEO:
4869 err = video_start(pipe);
4871 case IA_CSS_PIPE_ID_CAPTURE:
4872 err = capture_start(pipe);
4874 case IA_CSS_PIPE_ID_YUVPP:
4875 err = yuvpp_start(pipe);
4877 case IA_CSS_PIPE_ID_ACC:
4881 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4883 /* DH regular multi pipe - not continuous mode: start the next pipes too */
4884 if (!stream->config.continuous)
4888 for (i = 1; i < stream->num_pipes && IA_CSS_SUCCESS == err ; i++) {
4889 switch (stream->pipes[i]->mode) {
4890 case IA_CSS_PIPE_ID_PREVIEW:
4891 stream->pipes[i]->stop_requested = false;
4892 err = preview_start(stream->pipes[i]);
4894 case IA_CSS_PIPE_ID_VIDEO:
4895 stream->pipes[i]->stop_requested = false;
4896 err = video_start(stream->pipes[i]);
4898 case IA_CSS_PIPE_ID_CAPTURE:
4899 stream->pipes[i]->stop_requested = false;
4900 err = capture_start(stream->pipes[i]);
4902 case IA_CSS_PIPE_ID_YUVPP:
4903 stream->pipes[i]->stop_requested = false;
4904 err = yuvpp_start(stream->pipes[i]);
4906 case IA_CSS_PIPE_ID_ACC:
4907 stream->pipes[i]->stop_requested = false;
4908 acc_start(stream->pipes[i]);
4911 err = IA_CSS_ERR_INVALID_ARGUMENTS;
4915 if (err != IA_CSS_SUCCESS)
4917 IA_CSS_LEAVE_ERR_PRIVATE(err);
4921 /* Force ISP parameter calculation after a mode change
4922 * Acceleration API examples pass NULL for stream but they
4923 * don't use ISP parameters anyway. So this should be okay.
4924 * The SP binary (jpeg) copy does not use any parameters.
4926 if (!copy_on_sp(pipe))
4928 sh_css_invalidate_params(stream);
4929 err = sh_css_param_update_isp_params(pipe,
4930 stream->isp_params_configs, true, NULL);
4931 if (err != IA_CSS_SUCCESS) {
4932 IA_CSS_LEAVE_ERR_PRIVATE(err);
4937 ia_css_debug_pipe_graph_dump_epilogue();
4939 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
4941 if (!sh_css_sp_is_running())
4943 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
4944 /* SP is not running. The queues are not valid */
4945 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
4947 ia_css_bufq_enqueue_psys_event(IA_CSS_PSYS_SW_EVENT_START_STREAM,
4948 (uint8_t)thread_id, 0, 0);
4950 /* DH regular multi pipe - not continuous mode: enqueue event to the next pipes too */
4951 if (!stream->config.continuous)
4955 for (i = 1; i < stream->num_pipes; i++) {
4956 ia_css_pipeline_get_sp_thread_id(
4957 ia_css_pipe_get_pipe_num(stream->pipes[i]),
4959 ia_css_bufq_enqueue_psys_event(
4960 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4961 (uint8_t)thread_id, 0, 0);
4965 /* in case of continuous capture mode, we also start capture thread and copy thread*/
4966 if (pipe->stream->config.continuous)
4968 struct ia_css_pipe *copy_pipe = NULL;
4970 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4971 copy_pipe = pipe->pipe_settings.preview.copy_pipe;
4972 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4973 copy_pipe = pipe->pipe_settings.video.copy_pipe;
4976 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4977 return IA_CSS_ERR_INTERNAL_ERROR;
4979 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(copy_pipe),
4981 /* by the time we reach here q is initialized and handle is available.*/
4982 ia_css_bufq_enqueue_psys_event(
4983 IA_CSS_PSYS_SW_EVENT_START_STREAM,
4984 (uint8_t)thread_id, 0, 0);
4986 if (pipe->stream->cont_capt)
4988 struct ia_css_pipe *capture_pipe = NULL;
4990 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
4991 capture_pipe = pipe->pipe_settings.preview.capture_pipe;
4992 else if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
4993 capture_pipe = pipe->pipe_settings.video.capture_pipe;
4995 if (!capture_pipe) {
4996 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
4997 return IA_CSS_ERR_INTERNAL_ERROR;
4999 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5001 /* by the time we reach here q is initialized and handle is available.*/
5002 ia_css_bufq_enqueue_psys_event(
5003 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5004 (uint8_t)thread_id, 0, 0);
5007 /* in case of PREVIEW mode, check whether QOS acc_pipe is available, then start the qos pipe */
5008 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5010 struct ia_css_pipe *acc_pipe = NULL;
5012 acc_pipe = pipe->pipe_settings.preview.acc_pipe;
5015 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(acc_pipe),
5017 /* by the time we reach here q is initialized and handle is available.*/
5018 ia_css_bufq_enqueue_psys_event(
5019 IA_CSS_PSYS_SW_EVENT_START_STREAM,
5020 (uint8_t)thread_id, 0, 0);
5024 stream->started = true;
5026 IA_CSS_LEAVE_ERR_PRIVATE(err);
5032 sh_css_enable_cont_capt(bool enable, bool stop_copy_preview)
5034 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5035 "sh_css_enable_cont_capt() enter: enable=%d\n", enable);
5036 //my_css.cont_capt = enable;
5037 my_css.stop_copy_preview = stop_copy_preview;
5041 sh_css_continuous_is_enabled(uint8_t pipe_num)
5043 struct ia_css_pipe *pipe;
5046 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5047 "sh_css_continuous_is_enabled() enter: pipe_num=%d\n", pipe_num);
5049 pipe = find_pipe_by_num(pipe_num);
5050 continuous = pipe && pipe->stream->config.continuous;
5051 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5052 "sh_css_continuous_is_enabled() leave: enable=%d\n",
5059 ia_css_stream_get_max_buffer_depth(struct ia_css_stream *stream,
5060 int *buffer_depth) {
5062 return IA_CSS_ERR_INVALID_ARGUMENTS;
5063 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_max_buffer_depth() enter: void\n");
5065 *buffer_depth = NUM_CONTINUOUS_FRAMES;
5066 return IA_CSS_SUCCESS;
5070 ia_css_stream_set_buffer_depth(struct ia_css_stream *stream, int buffer_depth) {
5071 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_set_buffer_depth() enter: num_frames=%d\n", buffer_depth);
5073 if (buffer_depth > NUM_CONTINUOUS_FRAMES || buffer_depth < 1)
5074 return IA_CSS_ERR_INVALID_ARGUMENTS;
5075 /* ok, value allowed */
5076 stream->config.target_num_cont_raw_buf = buffer_depth;
5077 /* TODO: check what to regarding initialization */
5078 return IA_CSS_SUCCESS;
5083 ia_css_stream_get_buffer_depth(struct ia_css_stream *stream,
5084 int *buffer_depth) {
5086 return IA_CSS_ERR_INVALID_ARGUMENTS;
5087 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_buffer_depth() enter: void\n");
5089 *buffer_depth = stream->config.target_num_cont_raw_buf;
5090 return IA_CSS_SUCCESS;
5094 * @brief Stop all "ia_css_pipe" instances in the target
5095 * "ia_css_stream" instance.
5097 * Refer to "Local prototypes" for more info.
5100 static enum ia_css_err
5101 sh_css_pipes_stop(struct ia_css_stream *stream)
5103 enum ia_css_err err = IA_CSS_SUCCESS;
5104 struct ia_css_pipe *main_pipe;
5105 enum ia_css_pipe_id main_pipe_id;
5111 IA_CSS_LOG("stream does NOT exist!");
5112 err = IA_CSS_ERR_INTERNAL_ERROR;
5116 main_pipe = stream->last_pipe;
5120 IA_CSS_LOG("main_pipe does NOT exist!");
5121 err = IA_CSS_ERR_INTERNAL_ERROR;
5125 main_pipe_id = main_pipe->mode;
5126 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5129 * Stop all "ia_css_pipe" instances in this target
5130 * "ia_css_stream" instance.
5132 for (i = 0; i < stream->num_pipes; i++)
5134 /* send the "stop" request to the "ia_css_pipe" instance */
5135 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5136 stream->pipes[i]->pipeline.pipe_id);
5137 err = ia_css_pipeline_request_stop(&stream->pipes[i]->pipeline);
5140 * Exit this loop if "ia_css_pipeline_request_stop()"
5141 * returns the error code.
5143 * The error code would be generated in the following
5145 * (1) The Scalar Processor has already been stopped.
5146 * (2) The "Host->SP" event queue is full.
5148 * As the convention of using CSS API 2.0/2.1, such CSS
5149 * error code would be propogated from the CSS-internal
5150 * API returned value to the CSS API returned value. Then
5151 * the CSS driver should capture these error code and
5152 * handle it in the driver exception handling mechanism.
5154 if (err != IA_CSS_SUCCESS) {
5160 * In the CSS firmware use scenario "Continuous Preview"
5161 * as well as "Continuous Video", the "ia_css_pipe" instance
5162 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5163 * the CSS firmware so that it is not listed in the target
5164 * "ia_css_stream" instance.
5166 * We need to stop this "Copy Pipe", as well.
5168 if (main_pipe->stream->config.continuous)
5170 struct ia_css_pipe *copy_pipe = NULL;
5172 /* get the reference to "Copy Pipe" */
5173 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5174 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5175 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5176 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5178 /* return the error code if "Copy Pipe" does NOT exist */
5181 IA_CSS_LOG("Copy Pipe does NOT exist!");
5182 err = IA_CSS_ERR_INTERNAL_ERROR;
5186 /* send the "stop" request to "Copy Pipe" */
5187 IA_CSS_LOG("Send the stop-request to the pipe: pipe_id=%d",
5188 copy_pipe->pipeline.pipe_id);
5189 err = ia_css_pipeline_request_stop(©_pipe->pipeline);
5193 IA_CSS_LEAVE_ERR_PRIVATE(err);
5198 * @brief Check if all "ia_css_pipe" instances in the target
5199 * "ia_css_stream" instance have stopped.
5201 * Refer to "Local prototypes" for more info.
5205 sh_css_pipes_have_stopped(struct ia_css_stream *stream)
5209 struct ia_css_pipe *main_pipe;
5210 enum ia_css_pipe_id main_pipe_id;
5216 IA_CSS_LOG("stream does NOT exist!");
5221 main_pipe = stream->last_pipe;
5225 IA_CSS_LOG("main_pipe does NOT exist!");
5230 main_pipe_id = main_pipe->mode;
5231 IA_CSS_ENTER_PRIVATE("main_pipe_id=%d", main_pipe_id);
5234 * Check if every "ia_css_pipe" instance in this target
5235 * "ia_css_stream" instance has stopped.
5237 for (i = 0; i < stream->num_pipes; i++) {
5238 rval = rval && ia_css_pipeline_has_stopped(&stream->pipes[i]->pipeline);
5239 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5240 stream->pipes[i]->pipeline.pipe_id,
5245 * In the CSS firmware use scenario "Continuous Preview"
5246 * as well as "Continuous Video", the "ia_css_pipe" instance
5247 * "Copy Pipe" is activated. This "Copy Pipe" is private to
5248 * the CSS firmware so that it is not listed in the target
5249 * "ia_css_stream" instance.
5251 * We need to check if this "Copy Pipe" has stopped, as well.
5253 if (main_pipe->stream->config.continuous) {
5254 struct ia_css_pipe *copy_pipe = NULL;
5256 /* get the reference to "Copy Pipe" */
5257 if (main_pipe_id == IA_CSS_PIPE_ID_PREVIEW)
5258 copy_pipe = main_pipe->pipe_settings.preview.copy_pipe;
5259 else if (main_pipe_id == IA_CSS_PIPE_ID_VIDEO)
5260 copy_pipe = main_pipe->pipe_settings.video.copy_pipe;
5262 /* return if "Copy Pipe" does NOT exist */
5265 IA_CSS_LOG("Copy Pipe does NOT exist!");
5271 /* check if "Copy Pipe" has stopped or not */
5272 rval = rval && ia_css_pipeline_has_stopped(©_pipe->pipeline);
5273 IA_CSS_LOG("Pipe has stopped: pipe_id=%d, stopped=%d",
5274 copy_pipe->pipeline.pipe_id,
5279 IA_CSS_LEAVE_PRIVATE("rval=%d", rval);
5283 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
5285 sh_css_get_mipi_sizes_for_check(const unsigned int port, const unsigned int idx)
5287 OP___assert(port < N_CSI_PORTS);
5288 OP___assert(idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT);
5289 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5290 "sh_css_get_mipi_sizes_for_check(port %d, idx %d): %d\n",
5291 port, idx, my_css.mipi_sizes_for_check[port][idx]);
5292 return my_css.mipi_sizes_for_check[port][idx];
5296 static enum ia_css_err sh_css_pipe_configure_output(
5297 struct ia_css_pipe *pipe,
5299 unsigned int height,
5300 unsigned int padded_width,
5301 enum ia_css_frame_format format,
5304 enum ia_css_err err = IA_CSS_SUCCESS;
5306 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, padded width = %d, format = %d, idx = %d",
5307 pipe, width, height, padded_width, format, idx);
5309 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5310 return IA_CSS_ERR_INVALID_ARGUMENTS;
5313 err = ia_css_util_check_res(width, height);
5314 if (err != IA_CSS_SUCCESS) {
5315 IA_CSS_LEAVE_ERR_PRIVATE(err);
5318 if (pipe->output_info[idx].res.width != width ||
5319 pipe->output_info[idx].res.height != height ||
5320 pipe->output_info[idx].format != format) {
5321 ia_css_frame_info_init(
5322 &pipe->output_info[idx],
5328 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5329 return IA_CSS_SUCCESS;
5332 static enum ia_css_err
5333 sh_css_pipe_get_shading_info(struct ia_css_pipe *pipe,
5334 struct ia_css_shading_info *shading_info,
5335 struct ia_css_pipe_config *pipe_config)
5337 enum ia_css_err err = IA_CSS_SUCCESS;
5338 struct ia_css_binary *binary = NULL;
5340 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5341 "sh_css_pipe_get_shading_info() enter:\n");
5343 binary = ia_css_pipe_get_shading_correction_binary(pipe);
5347 err = ia_css_binary_get_shading_info(binary,
5348 IA_CSS_SHADING_CORRECTION_TYPE_1,
5349 pipe->required_bds_factor,
5350 (const struct ia_css_stream_config *)&pipe->stream->config,
5351 shading_info, pipe_config);
5353 /* Other function calls can be added here when other shading correction types will be added
5358 /* When the pipe does not have a binary which has the shading
5359 * correction, this function does not need to fill the shading
5360 * information. It is not a error case, and then
5361 * this function should return IA_CSS_SUCCESS.
5363 memset(shading_info, 0, sizeof(*shading_info));
5368 static enum ia_css_err
5369 sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe,
5370 struct ia_css_grid_info *info) {
5371 enum ia_css_err err = IA_CSS_SUCCESS;
5372 struct ia_css_binary *binary = NULL;
5377 IA_CSS_ENTER_PRIVATE("");
5379 binary = ia_css_pipe_get_s3a_binary(pipe);
5383 err = ia_css_binary_3a_grid_info(binary, info, pipe);
5384 if (err != IA_CSS_SUCCESS)
5387 memset(&info->s3a_grid, 0, sizeof(info->s3a_grid));
5389 binary = ia_css_pipe_get_sdis_binary(pipe);
5393 ia_css_binary_dvs_grid_info(binary, info, pipe);
5394 ia_css_binary_dvs_stat_grid_info(binary, info, pipe);
5397 memset(&info->dvs_grid.dvs_grid_info, 0,
5398 sizeof(info->dvs_grid.dvs_grid_info));
5399 memset(&info->dvs_grid.dvs_stat_grid_info, 0,
5400 sizeof(info->dvs_grid.dvs_stat_grid_info));
5405 /* copy pipe does not have ISP binary*/
5406 info->isp_in_width = binary->internal_frame_info.res.width;
5407 info->isp_in_height = binary->internal_frame_info.res.height;
5410 #if defined(HAS_VAMEM_VERSION_2)
5411 info->vamem_type = IA_CSS_VAMEM_TYPE_2;
5412 #elif defined(HAS_VAMEM_VERSION_1)
5413 info->vamem_type = IA_CSS_VAMEM_TYPE_1;
5415 #error "Unknown VAMEM version"
5419 IA_CSS_LEAVE_ERR_PRIVATE(err);
5425 * @brief Check if a format is supported by the pipe.
5428 static enum ia_css_err
5429 ia_css_pipe_check_format(struct ia_css_pipe *pipe,
5430 enum ia_css_frame_format format) {
5431 const enum ia_css_frame_format *supported_formats;
5432 int number_of_formats;
5436 IA_CSS_ENTER_PRIVATE("");
5438 if (NULL == pipe || NULL == pipe->pipe_settings.video.video_binary.info)
5440 IA_CSS_ERROR("Pipe or binary info is not set");
5441 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5442 return IA_CSS_ERR_INVALID_ARGUMENTS;
5445 supported_formats = pipe->pipe_settings.video.video_binary.info->output_formats;
5446 number_of_formats = sizeof(pipe->pipe_settings.video.video_binary.info->output_formats) / sizeof(enum ia_css_frame_format);
5448 for (i = 0; i < number_of_formats && !found; i++)
5450 if (supported_formats[i] == format) {
5457 IA_CSS_ERROR("Requested format is not supported by binary");
5458 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5459 return IA_CSS_ERR_INVALID_ARGUMENTS;
5462 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5463 return IA_CSS_SUCCESS;
5467 static enum ia_css_err load_video_binaries(struct ia_css_pipe *pipe)
5469 struct ia_css_frame_info video_in_info, tnr_info,
5470 *video_vf_info, video_bds_out_info, *pipe_out_info, *pipe_vf_out_info;
5472 enum ia_css_err err = IA_CSS_SUCCESS;
5473 bool continuous = pipe->stream->config.continuous;
5475 unsigned int num_output_pins;
5476 struct ia_css_frame_info video_bin_out_info;
5477 bool need_scaler = false;
5478 bool vf_res_different_than_output = false;
5479 bool need_vf_pp = false;
5481 struct ia_css_video_settings *mycs = &pipe->pipe_settings.video;
5483 IA_CSS_ENTER_PRIVATE("");
5485 assert(pipe->mode == IA_CSS_PIPE_ID_VIDEO);
5486 /* we only test the video_binary because offline video doesn't need a
5487 * vf_pp binary and online does not (always use) the copy_binary.
5488 * All are always reset at the same time anyway.
5490 if (mycs->video_binary.info)
5491 return IA_CSS_SUCCESS;
5493 online = pipe->stream->config.online;
5494 pipe_out_info = &pipe->output_info[0];
5495 pipe_vf_out_info = &pipe->vf_output_info[0];
5497 assert(pipe_out_info);
5500 * There is no explicit input format requirement for raw or yuv
5501 * What matters is that there is a binary that supports the stream format.
5502 * This is checked in the binary_find(), so no need to check it here
5504 err = ia_css_util_check_input(&pipe->stream->config, false, false);
5505 if (err != IA_CSS_SUCCESS)
5507 /* cannot have online video and input_mode memory */
5508 if (online && pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY)
5509 return IA_CSS_ERR_INVALID_ARGUMENTS;
5510 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5511 err = ia_css_util_check_vf_out_info(pipe_out_info,
5513 if (err != IA_CSS_SUCCESS)
5516 err = ia_css_frame_check_info(pipe_out_info);
5517 if (err != IA_CSS_SUCCESS)
5521 if (pipe->out_yuv_ds_input_info.res.width)
5522 video_bin_out_info = pipe->out_yuv_ds_input_info;
5524 video_bin_out_info = *pipe_out_info;
5527 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
5528 video_vf_info = pipe_vf_out_info;
5529 vf_res_different_than_output = (video_vf_info->res.width !=
5530 video_bin_out_info.res.width) ||
5531 (video_vf_info->res.height != video_bin_out_info.res.height);
5533 video_vf_info = NULL;
5536 need_scaler = need_downscaling(video_bin_out_info.res, pipe_out_info->res);
5538 /* we build up the pipeline starting at the end */
5539 /* YUV post-processing if needed */
5541 struct ia_css_cas_binary_descr cas_scaler_descr = { };
5543 /* NV12 is the common format that is supported by both */
5544 /* yuv_scaler and the video_xx_isp2_min binaries. */
5545 video_bin_out_info.format = IA_CSS_FRAME_FORMAT_NV12;
5547 err = ia_css_pipe_create_cas_scaler_desc_single_output(
5548 &video_bin_out_info,
5552 if (err != IA_CSS_SUCCESS)
5554 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
5555 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
5556 sizeof(struct ia_css_binary), GFP_KERNEL);
5557 if (!mycs->yuv_scaler_binary) {
5558 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5561 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage
5562 * sizeof(bool), GFP_KERNEL);
5563 if (!mycs->is_output_stage) {
5564 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
5567 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
5568 struct ia_css_binary_descr yuv_scaler_descr;
5570 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
5571 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
5572 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
5573 &cas_scaler_descr.out_info[i],
5574 &cas_scaler_descr.internal_out_info[i],
5575 &cas_scaler_descr.vf_info[i]);
5576 err = ia_css_binary_find(&yuv_scaler_descr,
5577 &mycs->yuv_scaler_binary[i]);
5578 if (err != IA_CSS_SUCCESS) {
5579 kfree(mycs->is_output_stage);
5580 mycs->is_output_stage = NULL;
5584 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
5588 struct ia_css_binary_descr video_descr;
5589 enum ia_css_frame_format vf_info_format;
5591 err = ia_css_pipe_get_video_binarydesc(pipe,
5592 &video_descr, &video_in_info, &video_bds_out_info, &video_bin_out_info,
5594 pipe->stream->config.left_padding);
5595 if (err != IA_CSS_SUCCESS)
5598 /* In the case where video_vf_info is not NULL, this allows
5599 * us to find a potential video library with desired vf format.
5600 * If success, no vf_pp binary is needed.
5601 * If failed, we will look up video binary with YUV_LINE vf format
5603 err = ia_css_binary_find(&video_descr,
5604 &mycs->video_binary);
5606 if (err != IA_CSS_SUCCESS) {
5607 if (video_vf_info) {
5608 /* This will do another video binary lookup later for YUV_LINE format*/
5612 } else if (video_vf_info) {
5613 /* The first video binary lookup is successful, but we may
5614 * still need vf_pp binary based on additiona check */
5615 num_output_pins = mycs->video_binary.info->num_output_pins;
5616 vf_ds_log2 = mycs->video_binary.vf_downscale_log2;
5618 /* If the binary has dual output pins, we need vf_pp if the resolution
5620 need_vf_pp |= ((num_output_pins == 2) && vf_res_different_than_output);
5622 /* If the binary has single output pin, we need vf_pp if additional
5623 * scaling is needed for vf */
5624 need_vf_pp |= ((num_output_pins == 1) &&
5625 ((video_vf_info->res.width << vf_ds_log2 != pipe_out_info->res.width) ||
5626 (video_vf_info->res.height << vf_ds_log2 != pipe_out_info->res.height)));
5630 /* save the current vf_info format for restoration later */
5631 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5632 "load_video_binaries() need_vf_pp; find video binary with YUV_LINE again\n");
5634 vf_info_format = video_vf_info->format;
5636 if (!pipe->config.enable_vfpp_bci)
5637 ia_css_frame_info_set_format(video_vf_info,
5638 IA_CSS_FRAME_FORMAT_YUV_LINE);
5640 ia_css_binary_destroy_isp_parameters(&mycs->video_binary);
5642 err = ia_css_binary_find(&video_descr,
5643 &mycs->video_binary);
5645 /* restore original vf_info format */
5646 ia_css_frame_info_set_format(video_vf_info,
5648 if (err != IA_CSS_SUCCESS)
5653 /* If a video binary does not use a ref_frame, we set the frame delay
5654 * to 0. This is the case for the 1-stage low-power video binary. */
5655 if (!mycs->video_binary.info->sp.enable.ref_frame)
5656 pipe->dvs_frame_delay = 0;
5658 /* The delay latency determines the number of invalid frames after
5659 * a stream is started. */
5660 pipe->num_invalid_frames = pipe->dvs_frame_delay;
5661 pipe->info.num_invalid_frames = pipe->num_invalid_frames;
5663 /* Viewfinder frames also decrement num_invalid_frames. If the pipe
5664 * outputs a viewfinder output, then we need double the number of
5667 pipe->num_invalid_frames *= 2;
5669 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
5670 "load_video_binaries() num_invalid_frames=%d dvs_frame_delay=%d\n",
5671 pipe->num_invalid_frames, pipe->dvs_frame_delay);
5673 /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */
5674 #if !defined(USE_INPUT_SYSTEM_VERSION_2401)
5676 if (!online && !continuous) {
5677 /* TODO: what exactly needs doing, prepend the copy binary to
5678 * video base this only on !online?
5680 err = load_copy_binary(pipe,
5682 &mycs->video_binary);
5683 if (err != IA_CSS_SUCCESS)
5690 #if !defined(HAS_OUTPUT_SYSTEM)
5691 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) {
5692 struct ia_css_binary_descr vf_pp_descr;
5694 if (mycs->video_binary.vf_frame_info.format
5695 == IA_CSS_FRAME_FORMAT_YUV_LINE) {
5696 ia_css_pipe_get_vfpp_binarydesc(pipe, &vf_pp_descr,
5697 &mycs->video_binary.vf_frame_info,
5700 /* output from main binary is not yuv line. currently this is
5701 * possible only when bci is enabled on vfpp output */
5702 assert(pipe->config.enable_vfpp_bci == true);
5703 ia_css_pipe_get_yuvscaler_binarydesc(pipe, &vf_pp_descr,
5704 &mycs->video_binary.vf_frame_info,
5705 pipe_vf_out_info, NULL, NULL);
5708 err = ia_css_binary_find(&vf_pp_descr,
5709 &mycs->vf_pp_binary);
5710 if (err != IA_CSS_SUCCESS)
5715 err = allocate_delay_frames(pipe);
5717 if (err != IA_CSS_SUCCESS)
5720 if (mycs->video_binary.info->sp.enable.block_output) {
5721 unsigned int tnr_width;
5722 unsigned int tnr_height;
5724 tnr_info = mycs->video_binary.out_frame_info[0];
5726 if (atomisp_hw_is_isp2401) {
5727 /* Select resolution for TNR. If
5728 * output_system_in_resolution(GDC_out_resolution) is
5729 * being used, then select that as it will also be in resolution for
5730 * TNR. At present, it only make sense for Skycam */
5731 if (pipe->config.output_system_in_res.width &&
5732 pipe->config.output_system_in_res.height) {
5733 tnr_width = pipe->config.output_system_in_res.width;
5734 tnr_height = pipe->config.output_system_in_res.height;
5736 tnr_width = tnr_info.res.width;
5737 tnr_height = tnr_info.res.height;
5740 /* Make tnr reference buffers output block width(in pix) align */
5741 tnr_info.res.width = CEIL_MUL(tnr_width,
5742 (mycs->video_binary.info->sp.block.block_width * ISP_NWAY));
5743 tnr_info.padded_width = tnr_info.res.width;
5745 tnr_height = tnr_info.res.height;
5748 /* Make tnr reference buffers output block height align */
5749 tnr_info.res.height = CEIL_MUL(tnr_height,
5750 mycs->video_binary.info->sp.block.output_block_height);
5752 tnr_info = mycs->video_binary.internal_frame_info;
5754 tnr_info.format = IA_CSS_FRAME_FORMAT_YUV_LINE;
5755 tnr_info.raw_bit_depth = SH_CSS_TNR_BIT_DEPTH;
5757 for (i = 0; i < NUM_TNR_FRAMES; i++) {
5758 if (mycs->tnr_frames[i]) {
5759 ia_css_frame_free(mycs->tnr_frames[i]);
5760 mycs->tnr_frames[i] = NULL;
5762 err = ia_css_frame_allocate_from_info(
5763 &mycs->tnr_frames[i],
5765 if (err != IA_CSS_SUCCESS)
5768 IA_CSS_LEAVE_PRIVATE("");
5769 return IA_CSS_SUCCESS;
5772 static enum ia_css_err
5773 unload_video_binaries(struct ia_css_pipe *pipe) {
5776 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5778 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO))
5780 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5781 return IA_CSS_ERR_INVALID_ARGUMENTS;
5783 ia_css_binary_unload(&pipe->pipe_settings.video.copy_binary);
5784 ia_css_binary_unload(&pipe->pipe_settings.video.video_binary);
5785 ia_css_binary_unload(&pipe->pipe_settings.video.vf_pp_binary);
5787 for (i = 0; i < pipe->pipe_settings.video.num_yuv_scaler; i++)
5788 ia_css_binary_unload(&pipe->pipe_settings.video.yuv_scaler_binary[i]);
5790 kfree(pipe->pipe_settings.video.is_output_stage);
5791 pipe->pipe_settings.video.is_output_stage = NULL;
5792 kfree(pipe->pipe_settings.video.yuv_scaler_binary);
5793 pipe->pipe_settings.video.yuv_scaler_binary = NULL;
5795 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5796 return IA_CSS_SUCCESS;
5799 static enum ia_css_err video_start(struct ia_css_pipe *pipe)
5801 struct ia_css_binary *copy_binary;
5802 enum ia_css_err err = IA_CSS_SUCCESS;
5803 struct ia_css_pipe *copy_pipe, *capture_pipe;
5804 enum sh_css_pipe_config_override copy_ovrd;
5805 enum ia_css_input_mode video_pipe_input_mode;
5807 const struct ia_css_coordinate *coord = NULL;
5808 const struct ia_css_isp_parameters *params = NULL;
5810 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
5811 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_VIDEO)) {
5812 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5813 return IA_CSS_ERR_INVALID_ARGUMENTS;
5816 video_pipe_input_mode = pipe->stream->config.mode;
5818 copy_pipe = pipe->pipe_settings.video.copy_pipe;
5819 capture_pipe = pipe->pipe_settings.video.capture_pipe;
5821 copy_binary = &pipe->pipe_settings.video.copy_binary;
5823 sh_css_metrics_start_frame();
5825 /* multi stream video needs mipi buffers */
5827 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
5828 err = send_mipi_frames(pipe);
5829 if (err != IA_CSS_SUCCESS)
5833 send_raw_frames(pipe);
5835 unsigned int thread_id;
5837 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
5838 copy_ovrd = 1 << thread_id;
5840 if (pipe->stream->cont_capt) {
5841 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(capture_pipe),
5843 copy_ovrd |= 1 << thread_id;
5847 if (atomisp_hw_is_isp2401) {
5848 coord = &pipe->config.internal_frame_origin_bqs_on_sctbl;
5849 params = pipe->stream->isp_params_configs;
5852 /* Construct and load the copy pipe */
5853 if (pipe->stream->config.continuous) {
5854 sh_css_sp_init_pipeline(©_pipe->pipeline,
5855 IA_CSS_PIPE_ID_COPY,
5856 (uint8_t)ia_css_pipe_get_pipe_num(copy_pipe),
5858 pipe->stream->config.pixels_per_clock == 2, false,
5859 false, pipe->required_bds_factor,
5861 pipe->stream->config.mode,
5862 &pipe->stream->config.metadata_config,
5863 &pipe->stream->info.metadata_info,
5864 #if !defined(HAS_NO_INPUT_SYSTEM)
5865 pipe->stream->config.source.port.port,
5870 /* make the video pipe start with mem mode input, copy handles
5872 video_pipe_input_mode = IA_CSS_INPUT_MODE_MEMORY;
5875 /* Construct and load the capture pipe */
5876 if (pipe->stream->cont_capt) {
5877 sh_css_sp_init_pipeline(&capture_pipe->pipeline,
5878 IA_CSS_PIPE_ID_CAPTURE,
5879 (uint8_t)ia_css_pipe_get_pipe_num(capture_pipe),
5880 capture_pipe->config.default_capture_config.enable_xnr != 0,
5881 capture_pipe->stream->config.pixels_per_clock == 2,
5882 true, /* continuous */
5883 false, /* offline */
5884 capture_pipe->required_bds_factor,
5886 IA_CSS_INPUT_MODE_MEMORY,
5887 &pipe->stream->config.metadata_config,
5888 &pipe->stream->info.metadata_info,
5889 #if !defined(HAS_NO_INPUT_SYSTEM)
5890 (enum mipi_port_id)0,
5896 start_pipe(pipe, copy_ovrd, video_pipe_input_mode);
5898 IA_CSS_LEAVE_ERR_PRIVATE(err);
5903 enum ia_css_err sh_css_pipe_get_viewfinder_frame_info(
5904 struct ia_css_pipe *pipe,
5905 struct ia_css_frame_info *info,
5911 /* We could print the pointer as input arg, and the values as output */
5912 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5913 "sh_css_pipe_get_viewfinder_frame_info() enter: void\n");
5915 if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE &&
5916 (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
5917 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER))
5918 return IA_CSS_ERR_MODE_HAS_NO_VIEWFINDER;
5919 /* offline video does not generate viewfinder output */
5920 *info = pipe->vf_output_info[idx];
5922 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
5923 "sh_css_pipe_get_viewfinder_frame_info() leave: \
5924 info.res.width=%d, info.res.height=%d, \
5925 info.padded_width=%d, info.format=%d, \
5926 info.raw_bit_depth=%d, info.raw_bayer_order=%d\n",
5927 info->res.width, info->res.height,
5928 info->padded_width, info->format,
5929 info->raw_bit_depth, info->raw_bayer_order);
5931 return IA_CSS_SUCCESS;
5934 static enum ia_css_err
5935 sh_css_pipe_configure_viewfinder(struct ia_css_pipe *pipe, unsigned int width,
5936 unsigned int height, unsigned int min_width,
5937 enum ia_css_frame_format format,
5939 enum ia_css_err err = IA_CSS_SUCCESS;
5941 IA_CSS_ENTER_PRIVATE("pipe = %p, width = %d, height = %d, min_width = %d, format = %d, idx = %d\n",
5942 pipe, width, height, min_width, format, idx);
5946 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
5947 return IA_CSS_ERR_INVALID_ARGUMENTS;
5950 err = ia_css_util_check_res(width, height);
5951 if (err != IA_CSS_SUCCESS)
5953 IA_CSS_LEAVE_ERR_PRIVATE(err);
5956 if (pipe->vf_output_info[idx].res.width != width ||
5957 pipe->vf_output_info[idx].res.height != height ||
5958 pipe->vf_output_info[idx].format != format)
5960 ia_css_frame_info_init(&pipe->vf_output_info[idx], width, height,
5963 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
5964 return IA_CSS_SUCCESS;
5967 static enum ia_css_err load_copy_binaries(struct ia_css_pipe *pipe)
5969 enum ia_css_err err = IA_CSS_SUCCESS;
5972 IA_CSS_ENTER_PRIVATE("");
5974 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
5975 pipe->mode == IA_CSS_PIPE_ID_COPY);
5976 if (pipe->pipe_settings.capture.copy_binary.info)
5977 return IA_CSS_SUCCESS;
5979 err = ia_css_frame_check_info(&pipe->output_info[0]);
5980 if (err != IA_CSS_SUCCESS)
5983 err = verify_copy_out_frame_format(pipe);
5984 if (err != IA_CSS_SUCCESS)
5987 err = load_copy_binary(pipe,
5988 &pipe->pipe_settings.capture.copy_binary,
5992 IA_CSS_LEAVE_ERR_PRIVATE(err);
5996 static bool need_capture_pp(
5997 const struct ia_css_pipe *pipe)
5999 const struct ia_css_frame_info *out_info = &pipe->output_info[0];
6001 IA_CSS_ENTER_LEAVE_PRIVATE("");
6003 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6005 if (atomisp_hw_is_isp2401) {
6006 /* ldc and capture_pp are not supported in the same pipeline */
6007 if (need_capt_ldc(pipe) == true)
6011 /* determine whether we need to use the capture_pp binary.
6012 * This is needed for:
6014 * 2. Digital Zoom or
6015 * 3. YUV downscaling
6017 if (pipe->out_yuv_ds_input_info.res.width &&
6018 ((pipe->out_yuv_ds_input_info.res.width != out_info->res.width) ||
6019 (pipe->out_yuv_ds_input_info.res.height != out_info->res.height)))
6022 if (pipe->config.default_capture_config.enable_xnr != 0)
6025 if ((pipe->stream->isp_params_configs->dz_config.dx < HRT_GDC_N) ||
6026 (pipe->stream->isp_params_configs->dz_config.dy < HRT_GDC_N) ||
6027 pipe->config.enable_dz)
6033 static bool need_capt_ldc(
6034 const struct ia_css_pipe *pipe)
6036 IA_CSS_ENTER_LEAVE_PRIVATE("");
6038 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6039 return (pipe->extra_config.enable_dvs_6axis) ? true : false;
6042 static enum ia_css_err set_num_primary_stages(unsigned int *num,
6043 enum ia_css_pipe_version version)
6045 enum ia_css_err err = IA_CSS_SUCCESS;
6048 return IA_CSS_ERR_INVALID_ARGUMENTS;
6051 case IA_CSS_PIPE_VERSION_2_6_1:
6052 *num = NUM_PRIMARY_HQ_STAGES;
6054 case IA_CSS_PIPE_VERSION_2_2:
6055 case IA_CSS_PIPE_VERSION_1:
6056 *num = NUM_PRIMARY_STAGES;
6059 err = IA_CSS_ERR_INVALID_ARGUMENTS;
6066 static enum ia_css_err load_primary_binaries(
6067 struct ia_css_pipe *pipe)
6069 bool online = false;
6070 bool memory = false;
6071 bool continuous = false;
6072 bool need_pp = false;
6073 bool need_isp_copy_binary = false;
6074 bool need_ldc = false;
6075 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6076 bool sensor = false;
6078 struct ia_css_frame_info prim_in_info,
6080 capt_pp_out_info, vf_info,
6081 *vf_pp_in_info, *pipe_out_info,
6082 *pipe_vf_out_info, *capt_pp_in_info,
6084 enum ia_css_err err = IA_CSS_SUCCESS;
6085 struct ia_css_capture_settings *mycs;
6087 bool need_extra_yuv_scaler = false;
6088 struct ia_css_binary_descr prim_descr[MAX_NUM_PRIMARY_STAGES];
6090 IA_CSS_ENTER_PRIVATE("");
6092 assert(pipe->stream);
6093 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6094 pipe->mode == IA_CSS_PIPE_ID_COPY);
6096 online = pipe->stream->config.online;
6097 memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
6098 continuous = pipe->stream->config.continuous;
6099 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6100 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
6103 mycs = &pipe->pipe_settings.capture;
6104 pipe_out_info = &pipe->output_info[0];
6105 pipe_vf_out_info = &pipe->vf_output_info[0];
6107 if (mycs->primary_binary[0].info)
6108 return IA_CSS_SUCCESS;
6110 err = set_num_primary_stages(&mycs->num_primary_stage,
6111 pipe->config.isp_pipe_version);
6112 if (err != IA_CSS_SUCCESS) {
6113 IA_CSS_LEAVE_ERR_PRIVATE(err);
6117 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6118 err = ia_css_util_check_vf_out_info(pipe_out_info, pipe_vf_out_info);
6119 if (err != IA_CSS_SUCCESS) {
6120 IA_CSS_LEAVE_ERR_PRIVATE(err);
6124 err = ia_css_frame_check_info(pipe_out_info);
6125 if (err != IA_CSS_SUCCESS) {
6126 IA_CSS_LEAVE_ERR_PRIVATE(err);
6130 need_pp = need_capture_pp(pipe);
6132 /* we use the vf output info to get the primary/capture_pp binary
6133 configured for vf_veceven. It will select the closest downscaling
6135 vf_info = *pipe_vf_out_info;
6138 * WARNING: The #if def flag has been added below as a
6139 * temporary solution to solve the problem of enabling the
6140 * view finder in a single binary in a capture flow. The
6141 * vf-pp stage has been removed for Skycam in the solution
6142 * provided. The vf-pp stage should be re-introduced when
6143 * required. This should not be considered as a clean solution.
6144 * Proper investigation should be done to come up with the clean
6147 ia_css_frame_info_set_format(&vf_info, IA_CSS_FRAME_FORMAT_YUV_LINE);
6149 /* TODO: All this yuv_scaler and capturepp calculation logic
6150 * can be shared later. Capture_pp is also a yuv_scale binary
6151 * with extra XNR funcionality. Therefore, it can be made as the
6152 * first step of the cascade. */
6153 capt_pp_out_info = pipe->out_yuv_ds_input_info;
6154 capt_pp_out_info.format = IA_CSS_FRAME_FORMAT_YUV420;
6155 capt_pp_out_info.res.width /= MAX_PREFERRED_YUV_DS_PER_STEP;
6156 capt_pp_out_info.res.height /= MAX_PREFERRED_YUV_DS_PER_STEP;
6157 ia_css_frame_info_set_width(&capt_pp_out_info, capt_pp_out_info.res.width, 0);
6159 need_extra_yuv_scaler = need_downscaling(capt_pp_out_info.res,
6160 pipe_out_info->res);
6162 if (need_extra_yuv_scaler) {
6163 struct ia_css_cas_binary_descr cas_scaler_descr = { };
6165 err = ia_css_pipe_create_cas_scaler_desc_single_output(
6170 if (err != IA_CSS_SUCCESS) {
6171 IA_CSS_LEAVE_ERR_PRIVATE(err);
6174 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
6175 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
6176 sizeof(struct ia_css_binary), GFP_KERNEL);
6177 if (!mycs->yuv_scaler_binary) {
6178 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6179 IA_CSS_LEAVE_ERR_PRIVATE(err);
6182 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
6183 sizeof(bool), GFP_KERNEL);
6184 if (!mycs->is_output_stage) {
6185 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6186 IA_CSS_LEAVE_ERR_PRIVATE(err);
6189 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
6190 struct ia_css_binary_descr yuv_scaler_descr;
6192 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
6193 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
6194 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
6195 &cas_scaler_descr.out_info[i],
6196 &cas_scaler_descr.internal_out_info[i],
6197 &cas_scaler_descr.vf_info[i]);
6198 err = ia_css_binary_find(&yuv_scaler_descr,
6199 &mycs->yuv_scaler_binary[i]);
6200 if (err != IA_CSS_SUCCESS) {
6201 IA_CSS_LEAVE_ERR_PRIVATE(err);
6205 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
6208 capt_pp_out_info = pipe->output_info[0];
6211 /* TODO Do we disable ldc for skycam */
6212 need_ldc = need_capt_ldc(pipe);
6213 if (atomisp_hw_is_isp2401 && need_ldc) {
6214 /* ldc and capt_pp are not supported in the same pipeline */
6215 struct ia_css_binary_descr capt_ldc_descr;
6217 ia_css_pipe_get_ldc_binarydesc(pipe,
6218 &capt_ldc_descr, &prim_out_info,
6221 err = ia_css_binary_find(&capt_ldc_descr,
6222 &mycs->capture_ldc_binary);
6223 if (err != IA_CSS_SUCCESS) {
6224 IA_CSS_LEAVE_ERR_PRIVATE(err);
6231 /* we build up the pipeline starting at the end */
6232 /* Capture post-processing */
6234 struct ia_css_binary_descr capture_pp_descr;
6236 if (!atomisp_hw_is_isp2401)
6237 capt_pp_in_info = need_ldc ? &capt_ldc_out_info : &prim_out_info;
6239 capt_pp_in_info = &prim_out_info;
6241 ia_css_pipe_get_capturepp_binarydesc(pipe,
6242 &capture_pp_descr, capt_pp_in_info,
6243 &capt_pp_out_info, &vf_info);
6244 err = ia_css_binary_find(&capture_pp_descr,
6245 &mycs->capture_pp_binary);
6246 if (err != IA_CSS_SUCCESS) {
6247 IA_CSS_LEAVE_ERR_PRIVATE(err);
6252 struct ia_css_binary_descr capt_ldc_descr;
6254 ia_css_pipe_get_ldc_binarydesc(pipe,
6255 &capt_ldc_descr, &prim_out_info,
6256 &capt_ldc_out_info);
6258 err = ia_css_binary_find(&capt_ldc_descr,
6259 &mycs->capture_ldc_binary);
6260 if (err != IA_CSS_SUCCESS) {
6261 IA_CSS_LEAVE_ERR_PRIVATE(err);
6266 prim_out_info = *pipe_out_info;
6270 for (i = 0; i < mycs->num_primary_stage; i++) {
6271 struct ia_css_frame_info *local_vf_info = NULL;
6273 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] &&
6274 (i == mycs->num_primary_stage - 1))
6275 local_vf_info = &vf_info;
6276 ia_css_pipe_get_primary_binarydesc(pipe, &prim_descr[i], &prim_in_info,
6277 &prim_out_info, local_vf_info, i);
6278 err = ia_css_binary_find(&prim_descr[i], &mycs->primary_binary[i]);
6279 if (err != IA_CSS_SUCCESS) {
6280 IA_CSS_LEAVE_ERR_PRIVATE(err);
6285 /* Viewfinder post-processing */
6287 vf_pp_in_info = &mycs->capture_pp_binary.vf_frame_info;
6289 vf_pp_in_info = &mycs->primary_binary[mycs->num_primary_stage - 1].vf_frame_info;
6292 * WARNING: The #if def flag has been added below as a
6293 * temporary solution to solve the problem of enabling the
6294 * view finder in a single binary in a capture flow. The
6295 * vf-pp stage has been removed for Skycam in the solution
6296 * provided. The vf-pp stage should be re-introduced when
6297 * required. Thisshould not be considered as a clean solution.
6298 * Proper * investigation should be done to come up with the clean
6301 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0]) {
6302 struct ia_css_binary_descr vf_pp_descr;
6304 ia_css_pipe_get_vfpp_binarydesc(pipe,
6305 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6306 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary);
6307 if (err != IA_CSS_SUCCESS) {
6308 IA_CSS_LEAVE_ERR_PRIVATE(err);
6312 err = allocate_delay_frames(pipe);
6314 if (err != IA_CSS_SUCCESS)
6317 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6318 /* When the input system is 2401, only the Direct Sensor Mode
6319 * Offline Capture uses the ISP copy binary.
6321 need_isp_copy_binary = !online && sensor;
6323 need_isp_copy_binary = !online && !continuous && !memory;
6327 if (need_isp_copy_binary) {
6328 err = load_copy_binary(pipe,
6330 &mycs->primary_binary[0]);
6331 if (err != IA_CSS_SUCCESS) {
6332 IA_CSS_LEAVE_ERR_PRIVATE(err);
6337 return IA_CSS_SUCCESS;
6340 static enum ia_css_err
6341 allocate_delay_frames(struct ia_css_pipe *pipe) {
6342 unsigned int num_delay_frames = 0, i = 0;
6343 unsigned int dvs_frame_delay = 0;
6344 struct ia_css_frame_info ref_info;
6345 enum ia_css_err err = IA_CSS_SUCCESS;
6346 enum ia_css_pipe_id mode = IA_CSS_PIPE_ID_VIDEO;
6347 struct ia_css_frame **delay_frames = NULL;
6349 IA_CSS_ENTER_PRIVATE("");
6353 IA_CSS_ERROR("Invalid args - pipe %p", pipe);
6354 return IA_CSS_ERR_INVALID_ARGUMENTS;
6358 dvs_frame_delay = pipe->dvs_frame_delay;
6360 if (dvs_frame_delay > 0)
6361 num_delay_frames = dvs_frame_delay + 1;
6365 case IA_CSS_PIPE_ID_CAPTURE: {
6366 struct ia_css_capture_settings *mycs_capture = &pipe->pipe_settings.capture;
6371 case IA_CSS_PIPE_ID_VIDEO: {
6372 struct ia_css_video_settings *mycs_video = &pipe->pipe_settings.video;
6374 ref_info = mycs_video->video_binary.internal_frame_info;
6375 /*The ref frame expects
6377 * 2. UV plane with line interleaving, like below
6378 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6380 * This format is not YUV420(which has Y, U and V planes).
6381 * Its closer to NV12, except that the UV plane has UV
6382 * interleaving, like UVUVUVUVUVUVUVUVU...
6384 * TODO: make this ref_frame format as a separate frame format
6386 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6387 delay_frames = mycs_video->delay_frames;
6390 case IA_CSS_PIPE_ID_PREVIEW: {
6391 struct ia_css_preview_settings *mycs_preview = &pipe->pipe_settings.preview;
6393 ref_info = mycs_preview->preview_binary.internal_frame_info;
6394 /*The ref frame expects
6396 * 2. UV plane with line interleaving, like below
6397 * UUUUUU(width/2 times) VVVVVVVV..(width/2 times)
6399 * This format is not YUV420(which has Y, U and V planes).
6400 * Its closer to NV12, except that the UV plane has UV
6401 * interleaving, like UVUVUVUVUVUVUVUVU...
6403 * TODO: make this ref_frame format as a separate frame format
6405 ref_info.format = IA_CSS_FRAME_FORMAT_NV12;
6406 delay_frames = mycs_preview->delay_frames;
6410 return IA_CSS_ERR_INVALID_ARGUMENTS;
6413 ref_info.raw_bit_depth = SH_CSS_REF_BIT_DEPTH;
6415 assert(num_delay_frames <= MAX_NUM_VIDEO_DELAY_FRAMES);
6416 for (i = 0; i < num_delay_frames; i++)
6418 err = ia_css_frame_allocate_from_info(&delay_frames[i], &ref_info);
6419 if (err != IA_CSS_SUCCESS)
6422 IA_CSS_LEAVE_PRIVATE("");
6423 return IA_CSS_SUCCESS;
6426 static enum ia_css_err load_advanced_binaries(
6427 struct ia_css_pipe *pipe) {
6428 struct ia_css_frame_info pre_in_info, gdc_in_info,
6429 post_in_info, post_out_info,
6430 vf_info, *vf_pp_in_info, *pipe_out_info,
6433 bool need_isp_copy = true;
6434 enum ia_css_err err = IA_CSS_SUCCESS;
6436 IA_CSS_ENTER_PRIVATE("");
6439 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6440 pipe->mode == IA_CSS_PIPE_ID_COPY);
6441 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6442 return IA_CSS_SUCCESS;
6443 pipe_out_info = &pipe->output_info[0];
6444 pipe_vf_out_info = &pipe->vf_output_info[0];
6446 vf_info = *pipe_vf_out_info;
6447 err = ia_css_util_check_vf_out_info(pipe_out_info, &vf_info);
6448 if (err != IA_CSS_SUCCESS)
6450 need_pp = need_capture_pp(pipe);
6452 ia_css_frame_info_set_format(&vf_info,
6453 IA_CSS_FRAME_FORMAT_YUV_LINE);
6455 /* we build up the pipeline starting at the end */
6456 /* Capture post-processing */
6458 struct ia_css_binary_descr capture_pp_descr;
6460 ia_css_pipe_get_capturepp_binarydesc(pipe,
6461 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6462 err = ia_css_binary_find(&capture_pp_descr,
6463 &pipe->pipe_settings.capture.capture_pp_binary);
6464 if (err != IA_CSS_SUCCESS)
6467 post_out_info = *pipe_out_info;
6472 struct ia_css_binary_descr post_gdc_descr;
6474 ia_css_pipe_get_post_gdc_binarydesc(pipe,
6475 &post_gdc_descr, &post_in_info, &post_out_info, &vf_info);
6476 err = ia_css_binary_find(&post_gdc_descr,
6477 &pipe->pipe_settings.capture.post_isp_binary);
6478 if (err != IA_CSS_SUCCESS)
6484 struct ia_css_binary_descr gdc_descr;
6486 ia_css_pipe_get_gdc_binarydesc(pipe, &gdc_descr, &gdc_in_info,
6487 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6488 err = ia_css_binary_find(&gdc_descr,
6489 &pipe->pipe_settings.capture.anr_gdc_binary);
6490 if (err != IA_CSS_SUCCESS)
6493 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6494 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6498 struct ia_css_binary_descr pre_gdc_descr;
6500 ia_css_pipe_get_pre_gdc_binarydesc(pipe, &pre_gdc_descr, &pre_in_info,
6501 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6502 err = ia_css_binary_find(&pre_gdc_descr,
6503 &pipe->pipe_settings.capture.pre_isp_binary);
6504 if (err != IA_CSS_SUCCESS)
6507 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6508 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6510 /* Viewfinder post-processing */
6513 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6516 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6520 struct ia_css_binary_descr vf_pp_descr;
6522 ia_css_pipe_get_vfpp_binarydesc(pipe,
6523 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6524 err = ia_css_binary_find(&vf_pp_descr,
6525 &pipe->pipe_settings.capture.vf_pp_binary);
6526 if (err != IA_CSS_SUCCESS)
6531 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6532 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6533 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6536 load_copy_binary(pipe,
6537 &pipe->pipe_settings.capture.copy_binary,
6538 &pipe->pipe_settings.capture.pre_isp_binary);
6543 static enum ia_css_err load_bayer_isp_binaries(
6544 struct ia_css_pipe *pipe) {
6545 struct ia_css_frame_info pre_isp_in_info, *pipe_out_info;
6546 enum ia_css_err err = IA_CSS_SUCCESS;
6547 struct ia_css_binary_descr pre_de_descr;
6549 IA_CSS_ENTER_PRIVATE("");
6551 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6552 pipe->mode == IA_CSS_PIPE_ID_COPY);
6553 pipe_out_info = &pipe->output_info[0];
6555 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6556 return IA_CSS_SUCCESS;
6558 err = ia_css_frame_check_info(pipe_out_info);
6559 if (err != IA_CSS_SUCCESS)
6562 ia_css_pipe_get_pre_de_binarydesc(pipe, &pre_de_descr,
6566 err = ia_css_binary_find(&pre_de_descr,
6567 &pipe->pipe_settings.capture.pre_isp_binary);
6572 static enum ia_css_err load_low_light_binaries(
6573 struct ia_css_pipe *pipe) {
6574 struct ia_css_frame_info pre_in_info, anr_in_info,
6575 post_in_info, post_out_info,
6576 vf_info, *pipe_vf_out_info, *pipe_out_info,
6579 bool need_isp_copy = true;
6580 enum ia_css_err err = IA_CSS_SUCCESS;
6582 IA_CSS_ENTER_PRIVATE("");
6584 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6585 pipe->mode == IA_CSS_PIPE_ID_COPY);
6587 if (pipe->pipe_settings.capture.pre_isp_binary.info)
6588 return IA_CSS_SUCCESS;
6589 pipe_vf_out_info = &pipe->vf_output_info[0];
6590 pipe_out_info = &pipe->output_info[0];
6592 vf_info = *pipe_vf_out_info;
6593 err = ia_css_util_check_vf_out_info(pipe_out_info,
6595 if (err != IA_CSS_SUCCESS)
6597 need_pp = need_capture_pp(pipe);
6599 ia_css_frame_info_set_format(&vf_info,
6600 IA_CSS_FRAME_FORMAT_YUV_LINE);
6602 /* we build up the pipeline starting at the end */
6603 /* Capture post-processing */
6605 struct ia_css_binary_descr capture_pp_descr;
6607 ia_css_pipe_get_capturepp_binarydesc(pipe,
6608 &capture_pp_descr, &post_out_info, pipe_out_info, &vf_info);
6609 err = ia_css_binary_find(&capture_pp_descr,
6610 &pipe->pipe_settings.capture.capture_pp_binary);
6611 if (err != IA_CSS_SUCCESS)
6614 post_out_info = *pipe_out_info;
6619 struct ia_css_binary_descr post_anr_descr;
6621 ia_css_pipe_get_post_anr_binarydesc(pipe,
6622 &post_anr_descr, &post_in_info, &post_out_info, &vf_info);
6623 err = ia_css_binary_find(&post_anr_descr,
6624 &pipe->pipe_settings.capture.post_isp_binary);
6625 if (err != IA_CSS_SUCCESS)
6631 struct ia_css_binary_descr anr_descr;
6633 ia_css_pipe_get_anr_binarydesc(pipe, &anr_descr, &anr_in_info,
6634 &pipe->pipe_settings.capture.post_isp_binary.in_frame_info);
6635 err = ia_css_binary_find(&anr_descr,
6636 &pipe->pipe_settings.capture.anr_gdc_binary);
6637 if (err != IA_CSS_SUCCESS)
6640 pipe->pipe_settings.capture.anr_gdc_binary.left_padding =
6641 pipe->pipe_settings.capture.post_isp_binary.left_padding;
6645 struct ia_css_binary_descr pre_anr_descr;
6647 ia_css_pipe_get_pre_anr_binarydesc(pipe, &pre_anr_descr, &pre_in_info,
6648 &pipe->pipe_settings.capture.anr_gdc_binary.in_frame_info);
6649 err = ia_css_binary_find(&pre_anr_descr,
6650 &pipe->pipe_settings.capture.pre_isp_binary);
6651 if (err != IA_CSS_SUCCESS)
6654 pipe->pipe_settings.capture.pre_isp_binary.left_padding =
6655 pipe->pipe_settings.capture.anr_gdc_binary.left_padding;
6657 /* Viewfinder post-processing */
6660 &pipe->pipe_settings.capture.capture_pp_binary.vf_frame_info;
6663 &pipe->pipe_settings.capture.post_isp_binary.vf_frame_info;
6667 struct ia_css_binary_descr vf_pp_descr;
6669 ia_css_pipe_get_vfpp_binarydesc(pipe,
6670 &vf_pp_descr, vf_pp_in_info, pipe_vf_out_info);
6671 err = ia_css_binary_find(&vf_pp_descr,
6672 &pipe->pipe_settings.capture.vf_pp_binary);
6673 if (err != IA_CSS_SUCCESS)
6678 #ifdef USE_INPUT_SYSTEM_VERSION_2401
6679 /* For CSI2+, only the direct sensor mode/online requires ISP copy */
6680 need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
6683 err = load_copy_binary(pipe,
6684 &pipe->pipe_settings.capture.copy_binary,
6685 &pipe->pipe_settings.capture.pre_isp_binary);
6690 static bool copy_on_sp(struct ia_css_pipe *pipe) {
6694 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "copy_on_sp() enter:\n");
6698 rval &= (pipe->mode == IA_CSS_PIPE_ID_CAPTURE);
6700 rval &= (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW);
6702 rval &= ((pipe->stream->config.input_config.format ==
6703 ATOMISP_INPUT_FORMAT_BINARY_8) ||
6704 (pipe->config.mode == IA_CSS_PIPE_MODE_COPY));
6709 static enum ia_css_err load_capture_binaries(
6710 struct ia_css_pipe *pipe) {
6711 enum ia_css_err err = IA_CSS_SUCCESS;
6714 IA_CSS_ENTER_PRIVATE("");
6716 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE ||
6717 pipe->mode == IA_CSS_PIPE_ID_COPY);
6719 if (pipe->pipe_settings.capture.primary_binary[0].info) {
6720 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6721 return IA_CSS_SUCCESS;
6724 /* in primary, advanced,low light or bayer,
6725 the input format must be raw */
6727 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
6728 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER ||
6729 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT;
6730 err = ia_css_util_check_input(&pipe->stream->config, must_be_raw, false);
6731 if (err != IA_CSS_SUCCESS) {
6732 IA_CSS_LEAVE_ERR_PRIVATE(err);
6735 if (copy_on_sp(pipe) &&
6736 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8) {
6737 ia_css_frame_info_init(
6738 &pipe->output_info[0],
6741 IA_CSS_FRAME_FORMAT_BINARY_8,
6743 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6744 return IA_CSS_SUCCESS;
6747 switch (pipe->config.default_capture_config.mode) {
6748 case IA_CSS_CAPTURE_MODE_RAW:
6749 err = load_copy_binaries(pipe);
6750 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
6751 if (err == IA_CSS_SUCCESS)
6752 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
6755 case IA_CSS_CAPTURE_MODE_BAYER:
6756 err = load_bayer_isp_binaries(pipe);
6758 case IA_CSS_CAPTURE_MODE_PRIMARY:
6759 err = load_primary_binaries(pipe);
6761 case IA_CSS_CAPTURE_MODE_ADVANCED:
6762 err = load_advanced_binaries(pipe);
6764 case IA_CSS_CAPTURE_MODE_LOW_LIGHT:
6765 err = load_low_light_binaries(pipe);
6768 if (err != IA_CSS_SUCCESS) {
6769 IA_CSS_LEAVE_ERR_PRIVATE(err);
6773 IA_CSS_LEAVE_ERR_PRIVATE(err);
6777 static enum ia_css_err
6778 unload_capture_binaries(struct ia_css_pipe *pipe) {
6781 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
6783 if ((!pipe) || ((pipe->mode != IA_CSS_PIPE_ID_CAPTURE) && (pipe->mode != IA_CSS_PIPE_ID_COPY)))
6785 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
6786 return IA_CSS_ERR_INVALID_ARGUMENTS;
6788 ia_css_binary_unload(&pipe->pipe_settings.capture.copy_binary);
6789 for (i = 0; i < MAX_NUM_PRIMARY_STAGES; i++)
6790 ia_css_binary_unload(&pipe->pipe_settings.capture.primary_binary[i]);
6791 ia_css_binary_unload(&pipe->pipe_settings.capture.pre_isp_binary);
6792 ia_css_binary_unload(&pipe->pipe_settings.capture.anr_gdc_binary);
6793 ia_css_binary_unload(&pipe->pipe_settings.capture.post_isp_binary);
6794 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_pp_binary);
6795 ia_css_binary_unload(&pipe->pipe_settings.capture.capture_ldc_binary);
6796 ia_css_binary_unload(&pipe->pipe_settings.capture.vf_pp_binary);
6798 for (i = 0; i < pipe->pipe_settings.capture.num_yuv_scaler; i++)
6799 ia_css_binary_unload(&pipe->pipe_settings.capture.yuv_scaler_binary[i]);
6801 kfree(pipe->pipe_settings.capture.is_output_stage);
6802 pipe->pipe_settings.capture.is_output_stage = NULL;
6803 kfree(pipe->pipe_settings.capture.yuv_scaler_binary);
6804 pipe->pipe_settings.capture.yuv_scaler_binary = NULL;
6806 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
6807 return IA_CSS_SUCCESS;
6811 need_downscaling(const struct ia_css_resolution in_res,
6812 const struct ia_css_resolution out_res) {
6813 if (in_res.width > out_res.width || in_res.height > out_res.height)
6820 need_yuv_scaler_stage(const struct ia_css_pipe *pipe) {
6822 struct ia_css_resolution in_res, out_res;
6824 bool need_format_conversion = false;
6826 IA_CSS_ENTER_PRIVATE("");
6828 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
6830 /* TODO: make generic function */
6831 need_format_conversion =
6832 ((pipe->stream->config.input_config.format ==
6833 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) &&
6834 (pipe->output_info[0].format != IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8));
6836 in_res = pipe->config.input_effective_res;
6838 if (pipe->config.enable_dz)
6841 if ((pipe->output_info[0].res.width != 0) && need_format_conversion)
6844 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6845 out_res = pipe->output_info[i].res;
6847 /* A non-zero width means it is a valid output port */
6848 if ((out_res.width != 0) && need_downscaling(in_res, out_res))
6855 /* TODO: it is temporarily created from ia_css_pipe_create_cas_scaler_desc */
6856 /* which has some hard-coded knowledge which prevents reuse of the function. */
6857 /* Later, merge this with ia_css_pipe_create_cas_scaler_desc */
6858 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc_single_output(
6859 struct ia_css_frame_info *cas_scaler_in_info,
6860 struct ia_css_frame_info *cas_scaler_out_info,
6861 struct ia_css_frame_info *cas_scaler_vf_info,
6862 struct ia_css_cas_binary_descr *descr) {
6864 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
6865 enum ia_css_err err = IA_CSS_SUCCESS;
6866 struct ia_css_frame_info tmp_in_info;
6868 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6870 assert(cas_scaler_in_info);
6871 assert(cas_scaler_out_info);
6873 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6874 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6876 /* We assume that this function is used only for single output port case. */
6877 descr->num_output_stage = 1;
6879 hor_ds_factor = CEIL_DIV(cas_scaler_in_info->res.width,
6880 cas_scaler_out_info->res.width);
6881 ver_ds_factor = CEIL_DIV(cas_scaler_in_info->res.height,
6882 cas_scaler_out_info->res.height);
6883 /* use the same horizontal and vertical downscaling factor for simplicity */
6884 assert(hor_ds_factor == ver_ds_factor);
6887 while (i < hor_ds_factor) {
6889 i *= max_scale_factor_per_stage;
6892 descr->in_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6894 if (!descr->in_info) {
6895 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6898 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
6899 struct ia_css_frame_info), GFP_KERNEL);
6900 if (!descr->internal_out_info) {
6901 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6904 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6906 if (!descr->out_info) {
6907 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6910 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
6912 if (!descr->vf_info) {
6913 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6916 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
6917 if (!descr->is_output_stage) {
6918 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
6922 tmp_in_info = *cas_scaler_in_info;
6923 for (i = 0; i < descr->num_stage; i++) {
6924 descr->in_info[i] = tmp_in_info;
6925 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
6926 cas_scaler_out_info->res.width) {
6927 descr->is_output_stage[i] = true;
6928 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
6929 descr->internal_out_info[i].res.width = cas_scaler_out_info->res.width;
6930 descr->internal_out_info[i].res.height = cas_scaler_out_info->res.height;
6931 descr->internal_out_info[i].padded_width = cas_scaler_out_info->padded_width;
6932 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6934 assert(i == (descr->num_stage - 1));
6935 descr->internal_out_info[i].res.width = 0;
6936 descr->internal_out_info[i].res.height = 0;
6938 descr->out_info[i].res.width = cas_scaler_out_info->res.width;
6939 descr->out_info[i].res.height = cas_scaler_out_info->res.height;
6940 descr->out_info[i].padded_width = cas_scaler_out_info->padded_width;
6941 descr->out_info[i].format = cas_scaler_out_info->format;
6942 if (cas_scaler_vf_info) {
6943 descr->vf_info[i].res.width = cas_scaler_vf_info->res.width;
6944 descr->vf_info[i].res.height = cas_scaler_vf_info->res.height;
6945 descr->vf_info[i].padded_width = cas_scaler_vf_info->padded_width;
6946 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
6948 descr->vf_info[i].res.width = 0;
6949 descr->vf_info[i].res.height = 0;
6950 descr->vf_info[i].padded_width = 0;
6953 descr->is_output_stage[i] = false;
6954 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
6955 max_scale_factor_per_stage;
6956 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
6957 max_scale_factor_per_stage;
6958 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
6959 ia_css_frame_info_init(&descr->internal_out_info[i],
6960 tmp_in_info.res.width / max_scale_factor_per_stage,
6961 tmp_in_info.res.height / max_scale_factor_per_stage,
6962 IA_CSS_FRAME_FORMAT_YUV420, 0);
6963 descr->out_info[i].res.width = 0;
6964 descr->out_info[i].res.height = 0;
6965 descr->vf_info[i].res.width = 0;
6966 descr->vf_info[i].res.height = 0;
6968 tmp_in_info = descr->internal_out_info[i];
6971 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6972 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
6977 /* FIXME: merge most of this and single output version */
6978 static enum ia_css_err ia_css_pipe_create_cas_scaler_desc(
6979 struct ia_css_pipe *pipe,
6980 struct ia_css_cas_binary_descr *descr) {
6981 struct ia_css_frame_info in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6982 struct ia_css_frame_info *out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6983 struct ia_css_frame_info *vf_out_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
6984 struct ia_css_frame_info tmp_in_info = IA_CSS_BINARY_DEFAULT_FRAME_INFO;
6986 unsigned int hor_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6987 ver_scale_factor[IA_CSS_PIPE_MAX_OUTPUT_STAGE],
6989 unsigned int num_stages = 0;
6990 enum ia_css_err err = IA_CSS_SUCCESS;
6992 unsigned int max_scale_factor_per_stage = MAX_PREFERRED_YUV_DS_PER_STEP;
6994 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
6995 "ia_css_pipe_create_cas_scaler_desc() enter:\n");
6997 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
6999 vf_out_info[i] = NULL;
7000 hor_scale_factor[i] = 0;
7001 ver_scale_factor[i] = 0;
7004 in_info.res = pipe->config.input_effective_res;
7005 in_info.padded_width = in_info.res.width;
7006 descr->num_output_stage = 0;
7007 /* Find out how much scaling we need for each output */
7008 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7009 if (pipe->output_info[i].res.width != 0) {
7010 out_info[i] = &pipe->output_info[i];
7011 if (pipe->vf_output_info[i].res.width != 0)
7012 vf_out_info[i] = &pipe->vf_output_info[i];
7013 descr->num_output_stage += 1;
7017 hor_scale_factor[i] = CEIL_DIV(in_info.res.width, out_info[i]->res.width);
7018 ver_scale_factor[i] = CEIL_DIV(in_info.res.height, out_info[i]->res.height);
7019 /* use the same horizontal and vertical scaling factor for simplicity */
7020 assert(hor_scale_factor[i] == ver_scale_factor[i]);
7024 scale_factor *= max_scale_factor_per_stage;
7025 } while (scale_factor < hor_scale_factor[i]);
7027 in_info.res = out_info[i]->res;
7031 if (need_yuv_scaler_stage(pipe) && (num_stages == 0))
7034 descr->num_stage = num_stages;
7036 descr->in_info = kmalloc_array(descr->num_stage,
7037 sizeof(struct ia_css_frame_info), GFP_KERNEL);
7038 if (!descr->in_info) {
7039 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7042 descr->internal_out_info = kmalloc(descr->num_stage * sizeof(
7043 struct ia_css_frame_info), GFP_KERNEL);
7044 if (!descr->internal_out_info) {
7045 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7048 descr->out_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7050 if (!descr->out_info) {
7051 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7054 descr->vf_info = kmalloc(descr->num_stage * sizeof(struct ia_css_frame_info),
7056 if (!descr->vf_info) {
7057 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7060 descr->is_output_stage = kmalloc(descr->num_stage * sizeof(bool), GFP_KERNEL);
7061 if (!descr->is_output_stage) {
7062 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7066 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7069 assert((out_info[i - 1]->res.width >= out_info[i]->res.width) &&
7070 (out_info[i - 1]->res.height >= out_info[i]->res.height));
7075 tmp_in_info.res = pipe->config.input_effective_res;
7076 tmp_in_info.format = IA_CSS_FRAME_FORMAT_YUV420;
7077 for (i = 0, j = 0; i < descr->num_stage; i++) {
7079 assert(out_info[j]);
7081 descr->in_info[i] = tmp_in_info;
7082 if ((tmp_in_info.res.width / max_scale_factor_per_stage) <=
7083 out_info[j]->res.width) {
7084 descr->is_output_stage[i] = true;
7085 if ((descr->num_output_stage > 1) && (i != (descr->num_stage - 1))) {
7086 descr->internal_out_info[i].res.width = out_info[j]->res.width;
7087 descr->internal_out_info[i].res.height = out_info[j]->res.height;
7088 descr->internal_out_info[i].padded_width = out_info[j]->padded_width;
7089 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7091 assert(i == (descr->num_stage - 1));
7092 descr->internal_out_info[i].res.width = 0;
7093 descr->internal_out_info[i].res.height = 0;
7095 descr->out_info[i].res.width = out_info[j]->res.width;
7096 descr->out_info[i].res.height = out_info[j]->res.height;
7097 descr->out_info[i].padded_width = out_info[j]->padded_width;
7098 descr->out_info[i].format = out_info[j]->format;
7099 if (vf_out_info[j]) {
7100 descr->vf_info[i].res.width = vf_out_info[j]->res.width;
7101 descr->vf_info[i].res.height = vf_out_info[j]->res.height;
7102 descr->vf_info[i].padded_width = vf_out_info[j]->padded_width;
7103 ia_css_frame_info_set_format(&descr->vf_info[i], IA_CSS_FRAME_FORMAT_YUV_LINE);
7105 descr->vf_info[i].res.width = 0;
7106 descr->vf_info[i].res.height = 0;
7107 descr->vf_info[i].padded_width = 0;
7111 descr->is_output_stage[i] = false;
7112 descr->internal_out_info[i].res.width = tmp_in_info.res.width /
7113 max_scale_factor_per_stage;
7114 descr->internal_out_info[i].res.height = tmp_in_info.res.height /
7115 max_scale_factor_per_stage;
7116 descr->internal_out_info[i].format = IA_CSS_FRAME_FORMAT_YUV420;
7117 ia_css_frame_info_init(&descr->internal_out_info[i],
7118 tmp_in_info.res.width / max_scale_factor_per_stage,
7119 tmp_in_info.res.height / max_scale_factor_per_stage,
7120 IA_CSS_FRAME_FORMAT_YUV420, 0);
7121 descr->out_info[i].res.width = 0;
7122 descr->out_info[i].res.height = 0;
7123 descr->vf_info[i].res.width = 0;
7124 descr->vf_info[i].res.height = 0;
7126 tmp_in_info = descr->internal_out_info[i];
7129 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7130 "ia_css_pipe_create_cas_scaler_desc() leave, err=%d\n",
7135 static void ia_css_pipe_destroy_cas_scaler_desc(struct ia_css_cas_binary_descr
7137 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7138 "ia_css_pipe_destroy_cas_scaler_desc() enter:\n");
7139 kfree(descr->in_info);
7140 descr->in_info = NULL;
7141 kfree(descr->internal_out_info);
7142 descr->internal_out_info = NULL;
7143 kfree(descr->out_info);
7144 descr->out_info = NULL;
7145 kfree(descr->vf_info);
7146 descr->vf_info = NULL;
7147 kfree(descr->is_output_stage);
7148 descr->is_output_stage = NULL;
7149 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7150 "ia_css_pipe_destroy_cas_scaler_desc() leave\n");
7153 static enum ia_css_err
7154 load_yuvpp_binaries(struct ia_css_pipe *pipe) {
7155 enum ia_css_err err = IA_CSS_SUCCESS;
7156 bool need_scaler = false;
7157 struct ia_css_frame_info *vf_pp_in_info[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7158 struct ia_css_yuvpp_settings *mycs;
7159 struct ia_css_binary *next_binary;
7160 struct ia_css_cas_binary_descr cas_scaler_descr = { };
7162 bool need_isp_copy_binary = false;
7164 IA_CSS_ENTER_PRIVATE("");
7166 assert(pipe->stream);
7167 assert(pipe->mode == IA_CSS_PIPE_ID_YUVPP);
7169 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7172 /* Set both must_be_raw and must_be_yuv to false then yuvpp can take rgb inputs */
7173 err = ia_css_util_check_input(&pipe->stream->config, false, false);
7174 if (err != IA_CSS_SUCCESS)
7177 mycs = &pipe->pipe_settings.yuvpp;
7179 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7181 if (pipe->vf_output_info[i].res.width != 0) {
7182 err = ia_css_util_check_vf_out_info(&pipe->output_info[i],
7183 &pipe->vf_output_info[i]);
7184 if (err != IA_CSS_SUCCESS)
7187 vf_pp_in_info[i] = NULL;
7190 need_scaler = need_yuv_scaler_stage(pipe);
7192 /* we build up the pipeline starting at the end */
7193 /* Capture post-processing */
7196 struct ia_css_binary_descr yuv_scaler_descr;
7198 err = ia_css_pipe_create_cas_scaler_desc(pipe,
7200 if (err != IA_CSS_SUCCESS)
7202 mycs->num_output = cas_scaler_descr.num_output_stage;
7203 mycs->num_yuv_scaler = cas_scaler_descr.num_stage;
7204 mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage *
7205 sizeof(struct ia_css_binary), GFP_KERNEL);
7206 if (!mycs->yuv_scaler_binary) {
7207 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7210 mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage *
7211 sizeof(bool), GFP_KERNEL);
7212 if (!mycs->is_output_stage) {
7213 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7216 for (i = 0; i < cas_scaler_descr.num_stage; i++) {
7217 mycs->is_output_stage[i] = cas_scaler_descr.is_output_stage[i];
7218 ia_css_pipe_get_yuvscaler_binarydesc(pipe,
7219 &yuv_scaler_descr, &cas_scaler_descr.in_info[i],
7220 &cas_scaler_descr.out_info[i],
7221 &cas_scaler_descr.internal_out_info[i],
7222 &cas_scaler_descr.vf_info[i]);
7223 err = ia_css_binary_find(&yuv_scaler_descr,
7224 &mycs->yuv_scaler_binary[i]);
7225 if (err != IA_CSS_SUCCESS)
7228 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7231 mycs->num_output = 1;
7236 next_binary = &mycs->yuv_scaler_binary[0];
7242 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
7245 * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when
7246 * its input is "ATOMISP_INPUT_FORMAT_YUV422_8"?
7248 * In most use cases, the first stage in the "yuvpp" pipe is the "yuv_scale_
7249 * binary". However, the "yuv_scale_binary" does NOT support the input-frame
7250 * format as "IA_CSS_STREAM _FORMAT_YUV422_8".
7252 * Hence, the "isp_copy_binary" is required to be present in front of the "yuv
7253 * _scale_binary". It would translate the input-frame to the frame formats that
7254 * are supported by the "yuv_scale_binary".
7256 * Please refer to "FrameWork/css/isp/pipes/capture_pp/capture_pp_1.0/capture_
7257 * pp_defs.h" for the list of input-frame formats that are supported by the
7258 * "yuv_scale_binary".
7260 need_isp_copy_binary =
7261 (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8);
7262 #else /* !USE_INPUT_SYSTEM_VERSION_2401 */
7263 need_isp_copy_binary = true;
7264 #endif /* USE_INPUT_SYSTEM_VERSION_2401 */
7266 if (need_isp_copy_binary)
7268 err = load_copy_binary(pipe,
7272 if (err != IA_CSS_SUCCESS)
7277 * - Why is "pipe->pipe_settings.capture.copy_binary.online" specified?
7279 * In some use cases, the first stage in the "yuvpp" pipe is the
7280 * "isp_copy_binary". The "isp_copy_binary" is designed to process
7281 * the input from either the system DDR or from the IPU internal VMEM.
7282 * So it provides the flag "online" to specify where its input is from,
7285 * (1) "online <= true", the input is from the IPU internal VMEM.
7286 * (2) "online <= false", the input is from the system DDR.
7288 * In other use cases, the first stage in the "yuvpp" pipe is the
7289 * "yuv_scale_binary". "The "yuv_scale_binary" is designed to process the
7290 * input ONLY from the system DDR. So it does not provide the flag "online"
7291 * to specify where its input is from.
7293 pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online;
7296 /* Viewfinder post-processing */
7299 for (i = 0, j = 0; i < mycs->num_yuv_scaler; i++) {
7300 if (mycs->is_output_stage[i]) {
7303 &mycs->yuv_scaler_binary[i].vf_frame_info;
7307 mycs->num_vf_pp = j;
7311 &mycs->copy_binary.vf_frame_info;
7312 for (i = 1; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++) {
7313 vf_pp_in_info[i] = NULL;
7315 mycs->num_vf_pp = 1;
7317 mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * sizeof(struct ia_css_binary),
7319 if (!mycs->vf_pp_binary)
7321 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
7326 struct ia_css_binary_descr vf_pp_descr;
7328 for (i = 0; i < mycs->num_vf_pp; i++)
7330 if (pipe->vf_output_info[i].res.width != 0) {
7331 ia_css_pipe_get_vfpp_binarydesc(pipe,
7332 &vf_pp_descr, vf_pp_in_info[i], &pipe->vf_output_info[i]);
7333 err = ia_css_binary_find(&vf_pp_descr, &mycs->vf_pp_binary[i]);
7334 if (err != IA_CSS_SUCCESS)
7340 if (err != IA_CSS_SUCCESS)
7346 ia_css_pipe_destroy_cas_scaler_desc(&cas_scaler_descr);
7348 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "load_yuvpp_binaries() leave, err=%d\n",
7353 static enum ia_css_err
7354 unload_yuvpp_binaries(struct ia_css_pipe *pipe) {
7357 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7359 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7361 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7362 return IA_CSS_ERR_INVALID_ARGUMENTS;
7364 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.copy_binary);
7365 for (i = 0; i < pipe->pipe_settings.yuvpp.num_yuv_scaler; i++)
7367 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.yuv_scaler_binary[i]);
7369 for (i = 0; i < pipe->pipe_settings.yuvpp.num_vf_pp; i++)
7371 ia_css_binary_unload(&pipe->pipe_settings.yuvpp.vf_pp_binary[i]);
7373 kfree(pipe->pipe_settings.yuvpp.is_output_stage);
7374 pipe->pipe_settings.yuvpp.is_output_stage = NULL;
7375 kfree(pipe->pipe_settings.yuvpp.yuv_scaler_binary);
7376 pipe->pipe_settings.yuvpp.yuv_scaler_binary = NULL;
7377 kfree(pipe->pipe_settings.yuvpp.vf_pp_binary);
7378 pipe->pipe_settings.yuvpp.vf_pp_binary = NULL;
7380 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7381 return IA_CSS_SUCCESS;
7384 static enum ia_css_err yuvpp_start(struct ia_css_pipe *pipe) {
7385 struct ia_css_binary *copy_binary;
7386 enum ia_css_err err = IA_CSS_SUCCESS;
7387 enum sh_css_pipe_config_override copy_ovrd;
7388 enum ia_css_input_mode yuvpp_pipe_input_mode;
7390 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7391 if ((!pipe) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) {
7392 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7393 return IA_CSS_ERR_INVALID_ARGUMENTS;
7396 yuvpp_pipe_input_mode = pipe->stream->config.mode;
7398 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7400 sh_css_metrics_start_frame();
7402 /* multi stream video needs mipi buffers */
7404 #if !defined(HAS_NO_INPUT_SYSTEM) && (defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401))
7405 err = send_mipi_frames(pipe);
7406 if (err != IA_CSS_SUCCESS) {
7407 IA_CSS_LEAVE_ERR_PRIVATE(err);
7413 unsigned int thread_id;
7415 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7416 copy_ovrd = 1 << thread_id;
7419 start_pipe(pipe, copy_ovrd, yuvpp_pipe_input_mode);
7421 IA_CSS_LEAVE_ERR_PRIVATE(err);
7425 static enum ia_css_err
7426 sh_css_pipe_unload_binaries(struct ia_css_pipe *pipe) {
7427 enum ia_css_err err = IA_CSS_SUCCESS;
7429 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7433 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7434 return IA_CSS_ERR_INVALID_ARGUMENTS;
7436 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7437 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7439 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7440 return IA_CSS_SUCCESS;
7445 case IA_CSS_PIPE_ID_PREVIEW:
7446 err = unload_preview_binaries(pipe);
7448 case IA_CSS_PIPE_ID_VIDEO:
7449 err = unload_video_binaries(pipe);
7451 case IA_CSS_PIPE_ID_CAPTURE:
7452 err = unload_capture_binaries(pipe);
7454 case IA_CSS_PIPE_ID_YUVPP:
7455 err = unload_yuvpp_binaries(pipe);
7460 IA_CSS_LEAVE_ERR_PRIVATE(err);
7464 static enum ia_css_err
7465 sh_css_pipe_load_binaries(struct ia_css_pipe *pipe) {
7466 enum ia_css_err err = IA_CSS_SUCCESS;
7469 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "sh_css_pipe_load_binaries() enter:\n");
7471 /* PIPE_MODE_COPY has no binaries, but has output frames to outside*/
7472 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
7477 case IA_CSS_PIPE_ID_PREVIEW:
7478 err = load_preview_binaries(pipe);
7480 case IA_CSS_PIPE_ID_VIDEO:
7481 err = load_video_binaries(pipe);
7483 case IA_CSS_PIPE_ID_CAPTURE:
7484 err = load_capture_binaries(pipe);
7486 case IA_CSS_PIPE_ID_YUVPP:
7487 err = load_yuvpp_binaries(pipe);
7489 case IA_CSS_PIPE_ID_ACC:
7492 err = IA_CSS_ERR_INTERNAL_ERROR;
7495 if (err != IA_CSS_SUCCESS)
7497 if (sh_css_pipe_unload_binaries(pipe) != IA_CSS_SUCCESS) {
7498 /* currently css does not support multiple error returns in a single function,
7499 * using IA_CSS_ERR_INTERNAL_ERROR in this case */
7500 err = IA_CSS_ERR_INTERNAL_ERROR;
7506 static enum ia_css_err
7507 create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) {
7508 struct ia_css_pipeline *me;
7509 enum ia_css_err err = IA_CSS_SUCCESS;
7510 struct ia_css_pipeline_stage *vf_pp_stage = NULL,
7512 *yuv_scaler_stage = NULL;
7513 struct ia_css_binary *copy_binary,
7516 bool need_scaler = false;
7517 unsigned int num_stage, num_vf_pp_stage, num_output_stage;
7520 struct ia_css_frame *in_frame = NULL;
7521 struct ia_css_frame *out_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7522 struct ia_css_frame *bin_out_frame[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7523 struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE];
7524 struct ia_css_pipeline_stage_desc stage_desc;
7525 bool need_in_frameinfo_memory = false;
7526 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7527 bool sensor = false;
7528 bool buffered_sensor = false;
7529 bool online = false;
7530 bool continuous = false;
7533 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
7534 if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP))
7536 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
7537 return IA_CSS_ERR_INVALID_ARGUMENTS;
7539 me = &pipe->pipeline;
7540 ia_css_pipeline_clean(me);
7541 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
7543 out_frame[i] = NULL;
7546 ia_css_pipe_util_create_output_frames(bin_out_frame);
7547 num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler;
7548 num_vf_pp_stage = pipe->pipe_settings.yuvpp.num_vf_pp;
7549 num_output_stage = pipe->pipe_settings.yuvpp.num_output;
7551 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7552 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7553 * except for the following:
7554 * - Direct Sensor Mode Online Capture
7555 * - Direct Sensor Mode Continuous Capture
7556 * - Buffered Sensor Mode Continuous Capture
7558 sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR;
7559 buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
7560 online = pipe->stream->config.online;
7561 continuous = pipe->stream->config.continuous;
7562 need_in_frameinfo_memory =
7563 !((sensor && (online || continuous)) || (buffered_sensor && continuous));
7565 /* Construct in_frame info (only in case we have dynamic input */
7566 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7568 /* the input frame can come from:
7569 * a) memory: connect yuvscaler to me->in_frame
7570 * b) sensor, via copy binary: connect yuvscaler to copy binary later on */
7571 if (need_in_frameinfo_memory)
7573 /* TODO: improve for different input formats. */
7576 * "pipe->stream->config.input_config.format" represents the sensor output
7577 * frame format, e.g. YUV422 8-bit.
7579 * "in_frame_format" represents the imaging pipe's input frame format, e.g.
7582 int in_frame_format;
7584 if (pipe->stream->config.input_config.format ==
7585 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY) {
7586 in_frame_format = IA_CSS_FRAME_FORMAT_CSI_MIPI_LEGACY_YUV420_8;
7587 } else if (pipe->stream->config.input_config.format ==
7588 ATOMISP_INPUT_FORMAT_YUV422_8) {
7590 * When the sensor output frame format is "ATOMISP_INPUT_FORMAT_YUV422_8",
7591 * the "isp_copy_var" binary is selected as the first stage in the yuvpp
7594 * For the "isp_copy_var" binary, it reads the YUV422-8 pixels from
7595 * the frame buffer (at DDR) to the frame-line buffer (at VMEM).
7597 * By now, the "isp_copy_var" binary does NOT provide a separated
7598 * frame-line buffer to store the YUV422-8 pixels. Instead, it stores
7599 * the YUV422-8 pixels in the frame-line buffer which is designed to
7600 * store the Bayer-Quad RAW pixels.
7602 * To direct the "isp_copy_var" binary reading from the RAW frame-line
7603 * buffer, its input frame format must be specified as "IA_CSS_FRAME_
7606 in_frame_format = IA_CSS_FRAME_FORMAT_RAW;
7608 in_frame_format = IA_CSS_FRAME_FORMAT_NV12;
7611 err = init_in_frameinfo_memory_defaults(pipe,
7615 if (err != IA_CSS_SUCCESS) {
7616 IA_CSS_LEAVE_ERR_PRIVATE(err);
7620 in_frame = &me->in_frame;
7626 for (i = 0; i < num_output_stage; i++)
7628 assert(i < IA_CSS_PIPE_MAX_OUTPUT_STAGE);
7629 if (pipe->output_info[i].res.width != 0) {
7630 err = init_out_frameinfo_defaults(pipe, &me->out_frame[i], i);
7631 if (err != IA_CSS_SUCCESS) {
7632 IA_CSS_LEAVE_ERR_PRIVATE(err);
7635 out_frame[i] = &me->out_frame[i];
7638 /* Construct vf_frame info (only in case we have VF) */
7639 if (pipe->vf_output_info[i].res.width != 0) {
7640 err = init_vf_frameinfo_defaults(pipe, &me->vf_frame[i], i);
7641 if (err != IA_CSS_SUCCESS) {
7642 IA_CSS_LEAVE_ERR_PRIVATE(err);
7645 vf_frame[i] = &me->vf_frame[i];
7649 copy_binary = &pipe->pipe_settings.yuvpp.copy_binary;
7650 vf_pp_binary = pipe->pipe_settings.yuvpp.vf_pp_binary;
7651 yuv_scaler_binary = pipe->pipe_settings.yuvpp.yuv_scaler_binary;
7652 need_scaler = need_yuv_scaler_stage(pipe);
7654 if (pipe->pipe_settings.yuvpp.copy_binary.info)
7656 struct ia_css_frame *in_frame_local = NULL;
7658 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7659 /* After isp copy is enabled in_frame needs to be passed. */
7661 in_frame_local = in_frame;
7665 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, NULL);
7666 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7667 bin_out_frame, in_frame_local, NULL);
7669 ia_css_pipe_util_set_output_frames(bin_out_frame, 0, out_frame[0]);
7670 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7671 bin_out_frame, in_frame_local, NULL);
7674 err = ia_css_pipeline_create_and_add_stage(me,
7678 if (err != IA_CSS_SUCCESS) {
7679 IA_CSS_LEAVE_ERR_PRIVATE(err);
7684 /* if we use yuv scaler binary, vf output should be from there */
7685 copy_stage->args.copy_vf = !need_scaler;
7686 /* for yuvpp pipe, it should always be enabled */
7687 copy_stage->args.copy_output = true;
7688 /* connect output of copy binary to input of yuv scaler */
7689 in_frame = copy_stage->args.out_frame[0];
7695 struct ia_css_frame *tmp_out_frame = NULL;
7696 struct ia_css_frame *tmp_vf_frame = NULL;
7697 struct ia_css_frame *tmp_in_frame = in_frame;
7699 for (i = 0, j = 0; i < num_stage; i++) {
7700 assert(j < num_output_stage);
7701 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7702 tmp_out_frame = out_frame[j];
7703 tmp_vf_frame = vf_frame[j];
7705 tmp_out_frame = NULL;
7706 tmp_vf_frame = NULL;
7709 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
7711 &yuv_scaler_binary[i],
7714 if (err != IA_CSS_SUCCESS) {
7715 IA_CSS_LEAVE_ERR_PRIVATE(err);
7718 /* we use output port 1 as internal output port */
7719 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
7720 if (pipe->pipe_settings.yuvpp.is_output_stage[i]) {
7721 if (tmp_vf_frame && (tmp_vf_frame->info.res.width != 0)) {
7722 in_frame = yuv_scaler_stage->args.out_vf_frame;
7723 err = add_vf_pp_stage(pipe, in_frame, tmp_vf_frame, &vf_pp_binary[j],
7726 if (err != IA_CSS_SUCCESS) {
7727 IA_CSS_LEAVE_ERR_PRIVATE(err);
7734 } else if (copy_stage)
7736 if (vf_frame[0] && vf_frame[0]->info.res.width != 0) {
7737 in_frame = copy_stage->args.out_vf_frame;
7738 err = add_vf_pp_stage(pipe, in_frame, vf_frame[0], &vf_pp_binary[0],
7741 if (err != IA_CSS_SUCCESS) {
7742 IA_CSS_LEAVE_ERR_PRIVATE(err);
7747 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7749 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
7751 return IA_CSS_SUCCESS;
7754 static enum ia_css_err
7755 create_host_copy_pipeline(struct ia_css_pipe *pipe,
7756 unsigned int max_input_width,
7757 struct ia_css_frame *out_frame) {
7758 struct ia_css_pipeline *me;
7759 enum ia_css_err err = IA_CSS_SUCCESS;
7760 struct ia_css_pipeline_stage_desc stage_desc;
7762 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7763 "create_host_copy_pipeline() enter:\n");
7765 /* pipeline already created as part of create_host_pipeline_structure */
7766 me = &pipe->pipeline;
7767 ia_css_pipeline_clean(me);
7769 /* Construct out_frame info */
7770 out_frame->contiguous = false;
7771 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7773 if (copy_on_sp(pipe) &&
7774 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
7776 ia_css_frame_info_init(
7780 IA_CSS_FRAME_FORMAT_BINARY_8,
7782 } else if (out_frame->info.format == IA_CSS_FRAME_FORMAT_RAW)
7784 out_frame->info.raw_bit_depth =
7785 ia_css_pipe_util_pipe_input_format_bpp(pipe);
7789 me->pipe_id = IA_CSS_PIPE_ID_COPY;
7790 pipe->mode = IA_CSS_PIPE_ID_COPY;
7792 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7793 IA_CSS_PIPELINE_RAW_COPY, max_input_width);
7794 err = ia_css_pipeline_create_and_add_stage(me,
7798 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
7800 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7801 "create_host_copy_pipeline() leave:\n");
7806 static enum ia_css_err
7807 create_host_isyscopy_capture_pipeline(struct ia_css_pipe *pipe) {
7808 struct ia_css_pipeline *me = &pipe->pipeline;
7809 enum ia_css_err err = IA_CSS_SUCCESS;
7810 struct ia_css_pipeline_stage_desc stage_desc;
7811 struct ia_css_frame *out_frame = &me->out_frame[0];
7812 struct ia_css_pipeline_stage *out_stage = NULL;
7813 unsigned int thread_id;
7814 enum sh_css_queue_id queue_id;
7815 unsigned int max_input_width = MAX_VECTORS_PER_INPUT_LINE_CONT * ISP_VEC_NELEMS;
7817 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7818 "create_host_isyscopy_capture_pipeline() enter:\n");
7819 ia_css_pipeline_clean(me);
7821 /* Construct out_frame info */
7822 err = sh_css_pipe_get_output_frame_info(pipe, &out_frame->info, 0);
7823 if (err != IA_CSS_SUCCESS)
7825 out_frame->contiguous = false;
7826 out_frame->flash_state = IA_CSS_FRAME_FLASH_STATE_NONE;
7827 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
7828 ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, &queue_id);
7829 out_frame->dynamic_queue_id = queue_id;
7830 out_frame->buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME;
7833 me->pipe_id = IA_CSS_PIPE_ID_CAPTURE;
7834 pipe->mode = IA_CSS_PIPE_ID_CAPTURE;
7835 ia_css_pipe_get_sp_func_stage_desc(&stage_desc, out_frame,
7836 IA_CSS_PIPELINE_ISYS_COPY, max_input_width);
7837 err = ia_css_pipeline_create_and_add_stage(me,
7838 &stage_desc, &out_stage);
7839 if (err != IA_CSS_SUCCESS)
7842 ia_css_pipeline_finalize_stages(me, pipe->stream->config.continuous);
7844 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
7845 "create_host_isyscopy_capture_pipeline() leave:\n");
7850 static enum ia_css_err
7851 create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) {
7852 struct ia_css_pipeline *me;
7853 enum ia_css_err err = IA_CSS_SUCCESS;
7854 enum ia_css_capture_mode mode;
7855 struct ia_css_pipeline_stage *current_stage = NULL;
7856 struct ia_css_pipeline_stage *yuv_scaler_stage = NULL;
7857 struct ia_css_binary *copy_binary,
7858 *primary_binary[MAX_NUM_PRIMARY_STAGES],
7865 *capture_ldc_binary;
7866 bool need_pp = false;
7869 struct ia_css_frame *in_frame;
7870 struct ia_css_frame *out_frame;
7871 struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS];
7872 struct ia_css_frame *vf_frame;
7873 struct ia_css_pipeline_stage_desc stage_desc;
7874 bool need_in_frameinfo_memory = false;
7875 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7876 bool sensor = false;
7877 bool buffered_sensor = false;
7878 bool online = false;
7879 bool continuous = false;
7881 unsigned int i, num_yuv_scaler, num_primary_stage;
7882 bool need_yuv_pp = false;
7883 bool *is_output_stage = NULL;
7884 bool need_ldc = false;
7886 IA_CSS_ENTER_PRIVATE("");
7888 assert(pipe->stream);
7889 assert(pipe->mode == IA_CSS_PIPE_ID_CAPTURE || pipe->mode == IA_CSS_PIPE_ID_COPY);
7891 me = &pipe->pipeline;
7892 mode = pipe->config.default_capture_config.mode;
7893 raw = (mode == IA_CSS_CAPTURE_MODE_RAW);
7894 ia_css_pipeline_clean(me);
7895 ia_css_pipe_util_create_output_frames(out_frames);
7897 #ifdef USE_INPUT_SYSTEM_VERSION_2401
7898 /* When the input system is 2401, always enable 'in_frameinfo_memory'
7899 * except for the following:
7900 * - Direct Sensor Mode Online Capture
7901 * - Direct Sensor Mode Online Capture
7902 * - Direct Sensor Mode Continuous Capture
7903 * - Buffered Sensor Mode Continuous Capture
7905 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR);
7906 buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR);
7907 online = pipe->stream->config.online;
7908 continuous = pipe->stream->config.continuous;
7909 need_in_frameinfo_memory =
7910 !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous)));
7912 /* Construct in_frame info (only in case we have dynamic input */
7913 need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
7915 if (need_in_frameinfo_memory)
7917 err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame,
7918 IA_CSS_FRAME_FORMAT_RAW);
7919 if (err != IA_CSS_SUCCESS) {
7920 IA_CSS_LEAVE_ERR_PRIVATE(err);
7924 in_frame = &me->in_frame;
7930 err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0);
7931 if (err != IA_CSS_SUCCESS)
7933 IA_CSS_LEAVE_ERR_PRIVATE(err);
7936 out_frame = &me->out_frame[0];
7938 /* Construct vf_frame info (only in case we have VF) */
7939 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
7941 if (mode == IA_CSS_CAPTURE_MODE_RAW || mode == IA_CSS_CAPTURE_MODE_BAYER) {
7942 /* These modes don't support viewfinder output */
7945 init_vf_frameinfo_defaults(pipe, &me->vf_frame[0], 0);
7946 vf_frame = &me->vf_frame[0];
7953 copy_binary = &pipe->pipe_settings.capture.copy_binary;
7954 num_primary_stage = pipe->pipe_settings.capture.num_primary_stage;
7955 if ((num_primary_stage == 0) && (mode == IA_CSS_CAPTURE_MODE_PRIMARY))
7957 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INTERNAL_ERROR);
7958 return IA_CSS_ERR_INTERNAL_ERROR;
7960 for (i = 0; i < num_primary_stage; i++)
7962 primary_binary[i] = &pipe->pipe_settings.capture.primary_binary[i];
7964 vf_pp_binary = &pipe->pipe_settings.capture.vf_pp_binary;
7965 pre_isp_binary = &pipe->pipe_settings.capture.pre_isp_binary;
7966 anr_gdc_binary = &pipe->pipe_settings.capture.anr_gdc_binary;
7967 post_isp_binary = &pipe->pipe_settings.capture.post_isp_binary;
7968 capture_pp_binary = &pipe->pipe_settings.capture.capture_pp_binary;
7969 yuv_scaler_binary = pipe->pipe_settings.capture.yuv_scaler_binary;
7970 num_yuv_scaler = pipe->pipe_settings.capture.num_yuv_scaler;
7971 is_output_stage = pipe->pipe_settings.capture.is_output_stage;
7972 capture_ldc_binary = &pipe->pipe_settings.capture.capture_ldc_binary;
7974 need_pp = (need_capture_pp(pipe) || pipe->output_stage) &&
7975 mode != IA_CSS_CAPTURE_MODE_RAW &&
7976 mode != IA_CSS_CAPTURE_MODE_BAYER;
7977 need_yuv_pp = (yuv_scaler_binary && yuv_scaler_binary->info);
7978 need_ldc = (capture_ldc_binary && capture_ldc_binary->info);
7980 if (pipe->pipe_settings.capture.copy_binary.info)
7983 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
7984 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2401)
7986 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7987 out_frames, in_frame, NULL);
7989 in_frame = pipe->stream->last_pipe->continuous_frames[0];
7990 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7991 out_frames, in_frame, NULL);
7994 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
7995 out_frames, NULL, NULL);
7998 ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame);
7999 ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary,
8000 out_frames, NULL, NULL);
8003 err = ia_css_pipeline_create_and_add_stage(me,
8006 if (err != IA_CSS_SUCCESS) {
8007 IA_CSS_LEAVE_ERR_PRIVATE(err);
8010 } else if (pipe->stream->config.continuous)
8012 in_frame = pipe->stream->last_pipe->continuous_frames[0];
8015 if (mode == IA_CSS_CAPTURE_MODE_PRIMARY)
8017 struct ia_css_frame *local_in_frame = NULL;
8018 struct ia_css_frame *local_out_frame = NULL;
8020 for (i = 0; i < num_primary_stage; i++) {
8022 local_in_frame = in_frame;
8024 local_in_frame = NULL;
8026 if (!need_pp && (i == num_primary_stage - 1))
8028 if (!need_pp && (i == num_primary_stage - 1) && !need_ldc)
8030 local_out_frame = out_frame;
8032 local_out_frame = NULL;
8033 ia_css_pipe_util_set_output_frames(out_frames, 0, local_out_frame);
8035 * WARNING: The #if def flag has been added below as a
8036 * temporary solution to solve the problem of enabling the
8037 * view finder in a single binary in a capture flow. The
8038 * vf-pp stage has been removed from Skycam in the solution
8039 * provided. The vf-pp stage should be re-introduced when
8040 * required. This * should not be considered as a clean solution.
8041 * Proper investigation should be done to come up with the clean
8044 ia_css_pipe_get_generic_stage_desc(&stage_desc, primary_binary[i],
8045 out_frames, local_in_frame, NULL);
8046 err = ia_css_pipeline_create_and_add_stage(me,
8049 if (err != IA_CSS_SUCCESS) {
8050 IA_CSS_LEAVE_ERR_PRIVATE(err);
8054 /* If we use copy iso primary,
8055 the input must be yuv iso raw */
8056 current_stage->args.copy_vf =
8057 primary_binary[0]->info->sp.pipeline.mode ==
8058 IA_CSS_BINARY_MODE_COPY;
8059 current_stage->args.copy_output = current_stage->args.copy_vf;
8060 } else if (mode == IA_CSS_CAPTURE_MODE_ADVANCED ||
8061 mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT)
8063 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8064 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8065 out_frames, in_frame, NULL);
8066 err = ia_css_pipeline_create_and_add_stage(me,
8068 if (err != IA_CSS_SUCCESS) {
8069 IA_CSS_LEAVE_ERR_PRIVATE(err);
8072 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8073 ia_css_pipe_get_generic_stage_desc(&stage_desc, anr_gdc_binary,
8074 out_frames, NULL, NULL);
8075 err = ia_css_pipeline_create_and_add_stage(me,
8077 if (err != IA_CSS_SUCCESS) {
8078 IA_CSS_LEAVE_ERR_PRIVATE(err);
8083 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8084 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8085 out_frames, NULL, NULL);
8087 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8088 ia_css_pipe_get_generic_stage_desc(&stage_desc, post_isp_binary,
8089 out_frames, NULL, NULL);
8092 err = ia_css_pipeline_create_and_add_stage(me,
8093 &stage_desc, ¤t_stage);
8094 if (err != IA_CSS_SUCCESS) {
8095 IA_CSS_LEAVE_ERR_PRIVATE(err);
8098 } else if (mode == IA_CSS_CAPTURE_MODE_BAYER)
8100 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8101 ia_css_pipe_get_generic_stage_desc(&stage_desc, pre_isp_binary,
8102 out_frames, in_frame, NULL);
8103 err = ia_css_pipeline_create_and_add_stage(me,
8106 if (err != IA_CSS_SUCCESS) {
8107 IA_CSS_LEAVE_ERR_PRIVATE(err);
8113 if (need_pp && current_stage)
8115 struct ia_css_frame *local_in_frame = NULL;
8117 local_in_frame = current_stage->args.out_frame[0];
8120 ia_css_pipe_util_set_output_frames(out_frames, 0, NULL);
8121 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8122 out_frames, local_in_frame, NULL);
8123 err = ia_css_pipeline_create_and_add_stage(me,
8126 local_in_frame = current_stage->args.out_frame[0];
8128 err = add_capture_pp_stage(pipe, me, local_in_frame,
8129 need_yuv_pp ? NULL : out_frame,
8131 /* ldc and capture_pp not supported in same pipeline */
8132 if (need_ldc && current_stage)
8134 in_frame = current_stage->args.out_frame[0];
8135 ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame);
8136 ia_css_pipe_get_generic_stage_desc(&stage_desc, capture_ldc_binary,
8137 out_frames, in_frame, NULL);
8138 err = ia_css_pipeline_create_and_add_stage(me,
8141 } else if (need_pp && current_stage)
8143 in_frame = current_stage->args.out_frame[0];
8144 err = add_capture_pp_stage(pipe, me, in_frame, need_yuv_pp ? NULL : out_frame,
8148 if (err != IA_CSS_SUCCESS) {
8149 IA_CSS_LEAVE_ERR_PRIVATE(err);
8154 if (need_yuv_pp && current_stage)
8156 struct ia_css_frame *tmp_in_frame = current_stage->args.out_frame[0];
8157 struct ia_css_frame *tmp_out_frame = NULL;
8159 for (i = 0; i < num_yuv_scaler; i++) {
8160 if (is_output_stage[i] == true)
8161 tmp_out_frame = out_frame;
8163 tmp_out_frame = NULL;
8165 err = add_yuv_scaler_stage(pipe, me, tmp_in_frame, tmp_out_frame,
8167 &yuv_scaler_binary[i],
8169 if (err != IA_CSS_SUCCESS) {
8170 IA_CSS_LEAVE_ERR_PRIVATE(err);
8173 /* we use output port 1 as internal output port */
8174 tmp_in_frame = yuv_scaler_stage->args.out_frame[1];
8179 * WARNING: The #if def flag has been added below as a
8180 * temporary solution to solve the problem of enabling the
8181 * view finder in a single binary in a capture flow. The vf-pp
8182 * stage has been removed from Skycam in the solution provided.
8183 * The vf-pp stage should be re-introduced when required. This
8184 * should not be considered as a clean solution. Proper
8185 * investigation should be done to come up with the clean solution.
8187 if (mode != IA_CSS_CAPTURE_MODE_RAW && mode != IA_CSS_CAPTURE_MODE_BAYER && current_stage && vf_frame)
8189 in_frame = current_stage->args.out_vf_frame;
8190 err = add_vf_pp_stage(pipe, in_frame, vf_frame, vf_pp_binary,
8192 if (err != IA_CSS_SUCCESS) {
8193 IA_CSS_LEAVE_ERR_PRIVATE(err);
8197 ia_css_pipeline_finalize_stages(&pipe->pipeline, pipe->stream->config.continuous);
8199 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8200 "create_host_regular_capture_pipeline() leave:\n");
8202 return IA_CSS_SUCCESS;
8205 static enum ia_css_err
8206 create_host_capture_pipeline(struct ia_css_pipe *pipe) {
8207 enum ia_css_err err = IA_CSS_SUCCESS;
8209 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8211 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY)
8212 err = create_host_isyscopy_capture_pipeline(pipe);
8214 err = create_host_regular_capture_pipeline(pipe);
8215 if (err != IA_CSS_SUCCESS)
8217 IA_CSS_LEAVE_ERR_PRIVATE(err);
8221 IA_CSS_LEAVE_ERR_PRIVATE(err);
8226 static enum ia_css_err capture_start(
8227 struct ia_css_pipe *pipe) {
8228 struct ia_css_pipeline *me;
8230 enum ia_css_err err = IA_CSS_SUCCESS;
8231 enum sh_css_pipe_config_override copy_ovrd;
8233 IA_CSS_ENTER_PRIVATE("pipe = %p", pipe);
8235 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8236 return IA_CSS_ERR_INVALID_ARGUMENTS;
8239 me = &pipe->pipeline;
8241 if ((pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW ||
8242 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) &&
8243 (pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) {
8244 if (copy_on_sp(pipe)) {
8245 err = start_copy_on_sp(pipe, &me->out_frame[0]);
8246 IA_CSS_LEAVE_ERR_PRIVATE(err);
8251 #if defined(USE_INPUT_SYSTEM_VERSION_2)
8252 /* old isys: need to send_mipi_frames() in all pipe modes */
8253 err = send_mipi_frames(pipe);
8254 if (err != IA_CSS_SUCCESS) {
8255 IA_CSS_LEAVE_ERR_PRIVATE(err);
8258 #elif defined(USE_INPUT_SYSTEM_VERSION_2401)
8259 if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) {
8260 err = send_mipi_frames(pipe);
8261 if (err != IA_CSS_SUCCESS) {
8262 IA_CSS_LEAVE_ERR_PRIVATE(err);
8270 unsigned int thread_id;
8272 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
8273 copy_ovrd = 1 << thread_id;
8275 start_pipe(pipe, copy_ovrd, pipe->stream->config.mode);
8277 #if !defined(HAS_NO_INPUT_SYSTEM) && !defined(USE_INPUT_SYSTEM_VERSION_2401)
8279 * old isys: for IA_CSS_PIPE_MODE_COPY pipe, isys rx has to be configured,
8280 * which is currently done in start_binary(); but COPY pipe contains no binary,
8281 * and does not call start_binary(); so we need to configure the rx here.
8283 if (pipe->config.mode == IA_CSS_PIPE_MODE_COPY &&
8284 pipe->stream->reconfigure_css_rx) {
8285 ia_css_isys_rx_configure(&pipe->stream->csi_rx_config,
8286 pipe->stream->config.mode);
8287 pipe->stream->reconfigure_css_rx = false;
8291 IA_CSS_LEAVE_ERR_PRIVATE(err);
8295 static enum ia_css_err
8296 sh_css_pipe_get_output_frame_info(struct ia_css_pipe *pipe,
8297 struct ia_css_frame_info *info,
8302 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8303 "sh_css_pipe_get_output_frame_info() enter:\n");
8305 *info = pipe->output_info[idx];
8306 if (copy_on_sp(pipe) &&
8307 pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8)
8309 ia_css_frame_info_init(
8313 IA_CSS_FRAME_FORMAT_BINARY_8,
8315 } else if (info->format == IA_CSS_FRAME_FORMAT_RAW ||
8316 info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED)
8318 info->raw_bit_depth =
8319 ia_css_pipe_util_pipe_input_format_bpp(pipe);
8322 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8323 "sh_css_pipe_get_output_frame_info() leave:\n");
8324 return IA_CSS_SUCCESS;
8327 #if !defined(HAS_NO_INPUT_SYSTEM)
8329 ia_css_stream_send_input_frame(const struct ia_css_stream *stream,
8330 const unsigned short *data,
8332 unsigned int height) {
8335 ia_css_inputfifo_send_input_frame(
8336 data, width, height,
8337 stream->config.channel_id,
8338 stream->config.input_config.format,
8339 stream->config.pixels_per_clock == 2);
8343 ia_css_stream_start_input_frame(const struct ia_css_stream *stream) {
8346 ia_css_inputfifo_start_frame(
8347 stream->config.channel_id,
8348 stream->config.input_config.format,
8349 stream->config.pixels_per_clock == 2);
8353 ia_css_stream_send_input_line(const struct ia_css_stream *stream,
8354 const unsigned short *data,
8356 const unsigned short *data2,
8357 unsigned int width2) {
8360 ia_css_inputfifo_send_line(stream->config.channel_id,
8361 data, width, data2, width2);
8365 ia_css_stream_send_input_embedded_line(const struct ia_css_stream *stream,
8366 enum atomisp_input_format format,
8367 const unsigned short *data,
8368 unsigned int width) {
8370 if (!data || width == 0)
8372 ia_css_inputfifo_send_embedded_line(stream->config.channel_id,
8373 format, data, width);
8377 ia_css_stream_end_input_frame(const struct ia_css_stream *stream) {
8380 ia_css_inputfifo_end_frame(stream->config.channel_id);
8385 append_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8386 IA_CSS_ENTER_PRIVATE("l = %p, firmware = %p", l, firmware);
8388 IA_CSS_ERROR("NULL fw_info");
8389 IA_CSS_LEAVE_PRIVATE("");
8395 /*firmware->next = NULL;*/ /* when multiple acc extensions are loaded, 'next' can be not NULL */
8396 IA_CSS_LEAVE_PRIVATE("");
8400 remove_firmware(struct ia_css_fw_info **l, struct ia_css_fw_info *firmware) {
8405 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() enter:\n");
8407 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "remove_firmware() leave:\n");
8408 return; /* removing single and multiple firmware is handled in acc_unload_extension() */
8411 static enum ia_css_err upload_isp_code(struct ia_css_fw_info *firmware) {
8415 IA_CSS_ERROR("NULL input parameter");
8416 return IA_CSS_ERR_INVALID_ARGUMENTS;
8418 binary = firmware->info.isp.xmem_addr;
8421 unsigned int size = firmware->blob.size;
8422 const unsigned char *blob;
8423 const unsigned char *binary_name;
8426 (const unsigned char *)(IA_CSS_EXT_ISP_PROG_NAME(
8428 blob = binary_name +
8429 strlen((const char *)binary_name) +
8431 binary = sh_css_load_blob(blob, size);
8432 firmware->info.isp.xmem_addr = binary;
8436 return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
8437 return IA_CSS_SUCCESS;
8440 static enum ia_css_err
8441 acc_load_extension(struct ia_css_fw_info *firmware) {
8442 enum ia_css_err err;
8443 struct ia_css_fw_info *hd = firmware;
8447 err = upload_isp_code(hd);
8448 if (err != IA_CSS_SUCCESS)
8454 return IA_CSS_ERR_INVALID_ARGUMENTS;
8455 firmware->loaded = true;
8456 return IA_CSS_SUCCESS;
8460 acc_unload_extension(struct ia_css_fw_info *firmware) {
8461 struct ia_css_fw_info *hd = firmware;
8462 struct ia_css_fw_info *hdn = NULL;
8464 if (!firmware) /* should not happen */
8466 /* unload and remove multiple firmwares */
8468 hdn = (hd->next) ? &(*hd->next) : NULL;
8469 if (hd->info.isp.xmem_addr) {
8470 hmm_free(hd->info.isp.xmem_addr);
8471 hd->info.isp.xmem_addr = mmgr_NULL;
8473 hd->isp_code = NULL;
8478 firmware->loaded = false;
8481 /* Load firmware for extension */
8482 static enum ia_css_err
8483 ia_css_pipe_load_extension(struct ia_css_pipe *pipe,
8484 struct ia_css_fw_info *firmware) {
8485 enum ia_css_err err = IA_CSS_SUCCESS;
8487 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8489 if ((!firmware) || (!pipe))
8491 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8492 return IA_CSS_ERR_INVALID_ARGUMENTS;
8495 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8496 append_firmware(&pipe->output_stage, firmware);
8497 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8498 append_firmware(&pipe->vf_stage, firmware);
8499 err = acc_load_extension(firmware);
8501 IA_CSS_LEAVE_ERR_PRIVATE(err);
8505 /* Unload firmware for extension */
8507 ia_css_pipe_unload_extension(struct ia_css_pipe *pipe,
8508 struct ia_css_fw_info *firmware) {
8509 IA_CSS_ENTER_PRIVATE("fw = %p pipe = %p", firmware, pipe);
8511 if ((!firmware) || (!pipe)) {
8512 IA_CSS_ERROR("NULL input parameters");
8513 IA_CSS_LEAVE_PRIVATE("");
8517 if (firmware->info.isp.type == IA_CSS_ACC_OUTPUT)
8518 remove_firmware(&pipe->output_stage, firmware);
8519 else if (firmware->info.isp.type == IA_CSS_ACC_VIEWFINDER)
8520 remove_firmware(&pipe->vf_stage, firmware);
8521 acc_unload_extension(firmware);
8523 IA_CSS_LEAVE_PRIVATE("");
8527 ia_css_pipeline_uses_params(struct ia_css_pipeline *me) {
8528 struct ia_css_pipeline_stage *stage;
8532 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8533 "ia_css_pipeline_uses_params() enter: me=%p\n", me);
8535 for (stage = me->stages; stage; stage = stage->next)
8536 if (stage->binary_info && stage->binary_info->enable.params) {
8537 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8538 "ia_css_pipeline_uses_params() leave: return_bool=true\n");
8541 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8542 "ia_css_pipeline_uses_params() leave: return_bool=false\n");
8546 static enum ia_css_err
8547 sh_css_pipeline_add_acc_stage(struct ia_css_pipeline *pipeline,
8548 const void *acc_fw) {
8549 struct ia_css_fw_info *fw = (struct ia_css_fw_info *)acc_fw;
8550 /* In QoS case, load_extension already called, so skipping */
8551 enum ia_css_err err = IA_CSS_SUCCESS;
8553 if (fw->loaded == false)
8554 err = acc_load_extension(fw);
8556 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8557 "sh_css_pipeline_add_acc_stage() enter: pipeline=%p, acc_fw=%p\n",
8560 if (err == IA_CSS_SUCCESS)
8562 struct ia_css_pipeline_stage_desc stage_desc;
8564 ia_css_pipe_get_acc_stage_desc(&stage_desc, NULL, fw);
8565 err = ia_css_pipeline_create_and_add_stage(pipeline,
8570 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8571 "sh_css_pipeline_add_acc_stage() leave: return_err=%d\n", err);
8576 * @brief Tag a specific frame in continuous capture.
8577 * Refer to "sh_css_internal.h" for details.
8579 enum ia_css_err ia_css_stream_capture_frame(struct ia_css_stream *stream,
8580 unsigned int exp_id) {
8581 struct sh_css_tag_descr tag_descr;
8582 u32 encoded_tag_descr;
8583 enum ia_css_err err;
8586 IA_CSS_ENTER("exp_id=%d", exp_id);
8588 /* Only continuous streams have a tagger */
8589 if (exp_id == 0 || !stream->config.continuous) {
8590 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
8591 return IA_CSS_ERR_INVALID_ARGUMENTS;
8594 if (!sh_css_sp_is_running()) {
8595 /* SP is not running. The queues are not valid */
8596 IA_CSS_LEAVE_ERR(IA_CSS_ERR_RESOURCE_NOT_AVAILABLE);
8597 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8600 /* Create the tag descriptor from the parameters */
8601 sh_css_create_tag_descr(0, 0, 0, exp_id, &tag_descr);
8602 /* Encode the tag descriptor into a 32-bit value */
8603 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8604 /* Enqueue the encoded tag to the host2sp queue.
8605 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8606 * on both host and the SP side.
8607 * It is mainly because it is enough to have only one tag_cmd queue */
8608 err = ia_css_bufq_enqueue_tag_cmd(encoded_tag_descr);
8610 IA_CSS_LEAVE_ERR(err);
8615 * @brief Configure the continuous capture.
8616 * Refer to "sh_css_internal.h" for details.
8618 enum ia_css_err ia_css_stream_capture(
8619 struct ia_css_stream *stream,
8623 struct sh_css_tag_descr tag_descr;
8624 unsigned int encoded_tag_descr;
8625 enum ia_css_err return_err;
8628 return IA_CSS_ERR_INVALID_ARGUMENTS;
8630 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8631 "ia_css_stream_capture() enter: num_captures=%d, skip=%d, offset=%d\n",
8632 num_captures, skip, offset);
8634 /* Check if the tag descriptor is valid */
8635 if (num_captures < SH_CSS_MINIMUM_TAG_ID) {
8636 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8637 "ia_css_stream_capture() leave: return_err=%d\n",
8638 IA_CSS_ERR_INVALID_ARGUMENTS);
8639 return IA_CSS_ERR_INVALID_ARGUMENTS;
8642 /* Create the tag descriptor from the parameters */
8643 sh_css_create_tag_descr(num_captures, skip, offset, 0, &tag_descr);
8645 /* Encode the tag descriptor into a 32-bit value */
8646 encoded_tag_descr = sh_css_encode_tag_descr(&tag_descr);
8648 if (!sh_css_sp_is_running()) {
8649 /* SP is not running. The queues are not valid */
8650 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8651 "ia_css_stream_capture() leaving:queues unavailable\n");
8652 return IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
8655 /* Enqueue the encoded tag to the host2sp queue.
8656 * Note: The pipe and stage IDs for tag_cmd queue are hard-coded to 0
8657 * on both host and the SP side.
8658 * It is mainly because it is enough to have only one tag_cmd queue */
8659 return_err = ia_css_bufq_enqueue_tag_cmd((uint32_t)encoded_tag_descr);
8661 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8662 "ia_css_stream_capture() leave: return_err=%d\n",
8668 void ia_css_stream_request_flash(struct ia_css_stream *stream) {
8672 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8673 "ia_css_stream_request_flash() enter: void\n");
8676 sh_css_write_host2sp_command(host2sp_cmd_start_flash);
8678 if (sh_css_sp_is_running()) {
8679 if (!sh_css_write_host2sp_command(host2sp_cmd_start_flash)) {
8680 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
8681 ia_css_debug_dump_sp_sw_debug_info();
8682 ia_css_debug_dump_debug_info(NULL);
8685 IA_CSS_LOG("SP is not running!");
8688 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
8689 "ia_css_stream_request_flash() leave: return_void\n");
8693 sh_css_init_host_sp_control_vars(void) {
8694 const struct ia_css_fw_info *fw;
8695 unsigned int HIVE_ADDR_ia_css_ispctrl_sp_isp_started;
8697 unsigned int HIVE_ADDR_host_sp_queues_initialized;
8698 unsigned int HIVE_ADDR_sp_sleep_mode;
8699 unsigned int HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8701 unsigned int HIVE_ADDR_sp_stop_copy_preview;
8703 unsigned int HIVE_ADDR_host_sp_com;
8704 unsigned int o = offsetof(struct host_sp_communication, host2sp_command)
8707 #if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401)
8711 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8712 "sh_css_init_host_sp_control_vars() enter: void\n");
8715 HIVE_ADDR_ia_css_ispctrl_sp_isp_started = fw->info.sp.isp_started;
8717 HIVE_ADDR_host_sp_queues_initialized =
8718 fw->info.sp.host_sp_queues_initialized;
8719 HIVE_ADDR_sp_sleep_mode = fw->info.sp.sleep_mode;
8720 HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb = fw->info.sp.invalidate_tlb;
8722 HIVE_ADDR_sp_stop_copy_preview = fw->info.sp.stop_copy_preview;
8724 HIVE_ADDR_host_sp_com = fw->info.sp.host_sp_com;
8726 (void)HIVE_ADDR_ia_css_ispctrl_sp_isp_started; /* Suppres warnings in CRUN */
8728 (void)HIVE_ADDR_sp_sleep_mode;
8729 (void)HIVE_ADDR_ia_css_dmaproxy_sp_invalidate_tlb;
8731 (void)HIVE_ADDR_sp_stop_copy_preview;
8733 (void)HIVE_ADDR_host_sp_com;
8735 sp_dmem_store_uint32(SP0_ID,
8736 (unsigned int)sp_address_of(ia_css_ispctrl_sp_isp_started),
8739 sp_dmem_store_uint32(SP0_ID,
8740 (unsigned int)sp_address_of(host_sp_queues_initialized),
8742 sp_dmem_store_uint32(SP0_ID,
8743 (unsigned int)sp_address_of(sp_sleep_mode),
8745 sp_dmem_store_uint32(SP0_ID,
8746 (unsigned int)sp_address_of(ia_css_dmaproxy_sp_invalidate_tlb),
8749 sp_dmem_store_uint32(SP0_ID,
8750 (unsigned int)sp_address_of(sp_stop_copy_preview),
8751 my_css.stop_copy_preview ? (uint32_t)(1) : (uint32_t)(0));
8753 store_sp_array_uint(host_sp_com, o, host2sp_cmd_ready);
8755 #if !defined(HAS_NO_INPUT_SYSTEM)
8756 for (i = 0; i < N_CSI_PORTS; i++) {
8757 sh_css_update_host2sp_num_mipi_frames
8758 (my_css.num_mipi_frames[i]);
8762 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE,
8763 "sh_css_init_host_sp_control_vars() leave: return_void\n");
8767 * create the internal structures and fill in the configuration data
8769 void ia_css_pipe_config_defaults(struct ia_css_pipe_config *pipe_config) {
8770 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_config_defaults()\n");
8771 *pipe_config = DEFAULT_PIPE_CONFIG;
8775 ia_css_pipe_extra_config_defaults(struct ia_css_pipe_extra_config
8777 if (!extra_config) {
8778 IA_CSS_ERROR("NULL input parameter");
8782 extra_config->enable_raw_binning = false;
8783 extra_config->enable_yuv_ds = false;
8784 extra_config->enable_high_speed = false;
8785 extra_config->enable_dvs_6axis = false;
8786 extra_config->enable_reduced_pipe = false;
8787 extra_config->disable_vf_pp = false;
8788 extra_config->enable_fractional_ds = false;
8791 void ia_css_stream_config_defaults(struct ia_css_stream_config *stream_config) {
8792 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_config_defaults()\n");
8793 assert(stream_config);
8794 memset(stream_config, 0, sizeof(*stream_config));
8795 stream_config->online = true;
8796 stream_config->left_padding = -1;
8797 stream_config->pixels_per_clock = 1;
8798 /* temporary default value for backwards compatibility.
8799 * This field used to be hardcoded within CSS but this has now
8800 * been moved to the stream_config struct. */
8801 stream_config->source.port.rxcount = 0x04040404;
8804 static enum ia_css_err
8805 ia_css_acc_pipe_create(struct ia_css_pipe *pipe) {
8806 enum ia_css_err err = IA_CSS_SUCCESS;
8810 IA_CSS_ERROR("NULL input parameter");
8811 return IA_CSS_ERR_INVALID_ARGUMENTS;
8814 /* There is not meaning for num_execs = 0 semantically. Run atleast once. */
8815 if (pipe->config.acc_num_execs == 0)
8816 pipe->config.acc_num_execs = 1;
8818 if (pipe->config.acc_extension)
8820 err = ia_css_pipe_load_extension(pipe, pipe->config.acc_extension);
8827 ia_css_pipe_create(const struct ia_css_pipe_config *config,
8828 struct ia_css_pipe **pipe) {
8832 enum ia_css_err err = IA_CSS_SUCCESS;
8834 IA_CSS_ENTER_PRIVATE("config = %p, pipe = %p", config, pipe);
8838 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8840 return IA_CSS_ERR_INVALID_ARGUMENTS;
8847 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8849 return IA_CSS_ERR_INVALID_ARGUMENTS;
8851 return ia_css_pipe_create_extra(config, NULL, pipe);
8855 err = ia_css_pipe_create_extra(config, NULL, pipe);
8857 if (err == IA_CSS_SUCCESS)
8859 IA_CSS_LOG("pipe created successfully = %p", *pipe);
8862 IA_CSS_LEAVE_ERR_PRIVATE(err);
8869 ia_css_pipe_create_extra(const struct ia_css_pipe_config *config,
8870 const struct ia_css_pipe_extra_config *extra_config,
8871 struct ia_css_pipe **pipe) {
8872 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
8873 struct ia_css_pipe *internal_pipe = NULL;
8876 IA_CSS_ENTER_PRIVATE("config = %p, extra_config = %p and pipe = %p", config, extra_config, pipe);
8878 /* do not allow to create more than the maximum limit */
8879 if (my_css.pipe_counter >= IA_CSS_PIPELINE_NUM_MAX)
8881 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_RESOURCE_EXHAUSTED);
8882 return IA_CSS_ERR_INVALID_ARGUMENTS;
8885 if ((!pipe) || (!config))
8887 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
8888 return IA_CSS_ERR_INVALID_ARGUMENTS;
8891 ia_css_debug_dump_pipe_config(config);
8892 ia_css_debug_dump_pipe_extra_config(extra_config);
8894 err = create_pipe(config->mode, &internal_pipe, false);
8895 if (err != IA_CSS_SUCCESS)
8897 IA_CSS_LEAVE_ERR_PRIVATE(err);
8901 /* now we have a pipe structure to fill */
8902 internal_pipe->config = *config;
8904 internal_pipe->extra_config = *extra_config;
8906 ia_css_pipe_extra_config_defaults(&internal_pipe->extra_config);
8908 if (config->mode == IA_CSS_PIPE_MODE_ACC)
8910 /* Temporary hack to migrate acceleration to CSS 2.0.
8911 * In the future the code for all pipe types should be
8913 *pipe = internal_pipe;
8914 if (!internal_pipe->config.acc_extension &&
8915 internal_pipe->config.num_acc_stages ==
8916 0) { /* if no acc binary and no standalone stage */
8918 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
8919 return IA_CSS_SUCCESS;
8921 return ia_css_acc_pipe_create(internal_pipe);
8924 /* Use config value when dvs_frame_delay setting equal to 2, otherwise always 1 by default */
8925 if (internal_pipe->config.dvs_frame_delay == IA_CSS_FRAME_DELAY_2)
8926 internal_pipe->dvs_frame_delay = 2;
8928 internal_pipe->dvs_frame_delay = 1;
8930 /* we still keep enable_raw_binning for backward compatibility, for any new
8931 fractional bayer downscaling, we should use bayer_ds_out_res. if both are
8932 specified, bayer_ds_out_res will take precedence.if none is specified, we
8933 set bayer_ds_out_res equal to IF output resolution(IF may do cropping on
8934 sensor output) or use default decimation factor 1. */
8935 if (internal_pipe->extra_config.enable_raw_binning &&
8936 internal_pipe->config.bayer_ds_out_res.width)
8938 /* fill some code here, if no code is needed, please remove it during integration */
8941 /* YUV downscaling */
8942 if ((internal_pipe->config.vf_pp_in_res.width ||
8943 internal_pipe->config.capt_pp_in_res.width))
8945 enum ia_css_frame_format format;
8947 if (internal_pipe->config.vf_pp_in_res.width) {
8948 format = IA_CSS_FRAME_FORMAT_YUV_LINE;
8949 ia_css_frame_info_init(
8950 &internal_pipe->vf_yuv_ds_input_info,
8951 internal_pipe->config.vf_pp_in_res.width,
8952 internal_pipe->config.vf_pp_in_res.height,
8955 if (internal_pipe->config.capt_pp_in_res.width) {
8956 format = IA_CSS_FRAME_FORMAT_YUV420;
8957 ia_css_frame_info_init(
8958 &internal_pipe->out_yuv_ds_input_info,
8959 internal_pipe->config.capt_pp_in_res.width,
8960 internal_pipe->config.capt_pp_in_res.height,
8964 if (internal_pipe->config.vf_pp_in_res.width &&
8965 internal_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
8967 ia_css_frame_info_init(
8968 &internal_pipe->vf_yuv_ds_input_info,
8969 internal_pipe->config.vf_pp_in_res.width,
8970 internal_pipe->config.vf_pp_in_res.height,
8971 IA_CSS_FRAME_FORMAT_YUV_LINE, 0);
8973 /* handle bayer downscaling output info */
8974 if (internal_pipe->config.bayer_ds_out_res.width)
8976 ia_css_frame_info_init(
8977 &internal_pipe->bds_output_info,
8978 internal_pipe->config.bayer_ds_out_res.width,
8979 internal_pipe->config.bayer_ds_out_res.height,
8980 IA_CSS_FRAME_FORMAT_RAW, 0);
8983 /* handle output info, assume always needed */
8984 for (i = 0; i < IA_CSS_PIPE_MAX_OUTPUT_STAGE; i++)
8986 if (internal_pipe->config.output_info[i].res.width) {
8987 err = sh_css_pipe_configure_output(
8989 internal_pipe->config.output_info[i].res.width,
8990 internal_pipe->config.output_info[i].res.height,
8991 internal_pipe->config.output_info[i].padded_width,
8992 internal_pipe->config.output_info[i].format,
8994 if (err != IA_CSS_SUCCESS) {
8995 IA_CSS_LEAVE_ERR_PRIVATE(err);
8996 kvfree(internal_pipe);
8997 internal_pipe = NULL;
9002 /* handle vf output info, when configured */
9003 internal_pipe->enable_viewfinder[i] =
9004 (internal_pipe->config.vf_output_info[i].res.width != 0);
9005 if (internal_pipe->config.vf_output_info[i].res.width) {
9006 err = sh_css_pipe_configure_viewfinder(
9008 internal_pipe->config.vf_output_info[i].res.width,
9009 internal_pipe->config.vf_output_info[i].res.height,
9010 internal_pipe->config.vf_output_info[i].padded_width,
9011 internal_pipe->config.vf_output_info[i].format,
9013 if (err != IA_CSS_SUCCESS) {
9014 IA_CSS_LEAVE_ERR_PRIVATE(err);
9015 kvfree(internal_pipe);
9016 internal_pipe = NULL;
9021 if (internal_pipe->config.acc_extension)
9023 err = ia_css_pipe_load_extension(internal_pipe,
9024 internal_pipe->config.acc_extension);
9025 if (err != IA_CSS_SUCCESS) {
9026 IA_CSS_LEAVE_ERR_PRIVATE(err);
9027 kvfree(internal_pipe);
9031 /* set all info to zeroes first */
9032 memset(&internal_pipe->info, 0, sizeof(internal_pipe->info));
9034 /* all went well, return the pipe */
9035 *pipe = internal_pipe;
9036 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9037 return IA_CSS_SUCCESS;
9041 ia_css_pipe_get_info(const struct ia_css_pipe *pipe,
9042 struct ia_css_pipe_info *pipe_info) {
9043 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9044 "ia_css_pipe_get_info()\n");
9048 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9049 "ia_css_pipe_get_info: pipe_info cannot be NULL\n");
9050 return IA_CSS_ERR_INVALID_ARGUMENTS;
9052 if (!pipe || !pipe->stream)
9054 ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR,
9055 "ia_css_pipe_get_info: ia_css_stream_create needs to be called before ia_css_[stream/pipe]_get_info\n");
9056 return IA_CSS_ERR_INVALID_ARGUMENTS;
9058 /* we succeeded return the info */
9059 *pipe_info = pipe->info;
9060 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_pipe_get_info() leave\n");
9061 return IA_CSS_SUCCESS;
9064 bool ia_css_pipe_has_dvs_stats(struct ia_css_pipe_info *pipe_info) {
9068 for (i = 0; i < IA_CSS_DVS_STAT_NUM_OF_LEVELS; i++) {
9069 if (pipe_info->grid_info.dvs_grid.dvs_stat_grid_info.grd_cfg[i].grd_start.enable)
9078 ia_css_pipe_override_frame_format(struct ia_css_pipe *pipe,
9080 enum ia_css_frame_format new_format) {
9081 enum ia_css_err err = IA_CSS_SUCCESS;
9083 IA_CSS_ENTER_PRIVATE("pipe = %p, pin_index = %d, new_formats = %d", pipe, pin_index, new_format);
9087 IA_CSS_ERROR("pipe is not set");
9088 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9089 IA_CSS_LEAVE_ERR_PRIVATE(err);
9092 if (0 != pin_index && 1 != pin_index)
9094 IA_CSS_ERROR("pin index is not valid");
9095 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9096 IA_CSS_LEAVE_ERR_PRIVATE(err);
9099 if (new_format != IA_CSS_FRAME_FORMAT_NV12_TILEY)
9101 IA_CSS_ERROR("new format is not valid");
9102 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9103 IA_CSS_LEAVE_ERR_PRIVATE(err);
9107 err = ia_css_pipe_check_format(pipe, new_format);
9108 if (err == IA_CSS_SUCCESS) {
9109 if (pin_index == 0) {
9110 pipe->output_info[0].format = new_format;
9112 pipe->vf_output_info[0].format = new_format;
9116 IA_CSS_LEAVE_ERR_PRIVATE(err);
9120 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9121 /* Configuration of INPUT_SYSTEM_VERSION_2401 is done on SP */
9122 static enum ia_css_err
9123 ia_css_stream_configure_rx(struct ia_css_stream *stream) {
9124 struct ia_css_input_port *config;
9128 config = &stream->config.source.port;
9129 /* AM: this code is not reliable, especially for 2400 */
9130 if (config->num_lanes == 1)
9131 stream->csi_rx_config.mode = MONO_1L_1L_0L;
9132 else if (config->num_lanes == 2)
9133 stream->csi_rx_config.mode = MONO_2L_1L_0L;
9134 else if (config->num_lanes == 3)
9135 stream->csi_rx_config.mode = MONO_3L_1L_0L;
9136 else if (config->num_lanes == 4)
9137 stream->csi_rx_config.mode = MONO_4L_1L_0L;
9138 else if (config->num_lanes != 0)
9139 return IA_CSS_ERR_INVALID_ARGUMENTS;
9141 if (config->port > MIPI_PORT2_ID)
9142 return IA_CSS_ERR_INVALID_ARGUMENTS;
9143 stream->csi_rx_config.port =
9144 ia_css_isys_port_to_mipi_port(config->port);
9145 stream->csi_rx_config.timeout = config->timeout;
9146 stream->csi_rx_config.initcount = 0;
9147 stream->csi_rx_config.synccount = 0x28282828;
9148 stream->csi_rx_config.rxcount = config->rxcount;
9149 if (config->compression.type == IA_CSS_CSI2_COMPRESSION_TYPE_NONE)
9150 stream->csi_rx_config.comp = MIPI_PREDICTOR_NONE;
9153 /* not implemented yet, requires extension of the rx_cfg_t
9155 return IA_CSS_ERR_INVALID_ARGUMENTS;
9157 stream->csi_rx_config.is_two_ppc = (stream->config.pixels_per_clock == 2);
9158 stream->reconfigure_css_rx = true;
9159 return IA_CSS_SUCCESS;
9163 static struct ia_css_pipe *
9164 find_pipe(struct ia_css_pipe *pipes[],
9165 unsigned int num_pipes,
9166 enum ia_css_pipe_mode mode,
9171 for (i = 0; i < num_pipes; i++) {
9173 if (pipes[i]->config.mode != mode)
9175 if (copy_pipe && pipes[i]->mode != IA_CSS_PIPE_ID_COPY)
9182 static enum ia_css_err
9183 ia_css_acc_stream_create(struct ia_css_stream *stream) {
9185 enum ia_css_err err = IA_CSS_SUCCESS;
9188 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9192 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9193 return IA_CSS_ERR_INVALID_ARGUMENTS;
9196 for (i = 0; i < stream->num_pipes; i++)
9198 struct ia_css_pipe *pipe = stream->pipes[i];
9202 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_ERR_INVALID_ARGUMENTS);
9203 return IA_CSS_ERR_INVALID_ARGUMENTS;
9206 pipe->stream = stream;
9209 /* Map SP threads before doing anything. */
9210 err = map_sp_threads(stream, true);
9211 if (err != IA_CSS_SUCCESS)
9213 IA_CSS_LEAVE_ERR_PRIVATE(err);
9217 for (i = 0; i < stream->num_pipes; i++)
9219 struct ia_css_pipe *pipe = stream->pipes[i];
9222 ia_css_pipe_map_queue(pipe, true);
9225 err = create_host_pipeline_structure(stream);
9226 if (err != IA_CSS_SUCCESS)
9228 IA_CSS_LEAVE_ERR_PRIVATE(err);
9232 stream->started = false;
9234 IA_CSS_LEAVE_ERR_PRIVATE(IA_CSS_SUCCESS);
9236 return IA_CSS_SUCCESS;
9239 static enum ia_css_err
9240 metadata_info_init(const struct ia_css_metadata_config *mdc,
9241 struct ia_css_metadata_info *md) {
9242 /* Either both width and height should be set or neither */
9243 if ((mdc->resolution.height > 0) ^ (mdc->resolution.width > 0))
9244 return IA_CSS_ERR_INVALID_ARGUMENTS;
9246 md->resolution = mdc->resolution;
9247 /* We round up the stride to a multiple of the width
9248 * of the port going to DDR, this is a HW requirements (DMA). */
9249 md->stride = CEIL_MUL(mdc->resolution.width, HIVE_ISP_DDR_WORD_BYTES);
9250 md->size = mdc->resolution.height * md->stride;
9251 return IA_CSS_SUCCESS;
9255 static enum ia_css_err check_pipe_resolutions(const struct ia_css_pipe *pipe) {
9256 enum ia_css_err err = IA_CSS_SUCCESS;
9258 IA_CSS_ENTER_PRIVATE("");
9260 if (!pipe || !pipe->stream) {
9261 IA_CSS_ERROR("null arguments");
9262 err = IA_CSS_ERR_INTERNAL_ERROR;
9266 if (ia_css_util_check_res(pipe->config.input_effective_res.width,
9267 pipe->config.input_effective_res.height) != IA_CSS_SUCCESS) {
9268 IA_CSS_ERROR("effective resolution not supported");
9269 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9272 if (!ia_css_util_resolution_is_zero(
9273 pipe->stream->config.input_config.input_res)) {
9274 if (!ia_css_util_res_leq(pipe->config.input_effective_res,
9275 pipe->stream->config.input_config.input_res)) {
9276 IA_CSS_ERROR("effective resolution is larger than input resolution");
9277 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9281 if (!ia_css_util_resolution_is_even(pipe->config.output_info[0].res)) {
9282 IA_CSS_ERROR("output resolution must be even");
9283 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9286 if (!ia_css_util_resolution_is_even(pipe->config.vf_output_info[0].res)) {
9287 IA_CSS_ERROR("VF resolution must be even");
9288 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9292 IA_CSS_LEAVE_ERR_PRIVATE(err);
9297 ia_css_stream_create(const struct ia_css_stream_config *stream_config,
9299 struct ia_css_pipe *pipes[],
9300 struct ia_css_stream **stream) {
9301 struct ia_css_pipe *curr_pipe;
9302 struct ia_css_stream *curr_stream = NULL;
9304 bool sensor_binning_changed;
9306 enum ia_css_err err = IA_CSS_ERR_INTERNAL_ERROR;
9307 struct ia_css_metadata_info md_info;
9308 struct ia_css_resolution effective_res;
9309 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9310 bool aspect_ratio_crop_enabled = false;
9313 IA_CSS_ENTER("num_pipes=%d", num_pipes);
9314 ia_css_debug_dump_stream_config(stream_config, num_pipes);
9317 if (num_pipes == 0 ||
9321 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9322 IA_CSS_LEAVE_ERR(err);
9326 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9327 /* We don't support metadata for JPEG stream, since they both use str2mem */
9328 if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 &&
9329 stream_config->metadata_config.resolution.height > 0)
9331 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9332 IA_CSS_LEAVE_ERR(err);
9337 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9338 if (stream_config->online && stream_config->pack_raw_pixels)
9340 IA_CSS_LOG("online and pack raw is invalid on input system 2401");
9341 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9342 IA_CSS_LEAVE_ERR(err);
9347 #if !defined(HAS_NO_INPUT_SYSTEM)
9348 ia_css_debug_pipe_graph_dump_stream_config(stream_config);
9350 /* check if mipi size specified */
9351 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
9352 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9353 if (!stream_config->online)
9356 unsigned int port = (unsigned int)stream_config->source.port.port;
9358 if (port >= N_MIPI_PORT_ID) {
9359 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9360 IA_CSS_LEAVE_ERR(err);
9364 if (my_css.size_mem_words != 0) {
9365 my_css.mipi_frame_size[port] = my_css.size_mem_words;
9366 } else if (stream_config->mipi_buffer_config.size_mem_words != 0) {
9367 my_css.mipi_frame_size[port] = stream_config->mipi_buffer_config.size_mem_words;
9369 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9370 "ia_css_stream_create() exit: error, need to set mipi frame size.\n");
9371 assert(stream_config->mipi_buffer_config.size_mem_words != 0);
9372 err = IA_CSS_ERR_INTERNAL_ERROR;
9373 IA_CSS_LEAVE_ERR(err);
9377 if (my_css.size_mem_words != 0) {
9378 my_css.num_mipi_frames[port] =
9379 2; /* Temp change: Default for backwards compatibility. */
9380 } else if (stream_config->mipi_buffer_config.nof_mipi_buffers != 0) {
9381 my_css.num_mipi_frames[port] =
9382 stream_config->mipi_buffer_config.nof_mipi_buffers;
9384 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
9385 "ia_css_stream_create() exit: error, need to set number of mipi frames.\n");
9386 assert(stream_config->mipi_buffer_config.nof_mipi_buffers != 0);
9387 err = IA_CSS_ERR_INTERNAL_ERROR;
9388 IA_CSS_LEAVE_ERR(err);
9394 /* Currently we only supported metadata up to a certain size. */
9395 err = metadata_info_init(&stream_config->metadata_config, &md_info);
9396 if (err != IA_CSS_SUCCESS)
9398 IA_CSS_LEAVE_ERR(err);
9402 /* allocate the stream instance */
9403 curr_stream = kmalloc(sizeof(struct ia_css_stream), GFP_KERNEL);
9406 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9407 IA_CSS_LEAVE_ERR(err);
9410 /* default all to 0 */
9411 memset(curr_stream, 0, sizeof(struct ia_css_stream));
9412 curr_stream->info.metadata_info = md_info;
9414 /* allocate pipes */
9415 curr_stream->num_pipes = num_pipes;
9416 curr_stream->pipes = kcalloc(num_pipes, sizeof(struct ia_css_pipe *), GFP_KERNEL);
9417 if (!curr_stream->pipes)
9419 curr_stream->num_pipes = 0;
9422 err = IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY;
9423 IA_CSS_LEAVE_ERR(err);
9427 spcopyonly = (num_pipes == 1) && (pipes[0]->config.mode == IA_CSS_PIPE_MODE_COPY);
9428 for (i = 0; i < num_pipes; i++)
9429 curr_stream->pipes[i] = pipes[i];
9430 curr_stream->last_pipe = curr_stream->pipes[0];
9431 /* take over stream config */
9432 curr_stream->config = *stream_config;
9434 #if defined(USE_INPUT_SYSTEM_VERSION_2401) && defined(CSI2P_DISABLE_ISYS2401_ONLINE_MODE)
9435 if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR &&
9436 stream_config->online)
9437 curr_stream->config.online = false;
9440 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9441 if (curr_stream->config.online)
9443 curr_stream->config.source.port.num_lanes =
9444 stream_config->source.port.num_lanes;
9445 curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9448 /* in case driver doesn't configure init number of raw buffers, configure it here */
9449 if (curr_stream->config.target_num_cont_raw_buf == 0)
9450 curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES;
9451 if (curr_stream->config.init_num_cont_raw_buf == 0)
9452 curr_stream->config.init_num_cont_raw_buf = curr_stream->config.target_num_cont_raw_buf;
9454 /* Enable locking & unlocking of buffers in RAW buffer pool */
9455 if (curr_stream->config.ia_css_enable_raw_buffer_locking)
9456 sh_css_sp_configure_enable_raw_pool_locking(
9457 curr_stream->config.lock_all);
9459 /* copy mode specific stuff */
9460 switch (curr_stream->config.mode)
9462 case IA_CSS_INPUT_MODE_SENSOR:
9463 case IA_CSS_INPUT_MODE_BUFFERED_SENSOR:
9464 #if defined(USE_INPUT_SYSTEM_VERSION_2)
9465 ia_css_stream_configure_rx(curr_stream);
9468 case IA_CSS_INPUT_MODE_TPG:
9469 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9470 IA_CSS_LOG("tpg_configuration: x_mask=%d, y_mask=%d, x_delta=%d, y_delta=%d, xy_mask=%d",
9471 curr_stream->config.source.tpg.x_mask,
9472 curr_stream->config.source.tpg.y_mask,
9473 curr_stream->config.source.tpg.x_delta,
9474 curr_stream->config.source.tpg.y_delta,
9475 curr_stream->config.source.tpg.xy_mask);
9477 sh_css_sp_configure_tpg(
9478 curr_stream->config.source.tpg.x_mask,
9479 curr_stream->config.source.tpg.y_mask,
9480 curr_stream->config.source.tpg.x_delta,
9481 curr_stream->config.source.tpg.y_delta,
9482 curr_stream->config.source.tpg.xy_mask);
9485 case IA_CSS_INPUT_MODE_PRBS:
9486 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9487 IA_CSS_LOG("mode prbs");
9488 sh_css_sp_configure_prbs(curr_stream->config.source.prbs.seed);
9491 case IA_CSS_INPUT_MODE_MEMORY:
9492 IA_CSS_LOG("mode memory");
9493 curr_stream->reconfigure_css_rx = false;
9496 IA_CSS_LOG("mode sensor/default");
9499 #ifdef USE_INPUT_SYSTEM_VERSION_2401
9500 err = aspect_ratio_crop_init(curr_stream,
9502 &aspect_ratio_crop_enabled);
9503 if (err != IA_CSS_SUCCESS)
9505 IA_CSS_LEAVE_ERR(err);
9509 for (i = 0; i < num_pipes; i++)
9511 struct ia_css_resolution effective_res;
9513 curr_pipe = pipes[i];
9514 /* set current stream */
9515 curr_pipe->stream = curr_stream;
9516 /* take over effective info */
9518 effective_res = curr_pipe->config.input_effective_res;
9519 if (effective_res.height == 0 || effective_res.width == 0) {
9520 effective_res = curr_pipe->stream->config.input_config.effective_res;
9522 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9523 /* The aspect ratio cropping is currently only
9524 * supported on the new input system. */
9525 if (aspect_ratio_crop_check(aspect_ratio_crop_enabled, curr_pipe)) {
9526 struct ia_css_resolution crop_res;
9528 err = aspect_ratio_crop(curr_pipe, &crop_res);
9529 if (err == IA_CSS_SUCCESS) {
9530 effective_res = crop_res;
9532 /* in case of error fallback to default
9533 * effective resolution from driver. */
9534 IA_CSS_LOG("aspect_ratio_crop() failed with err(%d)", err);
9538 curr_pipe->config.input_effective_res = effective_res;
9540 IA_CSS_LOG("effective_res=%dx%d",
9541 effective_res.width,
9542 effective_res.height);
9545 if (atomisp_hw_is_isp2401) {
9546 for (i = 0; i < num_pipes; i++) {
9547 if (pipes[i]->config.mode != IA_CSS_PIPE_MODE_ACC &&
9548 pipes[i]->config.mode != IA_CSS_PIPE_MODE_COPY) {
9549 err = check_pipe_resolutions(pipes[i]);
9550 if (err != IA_CSS_SUCCESS) {
9557 err = ia_css_stream_isp_parameters_init(curr_stream);
9558 if (err != IA_CSS_SUCCESS)
9560 IA_CSS_LOG("isp_params_configs: %p", curr_stream->isp_params_configs);
9562 if (num_pipes == 1 && pipes[0]->config.mode == IA_CSS_PIPE_MODE_ACC)
9564 *stream = curr_stream;
9565 err = ia_css_acc_stream_create(curr_stream);
9568 /* sensor binning */
9571 sensor_binning_changed =
9572 sh_css_params_set_binning_factor(curr_stream,
9573 curr_stream->config.sensor_binning_factor);
9576 sensor_binning_changed = false;
9579 IA_CSS_LOG("sensor_binning=%d, changed=%d",
9580 curr_stream->config.sensor_binning_factor, sensor_binning_changed);
9581 /* loop over pipes */
9582 IA_CSS_LOG("num_pipes=%d", num_pipes);
9583 curr_stream->cont_capt = false;
9584 /* Temporary hack: we give the preview pipe a reference to the capture
9585 * pipe in continuous capture mode. */
9586 if (curr_stream->config.continuous)
9588 /* Search for the preview pipe and create the copy pipe */
9589 struct ia_css_pipe *preview_pipe;
9590 struct ia_css_pipe *video_pipe;
9591 struct ia_css_pipe *acc_pipe;
9592 struct ia_css_pipe *capture_pipe = NULL;
9593 struct ia_css_pipe *copy_pipe = NULL;
9595 if (num_pipes >= 2) {
9596 curr_stream->cont_capt = true;
9597 curr_stream->disable_cont_vf = curr_stream->config.disable_cont_viewfinder;
9599 if (!atomisp_hw_is_isp2401)
9600 curr_stream->stop_copy_preview = my_css.stop_copy_preview;
9603 /* Create copy pipe here, since it may not be exposed to the driver */
9604 preview_pipe = find_pipe(pipes, num_pipes,
9605 IA_CSS_PIPE_MODE_PREVIEW, false);
9606 video_pipe = find_pipe(pipes, num_pipes,
9607 IA_CSS_PIPE_MODE_VIDEO, false);
9608 acc_pipe = find_pipe(pipes, num_pipes,
9609 IA_CSS_PIPE_MODE_ACC, false);
9610 if (acc_pipe && num_pipes == 2 && curr_stream->cont_capt == true)
9611 curr_stream->cont_capt =
9612 false; /* preview + QoS case will not need cont_capt switch */
9613 if (curr_stream->cont_capt == true) {
9614 capture_pipe = find_pipe(pipes, num_pipes,
9615 IA_CSS_PIPE_MODE_CAPTURE, false);
9616 if (!capture_pipe) {
9617 err = IA_CSS_ERR_INTERNAL_ERROR;
9621 /* We do not support preview and video pipe at the same time */
9622 if (preview_pipe && video_pipe) {
9623 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9627 if (preview_pipe && !preview_pipe->pipe_settings.preview.copy_pipe) {
9628 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9629 if (err != IA_CSS_SUCCESS)
9631 ia_css_pipe_config_defaults(©_pipe->config);
9632 preview_pipe->pipe_settings.preview.copy_pipe = copy_pipe;
9633 copy_pipe->stream = curr_stream;
9635 if (preview_pipe && (curr_stream->cont_capt == true)) {
9636 preview_pipe->pipe_settings.preview.capture_pipe = capture_pipe;
9638 if (video_pipe && !video_pipe->pipe_settings.video.copy_pipe) {
9639 err = create_pipe(IA_CSS_PIPE_MODE_CAPTURE, ©_pipe, true);
9640 if (err != IA_CSS_SUCCESS)
9642 ia_css_pipe_config_defaults(©_pipe->config);
9643 video_pipe->pipe_settings.video.copy_pipe = copy_pipe;
9644 copy_pipe->stream = curr_stream;
9646 if (video_pipe && (curr_stream->cont_capt == true)) {
9647 video_pipe->pipe_settings.video.capture_pipe = capture_pipe;
9649 if (preview_pipe && acc_pipe) {
9650 preview_pipe->pipe_settings.preview.acc_pipe = acc_pipe;
9653 for (i = 0; i < num_pipes; i++)
9655 curr_pipe = pipes[i];
9656 /* set current stream */
9657 curr_pipe->stream = curr_stream;
9659 if (!atomisp_hw_is_isp2401) {
9660 /* take over effective info */
9662 effective_res = curr_pipe->config.input_effective_res;
9663 err = ia_css_util_check_res(
9664 effective_res.width,
9665 effective_res.height);
9666 if (err != IA_CSS_SUCCESS)
9669 /* sensor binning per pipe */
9670 if (sensor_binning_changed)
9671 sh_css_pipe_free_shading_table(curr_pipe);
9674 /* now pipes have been configured, info should be available */
9675 for (i = 0; i < num_pipes; i++)
9677 struct ia_css_pipe_info *pipe_info = NULL;
9679 curr_pipe = pipes[i];
9681 err = sh_css_pipe_load_binaries(curr_pipe);
9682 if (err != IA_CSS_SUCCESS)
9685 /* handle each pipe */
9686 pipe_info = &curr_pipe->info;
9687 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9688 err = sh_css_pipe_get_output_frame_info(curr_pipe,
9689 &pipe_info->output_info[j], j);
9690 if (err != IA_CSS_SUCCESS)
9694 if (atomisp_hw_is_isp2401)
9695 pipe_info->output_system_in_res_info = curr_pipe->config.output_system_in_res;
9698 if (!atomisp_hw_is_isp2401)
9699 err = sh_css_pipe_get_shading_info(curr_pipe,
9700 &pipe_info->shading_info, NULL);
9702 err = sh_css_pipe_get_shading_info(curr_pipe,
9703 &pipe_info->shading_info, &curr_pipe->config);
9705 if (err != IA_CSS_SUCCESS)
9707 err = sh_css_pipe_get_grid_info(curr_pipe,
9708 &pipe_info->grid_info);
9709 if (err != IA_CSS_SUCCESS)
9711 for (j = 0; j < IA_CSS_PIPE_MAX_OUTPUT_STAGE; j++) {
9712 sh_css_pipe_get_viewfinder_frame_info(curr_pipe,
9713 &pipe_info->vf_output_info[j], j);
9714 if (err != IA_CSS_SUCCESS)
9719 my_css.active_pipes[ia_css_pipe_get_pipe_num(curr_pipe)] = curr_pipe;
9722 curr_stream->started = false;
9724 /* Map SP threads before doing anything. */
9725 err = map_sp_threads(curr_stream, true);
9726 if (err != IA_CSS_SUCCESS)
9728 IA_CSS_LOG("map_sp_threads: return_err=%d", err);
9732 for (i = 0; i < num_pipes; i++)
9734 curr_pipe = pipes[i];
9735 ia_css_pipe_map_queue(curr_pipe, true);
9738 /* Create host side pipeline objects without stages */
9739 err = create_host_pipeline_structure(curr_stream);
9740 if (err != IA_CSS_SUCCESS)
9742 IA_CSS_LOG("create_host_pipeline_structure: return_err=%d", err);
9746 /* assign curr_stream */
9747 *stream = curr_stream;
9750 if (err == IA_CSS_SUCCESS) {
9751 /* working mode: enter into the seed list */
9752 if (my_css_save.mode == sh_css_mode_working) {
9753 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9754 if (!my_css_save.stream_seeds[i].stream) {
9755 IA_CSS_LOG("entered stream into loc=%d", i);
9756 my_css_save.stream_seeds[i].orig_stream = stream;
9757 my_css_save.stream_seeds[i].stream = curr_stream;
9758 my_css_save.stream_seeds[i].num_pipes = num_pipes;
9759 my_css_save.stream_seeds[i].stream_config = *stream_config;
9760 for (j = 0; j < num_pipes; j++) {
9761 my_css_save.stream_seeds[i].pipe_config[j] = pipes[j]->config;
9762 my_css_save.stream_seeds[i].pipes[j] = pipes[j];
9763 my_css_save.stream_seeds[i].orig_pipes[j] = &pipes[j];
9769 ia_css_stream_destroy(curr_stream);
9772 ia_css_stream_destroy(curr_stream);
9774 IA_CSS_LEAVE("return_err=%d mode=%d", err, my_css_save.mode);
9779 ia_css_stream_destroy(struct ia_css_stream *stream) {
9781 enum ia_css_err err = IA_CSS_SUCCESS;
9783 IA_CSS_ENTER_PRIVATE("stream = %p", stream);
9786 err = IA_CSS_ERR_INVALID_ARGUMENTS;
9787 IA_CSS_LEAVE_ERR_PRIVATE(err);
9791 ia_css_stream_isp_parameters_uninit(stream);
9793 if ((stream->last_pipe) &&
9794 ia_css_pipeline_is_mapped(stream->last_pipe->pipe_num))
9796 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9799 for (i = 0; i < stream->num_pipes; i++) {
9800 struct ia_css_pipe *entry = stream->pipes[i];
9801 unsigned int sp_thread_id;
9802 struct sh_css_sp_pipeline_terminal *sp_pipeline_input_terminal;
9806 /* get the SP thread id */
9807 if (ia_css_pipeline_get_sp_thread_id(
9808 ia_css_pipe_get_pipe_num(entry), &sp_thread_id) != true)
9809 return IA_CSS_ERR_INTERNAL_ERROR;
9810 /* get the target input terminal */
9811 sp_pipeline_input_terminal =
9812 &sh_css_sp_group.pipe_io[sp_thread_id].input;
9814 for (i = 0; i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++) {
9815 ia_css_isys_stream_h isys_stream =
9816 &sp_pipeline_input_terminal->context.virtual_input_system_stream[i];
9817 if (stream->config.isys_config[i].valid && isys_stream->valid)
9818 ia_css_isys_stream_destroy(isys_stream);
9822 free_mpi = stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR;
9823 if (atomisp_hw_is_isp2401) {
9824 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_TPG;
9825 free_mpi |= stream->config.mode == IA_CSS_INPUT_MODE_PRBS;
9829 for (i = 0; i < stream->num_pipes; i++) {
9830 struct ia_css_pipe *entry = stream->pipes[i];
9831 /* free any mipi frames that are remaining:
9832 * some test stream create-destroy cycles do not generate output frames
9833 * and the mipi buffer is not freed in the deque function
9836 free_mipi_frames(entry);
9839 stream_unregister_with_csi_rx(stream);
9842 for (i = 0; i < stream->num_pipes; i++) {
9843 struct ia_css_pipe *curr_pipe = stream->pipes[i];
9846 ia_css_pipe_map_queue(curr_pipe, false);
9849 err = map_sp_threads(stream, false);
9850 if (err != IA_CSS_SUCCESS) {
9851 IA_CSS_LEAVE_ERR_PRIVATE(err);
9856 /* remove references from pipes to stream */
9857 for (i = 0; i < stream->num_pipes; i++)
9859 struct ia_css_pipe *entry = stream->pipes[i];
9863 /* clear reference to stream */
9864 entry->stream = NULL;
9865 /* check internal copy pipe */
9866 if (entry->mode == IA_CSS_PIPE_ID_PREVIEW &&
9867 entry->pipe_settings.preview.copy_pipe) {
9868 IA_CSS_LOG("clearing stream on internal preview copy pipe");
9869 entry->pipe_settings.preview.copy_pipe->stream = NULL;
9871 if (entry->mode == IA_CSS_PIPE_ID_VIDEO &&
9872 entry->pipe_settings.video.copy_pipe) {
9873 IA_CSS_LOG("clearing stream on internal video copy pipe");
9874 entry->pipe_settings.video.copy_pipe->stream = NULL;
9876 err = sh_css_pipe_unload_binaries(entry);
9879 /* free associated memory of stream struct */
9880 kfree(stream->pipes);
9881 stream->pipes = NULL;
9882 stream->num_pipes = 0;
9884 /* working mode: take out of the seed list */
9885 if (my_css_save.mode == sh_css_mode_working) {
9886 for (i = 0; i < MAX_ACTIVE_STREAMS; i++) {
9887 if (my_css_save.stream_seeds[i].stream == stream)
9889 IA_CSS_LOG("took out stream %d", i);
9890 my_css_save.stream_seeds[i].stream = NULL;
9897 IA_CSS_LEAVE_ERR(err);
9903 ia_css_stream_get_info(const struct ia_css_stream *stream,
9904 struct ia_css_stream_info *stream_info) {
9905 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_get_info: enter/exit\n");
9907 assert(stream_info);
9909 *stream_info = stream->info;
9910 return IA_CSS_SUCCESS;
9914 * Rebuild a stream, including allocating structs, setting configuration and
9915 * building the required pipes.
9916 * The data is taken from the css_save struct updated upon stream creation.
9917 * The stream handle is used to identify the correct entry in the css_save struct
9920 ia_css_stream_load(struct ia_css_stream *stream) {
9922 if (!atomisp_hw_is_isp2401) {
9924 enum ia_css_err err;
9927 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() enter,\n");
9928 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
9930 if (my_css_save.stream_seeds[i].stream == stream) {
9933 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++) {
9934 if ((err = ia_css_pipe_create(&my_css_save.stream_seeds[i].pipe_config[j],
9935 &my_css_save.stream_seeds[i].pipes[j])) != IA_CSS_SUCCESS) {
9939 for (k = 0; k < j; k++)
9940 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[k]);
9945 err = ia_css_stream_create(&my_css_save.stream_seeds[i].stream_config,
9946 my_css_save.stream_seeds[i].num_pipes,
9947 my_css_save.stream_seeds[i].pipes,
9948 &my_css_save.stream_seeds[i].stream);
9949 if (err != IA_CSS_SUCCESS) {
9950 ia_css_stream_destroy(stream);
9951 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
9952 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
9958 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_load() exit,\n");
9959 return IA_CSS_SUCCESS;
9961 /* TODO remove function - DEPRECATED */
9963 return IA_CSS_ERR_NOT_SUPPORTED;
9968 ia_css_stream_start(struct ia_css_stream *stream) {
9969 enum ia_css_err err = IA_CSS_SUCCESS;
9971 IA_CSS_ENTER("stream = %p", stream);
9972 if ((!stream) || (!stream->last_pipe))
9974 IA_CSS_LEAVE_ERR(IA_CSS_ERR_INVALID_ARGUMENTS);
9975 return IA_CSS_ERR_INVALID_ARGUMENTS;
9977 IA_CSS_LOG("starting %d", stream->last_pipe->mode);
9979 sh_css_sp_set_disable_continuous_viewfinder(stream->disable_cont_vf);
9981 /* Create host side pipeline. */
9982 err = create_host_pipeline(stream);
9983 if (err != IA_CSS_SUCCESS)
9985 IA_CSS_LEAVE_ERR(err);
9989 #if !defined(HAS_NO_INPUT_SYSTEM)
9990 #if defined(USE_INPUT_SYSTEM_VERSION_2401)
9991 if ((stream->config.mode == IA_CSS_INPUT_MODE_SENSOR) ||
9992 (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR))
9993 stream_register_with_csi_rx(stream);
9997 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
9998 /* Initialize mipi size checks */
9999 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10002 unsigned int port = (unsigned int)(stream->config.source.port.port);
10004 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10005 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] =
10006 sh_css_get_mipi_sizes_for_check(port, idx);
10011 #if !defined(HAS_NO_INPUT_SYSTEM)
10012 if (stream->config.mode != IA_CSS_INPUT_MODE_MEMORY)
10014 err = sh_css_config_input_network(stream);
10015 if (err != IA_CSS_SUCCESS)
10018 #endif /* !HAS_NO_INPUT_SYSTEM */
10020 err = sh_css_pipe_start(stream);
10021 IA_CSS_LEAVE_ERR(err);
10026 ia_css_stream_stop(struct ia_css_stream *stream) {
10027 enum ia_css_err err = IA_CSS_SUCCESS;
10029 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop() enter/exit\n");
10031 assert(stream->last_pipe);
10032 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_stop: stopping %d\n",
10033 stream->last_pipe->mode);
10035 #if !defined(HAS_NO_INPUT_SYSTEM) && defined(USE_INPUT_SYSTEM_VERSION_2)
10036 /* De-initialize mipi size checks */
10037 if (stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
10040 unsigned int port = (unsigned int)(stream->config.source.port.port);
10042 for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT; idx++) {
10043 sh_css_sp_group.config.mipi_sizes_for_check[port][idx] = 0;
10048 if (!atomisp_hw_is_isp2401) {
10049 err = ia_css_pipeline_request_stop(&stream->last_pipe->pipeline);
10051 err = sh_css_pipes_stop(stream);
10054 if (err != IA_CSS_SUCCESS)
10057 /* Ideally, unmapping should happen after pipeline_stop, but current
10058 * semantics do not allow that. */
10059 /* err = map_sp_threads(stream, false); */
10065 ia_css_stream_has_stopped(struct ia_css_stream *stream) {
10070 if (!atomisp_hw_is_isp2401) {
10071 stopped = ia_css_pipeline_has_stopped(&stream->last_pipe->pipeline);
10073 stopped = sh_css_pipes_have_stopped(stream);
10081 * Destroy the stream and all the pipes related to it.
10082 * The stream handle is used to identify the correct entry in the css_save struct
10085 ia_css_stream_unload(struct ia_css_stream *stream) {
10089 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() enter,\n");
10092 for (i = 0; i < MAX_ACTIVE_STREAMS; i++)
10093 if (my_css_save.stream_seeds[i].stream == stream)
10097 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10098 "ia_css_stream_unload(): unloading %d (%p)\n", i,
10099 my_css_save.stream_seeds[i].stream);
10100 ia_css_stream_destroy(stream);
10101 for (j = 0; j < my_css_save.stream_seeds[i].num_pipes; j++)
10102 ia_css_pipe_destroy(my_css_save.stream_seeds[i].pipes[j]);
10103 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE,
10104 "ia_css_stream_unload(): after unloading %d (%p)\n", i,
10105 my_css_save.stream_seeds[i].stream);
10108 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_stream_unload() exit,\n");
10109 return IA_CSS_SUCCESS;
10113 ia_css_temp_pipe_to_pipe_id(const struct ia_css_pipe *pipe,
10114 enum ia_css_pipe_id *pipe_id) {
10115 ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_temp_pipe_to_pipe_id() enter/exit\n");
10117 *pipe_id = pipe->mode;
10119 *pipe_id = IA_CSS_PIPE_ID_COPY;
10121 return IA_CSS_SUCCESS;
10124 enum atomisp_input_format
10125 ia_css_stream_get_format(const struct ia_css_stream *stream) {
10126 return stream->config.input_config.format;
10130 ia_css_stream_get_two_pixels_per_clock(const struct ia_css_stream *stream) {
10131 return (stream->config.pixels_per_clock == 2);
10134 struct ia_css_binary *
10135 ia_css_stream_get_shading_correction_binary(const struct ia_css_stream
10137 struct ia_css_pipe *pipe;
10141 pipe = stream->pipes[0];
10143 if (stream->num_pipes == 2) {
10144 assert(stream->pipes[1]);
10145 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10146 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10147 pipe = stream->pipes[1];
10150 return ia_css_pipe_get_shading_correction_binary(pipe);
10153 struct ia_css_binary *
10154 ia_css_stream_get_dvs_binary(const struct ia_css_stream *stream) {
10156 struct ia_css_pipe *video_pipe = NULL;
10158 /* First we find the video pipe */
10159 for (i = 0; i < stream->num_pipes; i++) {
10160 struct ia_css_pipe *pipe = stream->pipes[i];
10162 if (pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) {
10168 return &video_pipe->pipe_settings.video.video_binary;
10172 struct ia_css_binary *
10173 ia_css_stream_get_3a_binary(const struct ia_css_stream *stream) {
10174 struct ia_css_pipe *pipe;
10175 struct ia_css_binary *s3a_binary = NULL;
10179 pipe = stream->pipes[0];
10181 if (stream->num_pipes == 2) {
10182 assert(stream->pipes[1]);
10183 if (stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_VIDEO ||
10184 stream->pipes[1]->config.mode == IA_CSS_PIPE_MODE_PREVIEW)
10185 pipe = stream->pipes[1];
10188 s3a_binary = ia_css_pipe_get_s3a_binary(pipe);
10194 ia_css_stream_set_output_padded_width(struct ia_css_stream *stream,
10195 unsigned int output_padded_width) {
10196 struct ia_css_pipe *pipe;
10200 pipe = stream->last_pipe;
10204 /* set the config also just in case (redundant info? why do we save config in pipe?) */
10205 pipe->config.output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10206 pipe->output_info[IA_CSS_PIPE_OUTPUT_STAGE_0].padded_width = output_padded_width;
10208 return IA_CSS_SUCCESS;
10211 static struct ia_css_binary *
10212 ia_css_pipe_get_shading_correction_binary(const struct ia_css_pipe *pipe) {
10213 struct ia_css_binary *binary = NULL;
10217 switch (pipe->config.mode) {
10218 case IA_CSS_PIPE_MODE_PREVIEW:
10219 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10221 case IA_CSS_PIPE_MODE_VIDEO:
10222 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10224 case IA_CSS_PIPE_MODE_CAPTURE:
10225 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10228 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10229 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.sc) {
10230 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10234 } else if (pipe->config.default_capture_config.mode ==
10235 IA_CSS_CAPTURE_MODE_BAYER)
10236 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10237 else if (pipe->config.default_capture_config.mode ==
10238 IA_CSS_CAPTURE_MODE_ADVANCED ||
10239 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10240 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10241 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10242 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10243 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10250 if (binary && binary->info->sp.enable.sc)
10256 static struct ia_css_binary *
10257 ia_css_pipe_get_s3a_binary(const struct ia_css_pipe *pipe) {
10258 struct ia_css_binary *binary = NULL;
10262 switch (pipe->config.mode) {
10263 case IA_CSS_PIPE_MODE_PREVIEW:
10264 binary = (struct ia_css_binary *)&pipe->pipe_settings.preview.preview_binary;
10266 case IA_CSS_PIPE_MODE_VIDEO:
10267 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10269 case IA_CSS_PIPE_MODE_CAPTURE:
10270 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10273 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10274 if (pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10275 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.primary_binary[i];
10279 } else if (pipe->config.default_capture_config.mode ==
10280 IA_CSS_CAPTURE_MODE_BAYER)
10281 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10282 else if (pipe->config.default_capture_config.mode ==
10283 IA_CSS_CAPTURE_MODE_ADVANCED ||
10284 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT) {
10285 if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_1)
10286 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.pre_isp_binary;
10287 else if (pipe->config.isp_pipe_version == IA_CSS_PIPE_VERSION_2_2)
10288 binary = (struct ia_css_binary *)&pipe->pipe_settings.capture.post_isp_binary;
10297 if (binary && !binary->info->sp.enable.s3a)
10303 static struct ia_css_binary *
10304 ia_css_pipe_get_sdis_binary(const struct ia_css_pipe *pipe) {
10305 struct ia_css_binary *binary = NULL;
10309 switch (pipe->config.mode) {
10310 case IA_CSS_PIPE_MODE_VIDEO:
10311 binary = (struct ia_css_binary *)&pipe->pipe_settings.video.video_binary;
10317 if (binary && !binary->info->sp.enable.dis)
10323 struct ia_css_pipeline *
10324 ia_css_pipe_get_pipeline(const struct ia_css_pipe *pipe) {
10327 return (struct ia_css_pipeline *)&pipe->pipeline;
10331 ia_css_pipe_get_pipe_num(const struct ia_css_pipe *pipe) {
10334 /* KW was not sure this function was not returning a value
10335 that was out of range; so added an assert, and, for the
10336 case when asserts are not enabled, clip to the largest
10337 value; pipe_num is unsigned so the value cannot be too small
10339 assert(pipe->pipe_num < IA_CSS_PIPELINE_NUM_MAX);
10341 if (pipe->pipe_num >= IA_CSS_PIPELINE_NUM_MAX)
10342 return (IA_CSS_PIPELINE_NUM_MAX - 1);
10344 return pipe->pipe_num;
10348 ia_css_pipe_get_isp_pipe_version(const struct ia_css_pipe *pipe) {
10351 return (unsigned int)pipe->config.isp_pipe_version;
10354 #define SP_START_TIMEOUT_US 30000000
10357 ia_css_start_sp(void) {
10358 unsigned long timeout;
10359 enum ia_css_err err = IA_CSS_SUCCESS;
10362 sh_css_sp_start_isp();
10364 /* waiting for the SP is completely started */
10365 timeout = SP_START_TIMEOUT_US;
10366 while ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_INITIALIZED) && timeout)
10373 IA_CSS_ERROR("timeout during SP initialization");
10374 return IA_CSS_ERR_INTERNAL_ERROR;
10377 /* Workaround, in order to run two streams in parallel. See TASK 4271*/
10378 /* TODO: Fix this. */
10380 sh_css_init_host_sp_control_vars();
10382 /* buffers should be initialized only when sp is started */
10383 /* AM: At the moment it will be done only when there is no stream active. */
10385 sh_css_setup_queues();
10386 ia_css_bufq_dump_queue_info();
10388 IA_CSS_LEAVE_ERR(err);
10393 * Time to wait SP for termincate. Only condition when this can happen
10394 * is a fatal hw failure, but we must be able to detect this and emit
10395 * a proper error trace.
10397 #define SP_SHUTDOWN_TIMEOUT_US 200000
10400 ia_css_stop_sp(void) {
10401 unsigned long timeout;
10402 enum ia_css_err err = IA_CSS_SUCCESS;
10404 IA_CSS_ENTER("void");
10406 if (!sh_css_sp_is_running())
10408 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10409 IA_CSS_LEAVE("SP already stopped : return_err=%d", err);
10411 /* Return an error - stop SP should not have been called by driver */
10415 /* For now, stop whole SP */
10416 if (!atomisp_hw_is_isp2401) {
10417 sh_css_write_host2sp_command(host2sp_cmd_terminate);
10419 if (!sh_css_write_host2sp_command(host2sp_cmd_terminate))
10421 IA_CSS_ERROR("Call to 'sh-css_write_host2sp_command()' failed");
10422 ia_css_debug_dump_sp_sw_debug_info();
10423 ia_css_debug_dump_debug_info(NULL);
10427 sh_css_sp_set_sp_running(false);
10429 timeout = SP_SHUTDOWN_TIMEOUT_US;
10430 while (!ia_css_spctrl_is_idle(SP0_ID) && timeout)
10435 if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED))
10436 IA_CSS_WARNING("SP has not terminated (SW)");
10440 IA_CSS_WARNING("SP is not idle");
10441 ia_css_debug_dump_sp_sw_debug_info();
10443 timeout = SP_SHUTDOWN_TIMEOUT_US;
10444 while (!isp_ctrl_getbit(ISP0_ID, ISP_SC_REG, ISP_IDLE_BIT) && timeout)
10451 IA_CSS_WARNING("ISP is not idle");
10452 ia_css_debug_dump_sp_sw_debug_info();
10455 sh_css_hmm_buffer_record_uninit();
10457 /* clear pending param sets from refcount */
10458 sh_css_param_clear_param_sets();
10460 IA_CSS_LEAVE_ERR(err);
10465 ia_css_update_continuous_frames(struct ia_css_stream *stream) {
10466 struct ia_css_pipe *pipe;
10469 ia_css_debug_dtrace(
10470 IA_CSS_DEBUG_TRACE,
10471 "sh_css_update_continuous_frames() enter:\n");
10475 ia_css_debug_dtrace(
10476 IA_CSS_DEBUG_TRACE,
10477 "sh_css_update_continuous_frames() leave: invalid stream, return_void\n");
10478 return IA_CSS_ERR_INVALID_ARGUMENTS;
10481 pipe = stream->continuous_pipe;
10483 for (i = stream->config.init_num_cont_raw_buf;
10484 i < stream->config.target_num_cont_raw_buf; i++)
10486 sh_css_update_host2sp_offline_frame(i,
10487 pipe->continuous_frames[i], pipe->cont_md_buffers[i]);
10489 sh_css_update_host2sp_cont_num_raw_frames
10490 (stream->config.target_num_cont_raw_buf, true);
10491 ia_css_debug_dtrace(
10492 IA_CSS_DEBUG_TRACE,
10493 "sh_css_update_continuous_frames() leave: return_void\n");
10495 return IA_CSS_SUCCESS;
10498 void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) {
10499 unsigned int thread_id;
10500 enum ia_css_pipe_id pipe_id;
10501 unsigned int pipe_num;
10502 bool need_input_queue;
10507 pipe_id = pipe->mode;
10508 pipe_num = pipe->pipe_num;
10510 ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id);
10512 #if defined(HAS_NO_INPUT_SYSTEM) || defined(USE_INPUT_SYSTEM_VERSION_2401)
10513 need_input_queue = true;
10515 need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY;
10518 /* map required buffer queues to resources */
10519 /* TODO: to be improved */
10520 if (pipe->mode == IA_CSS_PIPE_ID_PREVIEW) {
10521 if (need_input_queue)
10522 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10523 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10524 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10525 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10526 #if defined SH_CSS_ENABLE_METADATA
10527 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10529 if (pipe->pipe_settings.preview.preview_binary.info &&
10530 pipe->pipe_settings.preview.preview_binary.info->sp.enable.s3a)
10531 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10532 } else if (pipe->mode == IA_CSS_PIPE_ID_CAPTURE) {
10535 if (need_input_queue)
10536 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10537 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10538 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10539 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10540 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10541 #if defined SH_CSS_ENABLE_METADATA
10542 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10544 if (pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_PRIMARY) {
10545 for (i = 0; i < pipe->pipe_settings.capture.num_primary_stage; i++) {
10546 if (pipe->pipe_settings.capture.primary_binary[i].info &&
10547 pipe->pipe_settings.capture.primary_binary[i].info->sp.enable.s3a) {
10548 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10552 } else if (pipe->config.default_capture_config.mode ==
10553 IA_CSS_CAPTURE_MODE_ADVANCED ||
10554 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_LOW_LIGHT ||
10555 pipe->config.default_capture_config.mode == IA_CSS_CAPTURE_MODE_BAYER) {
10556 if (pipe->pipe_settings.capture.pre_isp_binary.info &&
10557 pipe->pipe_settings.capture.pre_isp_binary.info->sp.enable.s3a)
10558 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10560 } else if (pipe->mode == IA_CSS_PIPE_ID_VIDEO) {
10561 if (need_input_queue)
10562 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10563 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10564 if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0])
10565 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME, map);
10566 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10567 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10568 #if defined SH_CSS_ENABLE_METADATA
10569 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10571 if (pipe->pipe_settings.video.video_binary.info &&
10572 pipe->pipe_settings.video.video_binary.info->sp.enable.s3a)
10573 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_3A_STATISTICS, map);
10574 if (pipe->pipe_settings.video.video_binary.info &&
10575 (pipe->pipe_settings.video.video_binary.info->sp.enable.dis
10577 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_DIS_STATISTICS, map);
10578 } else if (pipe->mode == IA_CSS_PIPE_ID_COPY) {
10579 if (need_input_queue)
10580 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10581 if (!pipe->stream->config.continuous)
10582 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10583 #if defined SH_CSS_ENABLE_METADATA
10584 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10586 } else if (pipe->mode == IA_CSS_PIPE_ID_ACC) {
10587 if (need_input_queue)
10588 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10589 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, map);
10590 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10591 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PER_FRAME_PARAMETER_SET, map);
10592 #if defined SH_CSS_ENABLE_METADATA
10593 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10595 } else if (pipe->mode == IA_CSS_PIPE_ID_YUVPP) {
10598 for (idx = 0; idx < IA_CSS_PIPE_MAX_OUTPUT_STAGE; idx++) {
10599 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME + idx, map);
10600 if (pipe->enable_viewfinder[idx])
10601 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME + idx, map);
10603 if (need_input_queue)
10604 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_INPUT_FRAME, map);
10605 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_PARAMETER_SET, map);
10606 #if defined SH_CSS_ENABLE_METADATA
10607 ia_css_queue_map(thread_id, IA_CSS_BUFFER_TYPE_METADATA, map);
10613 #if CONFIG_ON_FRAME_ENQUEUE()
10614 static enum ia_css_err set_config_on_frame_enqueue(struct ia_css_frame_info
10615 *info, struct frame_data_wrapper *frame) {
10616 frame->config_on_frame_enqueue.padded_width = 0;
10618 /* currently we support configuration on frame enqueue only on YUV formats */
10619 /* on other formats the padded_width is zeroed for no configuration override */
10620 switch (info->format) {
10621 case IA_CSS_FRAME_FORMAT_YUV420:
10622 case IA_CSS_FRAME_FORMAT_NV12:
10623 if (info->padded_width > info->res.width) {
10624 frame->config_on_frame_enqueue.padded_width = info->padded_width;
10625 } else if ((info->padded_width < info->res.width) && (info->padded_width > 0)) {
10626 return IA_CSS_ERR_INVALID_ARGUMENTS;
10628 /* nothing to do if width == padded width or padded width is zeroed (the same) */
10634 return IA_CSS_SUCCESS;
10639 ia_css_unlock_raw_frame(struct ia_css_stream *stream, uint32_t exp_id) {
10640 enum ia_css_err ret;
10644 /* Only continuous streams have a tagger to which we can send the
10645 * unlock message. */
10646 if (!stream || !stream->config.continuous)
10648 IA_CSS_ERROR("invalid stream pointer");
10649 return IA_CSS_ERR_INVALID_ARGUMENTS;
10652 if (exp_id > IA_CSS_ISYS_MAX_EXPOSURE_ID ||
10653 exp_id < IA_CSS_ISYS_MIN_EXPOSURE_ID)
10655 IA_CSS_ERROR("invalid exposure ID: %d\n", exp_id);
10656 return IA_CSS_ERR_INVALID_ARGUMENTS;
10659 /* Send the event. Since we verified that the exp_id is valid,
10660 * we can safely assign it to an 8-bit argument here. */
10661 ret = ia_css_bufq_enqueue_psys_event(
10662 IA_CSS_PSYS_SW_EVENT_UNLOCK_RAW_BUFFER, exp_id, 0, 0);
10664 IA_CSS_LEAVE_ERR(ret);
10668 /* @brief Set the state (Enable or Disable) of the Extension stage in the
10672 ia_css_pipe_set_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10674 unsigned int thread_id;
10675 struct ia_css_pipeline_stage *stage;
10676 enum ia_css_err err = IA_CSS_SUCCESS;
10680 /* Parameter Check */
10681 if (!pipe || !pipe->stream)
10683 IA_CSS_ERROR("Invalid Pipe.");
10684 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10685 } else if (!(pipe->config.acc_extension))
10687 IA_CSS_ERROR("Invalid Pipe(No Extension Firmware)");
10688 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10689 } else if (!sh_css_sp_is_running())
10691 IA_CSS_ERROR("Leaving: queue unavailable.");
10692 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10695 /* Query the threadid and stage_num for the Extension firmware*/
10696 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10697 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10698 if (err == IA_CSS_SUCCESS) {
10699 /* Set the Extension State;. TODO: Add check for stage firmware.type (QOS)*/
10700 err = ia_css_bufq_enqueue_psys_event(
10701 (uint8_t)IA_CSS_PSYS_SW_EVENT_STAGE_ENABLE_DISABLE,
10702 (uint8_t)thread_id,
10703 (uint8_t)stage->stage_num,
10705 if (err == IA_CSS_SUCCESS) {
10707 SH_CSS_QOS_STAGE_ENABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10709 SH_CSS_QOS_STAGE_DISABLE(&sh_css_sp_group.pipe[thread_id], stage->stage_num);
10713 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, enable);
10717 /* @brief Get the state (Enable or Disable) of the Extension stage in the
10721 ia_css_pipe_get_qos_ext_state(struct ia_css_pipe *pipe, uint32_t fw_handle,
10723 struct ia_css_pipeline_stage *stage;
10724 unsigned int thread_id;
10725 enum ia_css_err err = IA_CSS_SUCCESS;
10729 /* Parameter Check */
10730 if (!pipe || !pipe->stream)
10732 IA_CSS_ERROR("Invalid Pipe.");
10733 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10734 } else if (!(pipe->config.acc_extension))
10736 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10737 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10738 } else if (!sh_css_sp_is_running())
10740 IA_CSS_ERROR("Leaving: queue unavailable.");
10741 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10744 /* Query the threadid and stage_num corresponding to the Extension firmware*/
10745 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10746 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10748 if (err == IA_CSS_SUCCESS) {
10749 /* Get the Extension State */
10750 *enable = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10751 stage->stage_num)) ? true : false;
10754 IA_CSS_LEAVE("err:%d handle:%u enable:%d", err, fw_handle, *enable);
10760 ia_css_pipe_update_qos_ext_mapped_arg(struct ia_css_pipe *pipe,
10761 uint32_t fw_handle,
10762 struct ia_css_isp_param_css_segments *css_seg,
10763 struct ia_css_isp_param_isp_segments *isp_seg) {
10764 unsigned int HIVE_ADDR_sp_group;
10765 static struct sh_css_sp_group sp_group;
10766 static struct sh_css_sp_stage sp_stage;
10767 static struct sh_css_isp_stage isp_stage;
10768 const struct ia_css_fw_info *fw;
10769 unsigned int thread_id;
10770 struct ia_css_pipeline_stage *stage;
10771 enum ia_css_err err = IA_CSS_SUCCESS;
10773 enum ia_css_isp_memories mem;
10778 fw = &sh_css_sp_fw;
10780 /* Parameter Check */
10781 if (!pipe || !pipe->stream)
10783 IA_CSS_ERROR("Invalid Pipe.");
10784 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10785 } else if (!(pipe->config.acc_extension))
10787 IA_CSS_ERROR("Invalid Pipe (No Extension Firmware).");
10788 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10789 } else if (!sh_css_sp_is_running())
10791 IA_CSS_ERROR("Leaving: queue unavailable.");
10792 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10795 /* Query the thread_id and stage_num corresponding to the Extension firmware */
10796 ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id);
10797 err = ia_css_pipeline_get_stage_from_fw(&pipe->pipeline, fw_handle, &stage);
10798 if (err == IA_CSS_SUCCESS) {
10799 /* Get the Extension State */
10800 enabled = (SH_CSS_QOS_STAGE_IS_ENABLED(&sh_css_sp_group.pipe[thread_id],
10801 stage->stage_num)) ? true : false;
10802 /* Update mapped arg only when extension stage is not enabled */
10804 IA_CSS_ERROR("Leaving: cannot update when stage is enabled.");
10805 err = IA_CSS_ERR_RESOURCE_NOT_AVAILABLE;
10807 stage_num = stage->stage_num;
10809 HIVE_ADDR_sp_group = fw->info.sp.group;
10810 sp_dmem_load(SP0_ID,
10811 (unsigned int)sp_address_of(sp_group),
10812 &sp_group, sizeof(struct sh_css_sp_group));
10813 hmm_load(sp_group.pipe[thread_id].sp_stage_addr[stage_num],
10814 &sp_stage, sizeof(struct sh_css_sp_stage));
10816 hmm_load(sp_stage.isp_stage_addr,
10817 &isp_stage, sizeof(struct sh_css_isp_stage));
10819 for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) {
10820 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address =
10821 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10822 isp_stage.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size =
10823 css_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10824 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].address
10826 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].address;
10827 isp_stage.binary_info.mem_initializers.params[IA_CSS_PARAM_CLASS_PARAM][mem].size
10829 isp_seg->params[IA_CSS_PARAM_CLASS_PARAM][mem].size;
10832 hmm_store(sp_stage.isp_stage_addr,
10833 &isp_stage, sizeof(struct sh_css_isp_stage));
10837 IA_CSS_LEAVE("err:%d handle:%u", err, fw_handle);
10841 #ifdef USE_INPUT_SYSTEM_VERSION_2401
10842 static enum ia_css_err
10843 aspect_ratio_crop_init(struct ia_css_stream *curr_stream,
10844 struct ia_css_pipe *pipes[],
10845 bool *do_crop_status) {
10846 enum ia_css_err err = IA_CSS_SUCCESS;
10848 struct ia_css_pipe *curr_pipe;
10851 if ((!curr_stream) ||
10852 (curr_stream->num_pipes == 0) ||
10856 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10857 IA_CSS_LEAVE_ERR(err);
10861 for (i = 0; i < curr_stream->num_pipes; i++)
10863 curr_pipe = pipes[i];
10864 pipe_mask |= (1 << curr_pipe->config.mode);
10868 (((pipe_mask & (1 << IA_CSS_PIPE_MODE_PREVIEW)) ||
10869 (pipe_mask & (1 << IA_CSS_PIPE_MODE_VIDEO))) &&
10870 (pipe_mask & (1 << IA_CSS_PIPE_MODE_CAPTURE)) &&
10871 curr_stream->config.continuous);
10872 return IA_CSS_SUCCESS;
10876 aspect_ratio_crop_check(bool enabled, struct ia_css_pipe *curr_pipe) {
10877 bool status = false;
10879 if ((curr_pipe) && enabled) {
10880 if ((curr_pipe->config.mode == IA_CSS_PIPE_MODE_PREVIEW) ||
10881 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_VIDEO) ||
10882 (curr_pipe->config.mode == IA_CSS_PIPE_MODE_CAPTURE))
10889 static enum ia_css_err
10890 aspect_ratio_crop(struct ia_css_pipe *curr_pipe,
10891 struct ia_css_resolution *effective_res) {
10892 enum ia_css_err err = IA_CSS_SUCCESS;
10893 struct ia_css_resolution crop_res;
10894 struct ia_css_resolution *in_res = NULL;
10895 struct ia_css_resolution *out_res = NULL;
10896 bool use_bds_output_info = false;
10897 bool use_vf_pp_in_res = false;
10898 bool use_capt_pp_in_res = false;
10900 if ((!curr_pipe) ||
10903 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10904 IA_CSS_LEAVE_ERR(err);
10908 if ((curr_pipe->config.mode != IA_CSS_PIPE_MODE_PREVIEW) &&
10909 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_VIDEO) &&
10910 (curr_pipe->config.mode != IA_CSS_PIPE_MODE_CAPTURE))
10912 err = IA_CSS_ERR_INVALID_ARGUMENTS;
10913 IA_CSS_LEAVE_ERR(err);
10917 use_bds_output_info =
10918 ((curr_pipe->bds_output_info.res.width != 0) &&
10919 (curr_pipe->bds_output_info.res.height != 0));
10922 ((curr_pipe->config.vf_pp_in_res.width != 0) &&
10923 (curr_pipe->config.vf_pp_in_res.height != 0));
10925 use_capt_pp_in_res =
10926 ((curr_pipe->config.capt_pp_in_res.width != 0) &&
10927 (curr_pipe->config.capt_pp_in_res.height != 0));
10929 in_res = &curr_pipe->stream->config.input_config.effective_res;
10930 out_res = &curr_pipe->output_info[0].res;
10932 switch (curr_pipe->config.mode)
10934 case IA_CSS_PIPE_MODE_PREVIEW:
10935 if (use_bds_output_info)
10936 out_res = &curr_pipe->bds_output_info.res;
10937 else if (use_vf_pp_in_res)
10938 out_res = &curr_pipe->config.vf_pp_in_res;
10940 case IA_CSS_PIPE_MODE_VIDEO:
10941 if (use_bds_output_info)
10942 out_res = &curr_pipe->bds_output_info.res;
10944 case IA_CSS_PIPE_MODE_CAPTURE:
10945 if (use_capt_pp_in_res)
10946 out_res = &curr_pipe->config.capt_pp_in_res;
10948 case IA_CSS_PIPE_MODE_ACC:
10949 case IA_CSS_PIPE_MODE_COPY:
10950 case IA_CSS_PIPE_MODE_YUVPP:
10952 IA_CSS_ERROR("aspect ratio cropping invalid args: mode[%d]\n",
10953 curr_pipe->config.mode);
10958 err = ia_css_frame_find_crop_resolution(in_res, out_res, &crop_res);
10959 if (err == IA_CSS_SUCCESS)
10961 *effective_res = crop_res;
10964 /* in case of error fallback to default
10965 * effective resolution from driver. */
10966 IA_CSS_LOG("ia_css_frame_find_crop_resolution() failed with err(%d)", err);
10973 sh_css_hmm_buffer_record_init(void) {
10976 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++)
10977 sh_css_hmm_buffer_record_reset(&hmm_buffer_record[i]);
10981 sh_css_hmm_buffer_record_uninit(void) {
10983 struct sh_css_hmm_buffer_record *buffer_record = NULL;
10985 buffer_record = &hmm_buffer_record[0];
10986 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
10987 if (buffer_record->in_use) {
10988 if (buffer_record->h_vbuf)
10989 ia_css_rmgr_rel_vbuf(hmm_buffer_pool, &buffer_record->h_vbuf);
10990 sh_css_hmm_buffer_record_reset(buffer_record);
10997 sh_css_hmm_buffer_record_reset(struct sh_css_hmm_buffer_record *buffer_record) {
10998 assert(buffer_record);
10999 buffer_record->in_use = false;
11000 buffer_record->type = IA_CSS_BUFFER_TYPE_INVALID;
11001 buffer_record->h_vbuf = NULL;
11002 buffer_record->kernel_ptr = 0;
11005 static struct sh_css_hmm_buffer_record
11006 *sh_css_hmm_buffer_record_acquire(struct ia_css_rmgr_vbuf_handle *h_vbuf,
11007 enum ia_css_buffer_type type,
11008 hrt_address kernel_ptr) {
11010 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11011 struct sh_css_hmm_buffer_record *out_buffer_record = NULL;
11014 assert((type > IA_CSS_BUFFER_TYPE_INVALID) &&
11015 (type < IA_CSS_NUM_DYNAMIC_BUFFER_TYPE));
11016 assert(kernel_ptr != 0);
11018 buffer_record = &hmm_buffer_record[0];
11019 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11020 if (!buffer_record->in_use) {
11021 buffer_record->in_use = true;
11022 buffer_record->type = type;
11023 buffer_record->h_vbuf = h_vbuf;
11024 buffer_record->kernel_ptr = kernel_ptr;
11025 out_buffer_record = buffer_record;
11031 return out_buffer_record;
11034 static struct sh_css_hmm_buffer_record
11035 *sh_css_hmm_buffer_record_validate(ia_css_ptr ddr_buffer_addr,
11036 enum ia_css_buffer_type type) {
11038 struct sh_css_hmm_buffer_record *buffer_record = NULL;
11039 bool found_record = false;
11041 buffer_record = &hmm_buffer_record[0];
11042 for (i = 0; i < MAX_HMM_BUFFER_NUM; i++) {
11043 if ((buffer_record->in_use) &&
11044 (buffer_record->type == type) &&
11045 (buffer_record->h_vbuf) &&
11046 (buffer_record->h_vbuf->vptr == ddr_buffer_addr)) {
11047 found_record = true;
11054 return buffer_record;